aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.idea/codeStyles/Project.xml9
-rw-r--r--.idea/jarRepositories.xml5
-rw-r--r--app/build.gradle15
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt41
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/TestModules.kt35
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt10
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt2
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt2
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt2
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt2
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt6
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt2
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt2
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/facebook/FbCookieTest.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt66
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt43
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt29
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt23
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt72
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt17
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt44
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt30
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt7
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt41
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt14
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt17
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/CacheDb.kt14
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt41
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt14
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt36
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/SearchParser.kt52
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt (renamed from app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt)47
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt14
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt36
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt34
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt19
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt97
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/kotlin/CoroutineUtils.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/OldPrefs.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/Prefs.kt82
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/BehaviourPrefs.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/CorePrefs.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/FeedPrefs.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/NotifPrefs.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ShowcasePrefs.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt23
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/BaseJobService.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt10
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt112
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt16
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt99
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt70
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt139
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt18
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt59
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt33
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt15
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt26
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt39
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt17
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt8
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt19
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt37
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt22
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/facebook/FbDomTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/facebook/FbRegexTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/facebook/parsers/FbParseTest.kt4
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/facebook/requests/FbFullImageTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/internal/Internal.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/kotlin/FlyweightTest.kt10
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/prefs/PrefsTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/BuildUtilsTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt44
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/JsoupCleanerTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/StringEscapeUtilsTest.kt2
-rw-r--r--app/src/test/kotlin/com/pitchedapps/frost/utils/UrlTests.kt2
-rw-r--r--build.gradle1
-rw-r--r--spotless.gradle2
102 files changed, 1292 insertions, 838 deletions
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index f9ad7a67..b0ef7bf4 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -6,15 +6,6 @@
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
</value>
</option>
- <option name="PACKAGES_IMPORT_LAYOUT">
- <value>
- <package name="" alias="false" withSubpackages="true" />
- <package name="java" alias="false" withSubpackages="true" />
- <package name="javax" alias="false" withSubpackages="true" />
- <package name="kotlin" alias="false" withSubpackages="true" />
- <package name="" alias="true" withSubpackages="true" />
- </value>
- </option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index eb2873e7..1e2d92c1 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -26,5 +26,10 @@
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
+ <remote-repository>
+ <option name="id" value="MavenRepo" />
+ <option name="name" value="MavenRepo" />
+ <option name="url" value="https://repo.maven.apache.org/maven2/" />
+ </remote-repository>
</component>
</project> \ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 357d21d4..1046d52f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,6 +2,7 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt'
+apply plugin: 'dagger.hilt.android.plugin'
//apply plugin: 'com.getkeepsafe.dexcount'
apply plugin: 'com.gladed.androidgitversion'
@@ -52,7 +53,7 @@ android {
testInstrumentationRunner "com.pitchedapps.frost.FrostTestRunner"
javaCompileOptions {
annotationProcessorOptions {
- arguments = ["room.schemaLocation": "$projectDir/src/schemas".toString()]
+ arguments += ["room.schemaLocation": "$projectDir/src/schemas".toString()]
}
}
}
@@ -270,10 +271,16 @@ dependencies {
implementation "androidx.biometric:biometric:${Versions.andxBiometric}"
- implementation kau.Dependencies.koin
testImplementation kau.Dependencies.koinTest
androidTestImplementation kau.Dependencies.koinTest
+ implementation kau.Dependencies.hilt
+ kapt kau.Dependencies.hiltCompiler
+ testImplementation kau.Dependencies.hiltTest
+ kaptTest kau.Dependencies.hiltCompiler
+ androidTestImplementation kau.Dependencies.hiltTest
+ kaptAndroidTest kau.Dependencies.hiltCompiler
+
implementation kau.Dependencies.coroutines
implementation "org.apache.commons:commons-text:${Versions.apacheCommonsText}"
@@ -313,6 +320,10 @@ dependencies {
}
+kapt {
+ correctErrorTypes true
+}
+
def kotlinResolutions = ['kotlin-reflect',
'kotlin-stdlib',
'kotlin-stdlib-jdk7',
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt
index 9d0caae6..2a834cc8 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/FrostTestApp.kt
@@ -19,22 +19,13 @@ package com.pitchedapps.frost
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
-import ca.allanwang.kau.kpref.KPrefFactory
-import ca.allanwang.kau.kpref.KPrefFactoryInMemory
-import com.pitchedapps.frost.db.FrostDatabase
-import com.pitchedapps.frost.facebook.FbCookie
-import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
+import dagger.hilt.android.testing.HiltTestApplication
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
-import org.koin.android.ext.koin.androidContext
-import org.koin.android.ext.koin.androidLogger
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
-import org.koin.core.context.startKoin
-import org.koin.core.module.Module
-import org.koin.dsl.module
class FrostTestRunner : AndroidJUnitRunner() {
override fun newApplication(
@@ -42,7 +33,7 @@ class FrostTestRunner : AndroidJUnitRunner() {
className: String?,
context: Context?
): Application {
- return super.newApplication(cl, FrostTestApp::class.java.name, context)
+ return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
@@ -58,31 +49,3 @@ class FrostTestRule : TestRule {
}
}
}
-
-class FrostTestApp : Application() {
-
- override fun onCreate() {
- super.onCreate()
- startKoin {
- androidLogger()
- androidContext(this@FrostTestApp)
- modules(
- listOf(
- FrostDatabase.module(),
- prefFactoryModule(),
- Prefs.module(),
- FbCookie.module(),
- ThemeProvider.module()
- )
- )
- }
- }
-
- companion object {
- fun prefFactoryModule(): Module = module {
- single<KPrefFactory> {
- KPrefFactoryInMemory
- }
- }
- }
-}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/TestModules.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/TestModules.kt
new file mode 100644
index 00000000..176db811
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/TestModules.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2021 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
+
+import ca.allanwang.kau.kpref.KPrefFactory
+import ca.allanwang.kau.kpref.KPrefFactoryInMemory
+import com.pitchedapps.frost.prefs.PrefFactoryModule
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.components.SingletonComponent
+import dagger.hilt.testing.TestInstallIn
+
+@Module
+@TestInstallIn(
+ components = [SingletonComponent::class],
+ replaces = [PrefFactoryModule::class]
+)
+object PrefFactoryTestModule {
+ @Provides
+ fun factory(): KPrefFactory = KPrefFactoryInMemory
+}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt
index a23cac0b..57441a62 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/activities/ImageActivityTest.kt
@@ -26,11 +26,6 @@ import com.pitchedapps.frost.utils.ARG_COOKIE
import com.pitchedapps.frost.utils.ARG_IMAGE_URL
import com.pitchedapps.frost.utils.ARG_TEXT
import com.pitchedapps.frost.utils.isIndirectImageUrl
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertNotNull
-import kotlin.test.assertNull
-import kotlin.test.assertTrue
import okhttp3.internal.closeQuietly
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
@@ -46,6 +41,11 @@ import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.rules.Timeout
import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
@RunWith(AndroidJUnit4::class)
class ImageActivityTest {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt
index c028e265..bae56e2f 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt
@@ -20,9 +20,9 @@ import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
-import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
abstract class BaseDbTest {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt
index 410f92b4..417c6678 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt
@@ -16,11 +16,11 @@
*/
package com.pitchedapps.frost.db
+import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
-import kotlinx.coroutines.runBlocking
class CacheDbTest : BaseDbTest() {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt
index 945ac5e6..327ead86 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt
@@ -16,10 +16,10 @@
*/
package com.pitchedapps.frost.db
+import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
-import kotlinx.coroutines.runBlocking
class CookieDbTest : BaseDbTest() {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt
index 6ba6e0b6..8da7c663 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt
@@ -21,8 +21,8 @@ import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
-import kotlin.test.Test
import org.junit.runner.RunWith
+import kotlin.test.Test
@RunWith(AndroidJUnit4::class)
class CookieMigrationTest {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt
index 79d7e8f5..49d18b31 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt
@@ -17,13 +17,13 @@
package com.pitchedapps.frost.db
import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+import org.koin.core.error.NoBeanDefFoundException
+import org.koin.test.KoinTest
import kotlin.reflect.KClass
import kotlin.reflect.full.functions
import kotlin.test.Test
import kotlin.test.assertTrue
-import org.junit.runner.RunWith
-import org.koin.core.error.NoBeanDefFoundException
-import org.koin.test.KoinTest
@RunWith(AndroidJUnit4::class)
class DatabaseTest : KoinTest {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt
index 39b9f513..c911ddf6 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt
@@ -18,9 +18,9 @@ package com.pitchedapps.frost.db
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.defaultTabs
+import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
-import kotlinx.coroutines.runBlocking
class GenericDbTest : BaseDbTest() {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt
index 60b6ee05..6fb01350 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt
@@ -19,11 +19,11 @@ package com.pitchedapps.frost.db
import com.pitchedapps.frost.services.NOTIF_CHANNEL_GENERAL
import com.pitchedapps.frost.services.NOTIF_CHANNEL_MESSAGES
import com.pitchedapps.frost.services.NotificationContent
+import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
-import kotlinx.coroutines.runBlocking
class NotificationDbTest : BaseDbTest() {
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/facebook/FbCookieTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/facebook/FbCookieTest.kt
index a39aa6d2..71391b5a 100644
--- a/app/src/androidTest/kotlin/com/pitchedapps/frost/facebook/FbCookieTest.kt
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/facebook/FbCookieTest.kt
@@ -17,8 +17,8 @@
package com.pitchedapps.frost.facebook
import android.webkit.CookieManager
-import kotlin.test.assertTrue
import org.junit.Test
+import kotlin.test.assertTrue
class FbCookieTest {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
index 100aeecb..1e2b438e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt
@@ -20,64 +20,48 @@ import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.util.Log
-import ca.allanwang.kau.kpref.KPrefFactory
-import ca.allanwang.kau.kpref.KPrefFactoryAndroid
import ca.allanwang.kau.logging.KL
import ca.allanwang.kau.utils.buildIsLollipopAndUp
-import com.pitchedapps.frost.db.FrostDatabase
-import com.pitchedapps.frost.facebook.FbCookie
+import com.pitchedapps.frost.db.CookieDao
+import com.pitchedapps.frost.db.NotificationDao
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.services.scheduleNotificationsFromPrefs
import com.pitchedapps.frost.services.setupNotificationChannels
import com.pitchedapps.frost.utils.FrostPglAdBlock
import com.pitchedapps.frost.utils.L
+import dagger.hilt.android.HiltAndroidApp
import java.util.Random
-import org.koin.android.ext.koin.androidContext
-import org.koin.android.ext.koin.androidLogger
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.get
-import org.koin.core.context.startKoin
-import org.koin.core.module.Module
-import org.koin.dsl.module
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-28.
*/
-class FrostApp : Application(), KoinComponent {
+@HiltAndroidApp
+class FrostApp : Application() {
- private lateinit var prefs: Prefs
- private lateinit var themeProvider: ThemeProvider
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var cookieDao: CookieDao
+
+ @Inject
+ lateinit var notifDao: NotificationDao
override fun onCreate() {
- startKoin {
- if (BuildConfig.DEBUG) {
- androidLogger()
- }
- androidContext(this@FrostApp)
- modules(
- listOf(
- FrostDatabase.module(),
- prefFactoryModule(),
- Prefs.module(),
- FbCookie.module(),
- ThemeProvider.module()
- )
- )
- }
- if (!buildIsLollipopAndUp) { // not supported
- super.onCreate()
- return
- }
- prefs = get()
- themeProvider = get()
+ super.onCreate()
+
+ if (!buildIsLollipopAndUp) return // not supported
+
initPrefs()
L.i { "Begin Frost for Facebook" }
FrostPglAdBlock.init(this)
- super.onCreate()
-
setupNotificationChannels(this, themeProvider)
scheduleNotificationsFromPrefs(prefs)
@@ -122,12 +106,4 @@ class FrostApp : Application(), KoinComponent {
}
prefs.lastLaunch = System.currentTimeMillis()
}
-
- companion object {
- fun prefFactoryModule(): Module = module {
- single<KPrefFactory> {
- KPrefFactoryAndroid(get())
- }
- }
- }
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt
index 3248eb14..9a952932 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt
@@ -44,20 +44,31 @@ import com.pitchedapps.frost.utils.EXTRA_COOKIES
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.loadAssets
-import java.util.ArrayList
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
-import org.koin.android.ext.android.inject
+import java.util.ArrayList
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-28.
*/
+@AndroidEntryPoint
class StartActivity : KauBaseActivity() {
- private val fbCookie: FbCookie by inject()
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
- private val cookieDao: CookieDao by inject()
- private val genericDao: GenericDao by inject()
+ @Inject
+ lateinit var fbCookie: FbCookie
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var cookieDao: CookieDao
+
+ @Inject
+ lateinit var genericDao: GenericDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -82,10 +93,12 @@ class StartActivity : KauBaseActivity() {
val cookies = ArrayList(cookieDao.selectAll())
L.i { "Cookies loaded at time ${System.currentTimeMillis()}" }
L._d {
- "Cookies: ${cookies.joinToString(
+ "Cookies: ${
+ cookies.joinToString(
"\t",
transform = CookieEntity::toSensitiveString
- )}"
+ )
+ }"
}
loadAssets(themeProvider)
authDefer.await()
@@ -93,11 +106,13 @@ class StartActivity : KauBaseActivity() {
cookies.isEmpty() -> launchNewTask<LoginActivity>()
// Has cookies but no selected account
prefs.userId == -1L -> launchNewTask<SelectorActivity>(cookies)
- else -> startActivity<MainActivity>(intentBuilder = {
- putParcelableArrayListExtra(EXTRA_COOKIES, cookies)
- flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or
- Intent.FLAG_ACTIVITY_SINGLE_TOP
- })
+ else -> startActivity<MainActivity>(
+ intentBuilder = {
+ putParcelableArrayListExtra(EXTRA_COOKIES, cookies)
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or
+ Intent.FLAG_ACTIVITY_SINGLE_TOP
+ }
+ )
}
} catch (e: Exception) {
L._e(e) { "Load start failed" }
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 74d876cb..bbf8f812 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt
@@ -50,16 +50,20 @@ import com.pitchedapps.frost.R
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
-import org.koin.android.ext.android.inject
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-26.
*/
+@AndroidEntryPoint
class AboutActivity : AboutActivityBase(null) {
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
override fun Configs.buildConfigs() {
textColor = themeProvider.textColor
@@ -144,7 +148,8 @@ class AboutActivity : AboutActivityBase(null) {
}
}
- class AboutLinks : AbstractItem<AboutLinks.ViewHolder>(),
+ class AboutLinks :
+ AbstractItem<AboutLinks.ViewHolder>(),
ThemableIItem by ThemableIItemDelegate() {
override fun getViewHolder(v: View): ViewHolder = ViewHolder(v)
@@ -186,12 +191,14 @@ class AboutActivity : AboutActivityBase(null) {
)
images =
- (icons.map { (icon, onClick) -> c.drawable(icon) to onClick } + iicons.map { (icon, onClick) ->
- icon.toDrawable(
- c,
- 32
- ) to onClick
- }).mapIndexed { i, (icon, onClick) ->
+ (
+ 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
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
index 0553086c..36e44936 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
@@ -24,18 +24,27 @@ import com.pitchedapps.frost.contracts.VideoViewHolder
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
-import com.pitchedapps.frost.utils.setFrostTheme
-import org.koin.android.ext.android.inject
-import org.koin.core.component.inject
+import com.pitchedapps.frost.utils.ActivityThemer
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-12.
*/
+@AndroidEntryPoint
abstract class BaseActivity : KauBaseActivity() {
- val fbCookie: FbCookie by inject()
- val prefs: Prefs by inject()
- val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var fbCookie: FbCookie
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var activityThemer: ActivityThemer
/**
* Inherited consumer to customize back press
@@ -51,7 +60,7 @@ abstract class BaseActivity : KauBaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- if (this !is WebOverlayActivityBase) setFrostTheme(themeProvider)
+ if (this !is WebOverlayActivityBase) activityThemer.setFrostTheme()
}
override fun onStop() {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
index 394969cb..19e54f68 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
@@ -122,16 +122,22 @@ import com.pitchedapps.frost.utils.frostNavigationBar
import com.pitchedapps.frost.utils.launchLogin
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.launchWebOverlay
-import com.pitchedapps.frost.utils.setFrostColors
import com.pitchedapps.frost.utils.urlEncode
import com.pitchedapps.frost.views.BadgedIcon
import com.pitchedapps.frost.views.FrostVideoViewer
import com.pitchedapps.frost.views.FrostViewPager
import com.pitchedapps.frost.widgets.NotificationWidget
-import kotlin.math.abs
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.AndroidEntryPoint
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.qualifiers.ActivityContext
+import dagger.hilt.android.scopes.ActivityScoped
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
+import kotlin.math.abs
/**
* Created by Allan Wang on 20/12/17.
@@ -139,9 +145,13 @@ import org.koin.android.ext.android.inject
* Most of the logic that is unrelated to handling fragments
*/
@UseExperimental(ExperimentalCoroutinesApi::class)
-abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
+@AndroidEntryPoint
+abstract class BaseMainActivity :
+ BaseActivity(),
+ MainActivityContract,
FileChooserContract by FileChooserDelegate(),
- VideoViewHolder, SearchViewHolder {
+ VideoViewHolder,
+ SearchViewHolder {
/**
* Note that tabs themselves are initialized through a coroutine during onCreate
@@ -150,8 +160,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
override val frameWrapper: FrameLayout get() = drawerWrapperBinding.mainContainer
lateinit var drawerWrapperBinding: ActivityMainDrawerWrapperBinding
lateinit var contentBinding: ActivityMainContentBinding
- val cookieDao: CookieDao by inject()
- val genericDao: GenericDao by inject()
+
+ @Inject
+ lateinit var cookieDao: CookieDao
+
+ @Inject
+ lateinit var genericDao: GenericDao
interface ActivityMainContentBinding {
val root: View
@@ -179,6 +193,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
contentBinding = when (prefs.mainActivityLayout) {
MainActivityLayout.TOP_BAR -> {
val binding = ActivityMainBinding.inflate(layoutInflater)
+ @SuppressLint("StaticFieldLeak")
object : ActivityMainContentBinding {
override val root: View = binding.root
override val toolbar: Toolbar = binding.toolbar
@@ -190,6 +205,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
}
MainActivityLayout.BOTTOM_BAR -> {
val binding = ActivityMainBottomTabsBinding.inflate(layoutInflater)
+ @SuppressLint("StaticFieldLeak")
object : ActivityMainContentBinding {
override val root: View = binding.root
override val toolbar: Toolbar = binding.toolbar
@@ -202,7 +218,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
}
drawerWrapperBinding.mainContainer.addView(contentBinding.root)
with(contentBinding) {
- setFrostColors {
+ activityThemer.setFrostColors {
toolbar(toolbar)
themeWindow = false
header(appbar)
@@ -333,15 +349,17 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
shouldShow = false
fab.backgroundTintList = ColorStateList.valueOf(themeProvider.headerColor.withMinAlpha(200))
fab.hide()
- appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
- if (!hasFab) return@OnOffsetChangedListener
- val percent = abs(verticalOffset.toFloat() / appBarLayout.totalScrollRange)
- val shouldShow = percent < 0.2
- if (this@BaseMainActivity.shouldShow != shouldShow) {
- this@BaseMainActivity.shouldShow = shouldShow
- fab.showIf(shouldShow)
+ appbar.addOnOffsetChangedListener(
+ AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
+ if (!hasFab) return@OnOffsetChangedListener
+ val percent = abs(verticalOffset.toFloat() / appBarLayout.totalScrollRange)
+ val shouldShow = percent < 0.2
+ if (this@BaseMainActivity.shouldShow != shouldShow) {
+ this@BaseMainActivity.shouldShow = shouldShow
+ fab.showIf(shouldShow)
+ }
}
- })
+ )
}
override fun showFab(iicon: IIcon, clickEvent: () -> Unit) {
@@ -843,11 +861,13 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
this@SectionsPagerAdapter.pages.forEachIndexed { index, fbItem ->
tabs.addTab(
tabs.newTab()
- .setCustomView(BadgedIcon(this@BaseMainActivity).apply {
- iicon = fbItem.icon
- }.also {
- it.setAllAlpha(if (index == 0) SELECTED_TAB_ALPHA else UNSELECTED_TAB_ALPHA)
- })
+ .setCustomView(
+ BadgedIcon(this@BaseMainActivity).apply {
+ iicon = fbItem.icon
+ }.also {
+ it.setAllAlpha(if (index == 0) SELECTED_TAB_ALPHA else UNSELECTED_TAB_ALPHA)
+ }
+ )
)
}
lastPosition = 0
@@ -921,3 +941,13 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
const val UNSELECTED_TAB_ALPHA = 128f
}
}
+
+@Module
+@InstallIn(ActivityComponent::class)
+object MainActivityModule {
+ @Provides
+ @ActivityScoped
+ fun contract(@ActivityContext context: Context): MainActivityContract =
+ (context as? BaseMainActivity)
+ ?: throw IllegalArgumentException("${context::class.java.simpleName} does not implement MainActivityContract")
+}
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 935b88c9..4d2af123 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt
@@ -31,19 +31,20 @@ import com.pitchedapps.frost.databinding.ActivityDebugBinding
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.injectors.JsActions
import com.pitchedapps.frost.injectors.ThemeProvider
+import com.pitchedapps.frost.utils.ActivityThemer
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.createFreshDir
-import com.pitchedapps.frost.utils.setFrostColors
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.CoroutineExceptionHandler
import java.io.File
+import javax.inject.Inject
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
-import kotlinx.coroutines.CoroutineExceptionHandler
-import org.koin.android.ext.android.inject
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 05/01/18.
*/
+@AndroidEntryPoint
class DebugActivity : KauBaseActivity() {
companion object {
@@ -53,7 +54,11 @@ class DebugActivity : KauBaseActivity() {
fun baseDir(context: Context) = File(context.externalCacheDir, "offline_debug")
}
- private val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var activityThemer: ActivityThemer
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
lateinit var binding: ActivityDebugBinding
@@ -72,7 +77,7 @@ class DebugActivity : KauBaseActivity() {
}
setTitle(R.string.debug_frost)
- setFrostColors {
+ activityThemer.setFrostColors {
toolbar(toolbar)
}
debugWebview.loadUrl(FbItem.FEED.url)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
index 7b8ee4d3..c5b8bdaa 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
@@ -61,33 +61,40 @@ import com.pitchedapps.frost.services.LocalService
import com.pitchedapps.frost.utils.ARG_COOKIE
import com.pitchedapps.frost.utils.ARG_IMAGE_URL
import com.pitchedapps.frost.utils.ARG_TEXT
+import com.pitchedapps.frost.utils.ActivityThemer
import com.pitchedapps.frost.utils.frostDownload
import com.pitchedapps.frost.utils.frostSnackbar
import com.pitchedapps.frost.utils.frostUriFromFile
import com.pitchedapps.frost.utils.isIndirectImageUrl
import com.pitchedapps.frost.utils.logFrostEvent
-import com.pitchedapps.frost.utils.setFrostColors
-import java.io.File
-import java.io.FileNotFoundException
-import java.io.IOException
-import kotlin.math.abs
-import kotlin.math.max
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.koin.android.ext.android.inject
-import org.koin.core.component.inject
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.IOException
+import javax.inject.Inject
+import kotlin.math.abs
+import kotlin.math.max
/**
* Created by Allan Wang on 2017-07-15.
*/
+@AndroidEntryPoint
class ImageActivity : KauBaseActivity() {
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var activityThemer: ActivityThemer
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
@Volatile
internal var errorRef: Throwable? = null
@@ -219,12 +226,12 @@ class ImageActivity : KauBaseActivity() {
setState(FabStates.SHARE)
}
imagePhoto.setOnImageEventListener(object :
- SubsamplingScaleImageView.DefaultOnImageEventListener() {
- override fun onImageLoadError(e: Exception) {
- loadError(e)
- }
- })
- setFrostColors {
+ SubsamplingScaleImageView.DefaultOnImageEventListener() {
+ override fun onImageLoadError(e: Exception) {
+ loadError(e)
+ }
+ })
+ activityThemer.setFrostColors {
themeWindow = false
}
dragHelper = ViewDragHelper.create(imageDrag, ViewDragCallback()).apply {
@@ -394,7 +401,7 @@ internal enum class FabStates(
} catch (e: Exception) {
activity.errorRef = e
e.logFrostEvent("Image share failed")
- activity.frostSnackbar(R.string.image_share_failed)
+ activity.frostSnackbar(R.string.image_share_failed, activity.themeProvider)
}
}
};
@@ -409,7 +416,8 @@ internal enum class FabStates(
*
*/
fun update(fab: FloatingActionButton, themeProvider: ThemeProvider) {
- val tint = if (backgroundTint != Int.MAX_VALUE) backgroundTint else themeProvider.accentColor
+ val tint =
+ if (backgroundTint != Int.MAX_VALUE) backgroundTint else themeProvider.accentColor
val iconColor = iconColorProvider(themeProvider)
if (fab.isHidden) {
fab.setIcon(iicon, color = iconColor)
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 f06c3a37..817eebe1 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt
@@ -48,14 +48,15 @@ import com.pitchedapps.frost.intro.IntroFragmentWelcome
import com.pitchedapps.frost.intro.IntroTabContextFragment
import com.pitchedapps.frost.intro.IntroTabTouchFragment
import com.pitchedapps.frost.prefs.Prefs
+import com.pitchedapps.frost.utils.ActivityThemer
import com.pitchedapps.frost.utils.cookies
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.loadAssets
-import com.pitchedapps.frost.utils.setFrostTheme
import com.pitchedapps.frost.widgets.NotificationWidget
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-07-25.
@@ -63,11 +64,21 @@ import org.koin.android.ext.android.inject
* A beautiful intro activity
* Phone showcases are drawn via layers
*/
-class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer,
+@AndroidEntryPoint
+class IntroActivity :
+ KauBaseActivity(),
+ ViewPager.PageTransformer,
ViewPager.OnPageChangeListener {
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var activityThemer: ActivityThemer
+
lateinit var binding: ActivityIntroBinding
private var barHasNext = true
@@ -114,7 +125,7 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer,
indicator.invalidate()
}
fragments.forEach { it.themeFragment() }
- setFrostTheme(themeProvider, true)
+ activityThemer.setFrostTheme(forceTransparent = true)
}
/**
@@ -157,7 +168,12 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer,
if (f != null)
ValueAnimator.ofFloat(0f, 1f).apply {
addUpdateListener {
- f.setTint(themeProvider.textColor.blendWith(Color.WHITE, it.animatedValue as Float))
+ f.setTint(
+ themeProvider.textColor.blendWith(
+ Color.WHITE,
+ it.animatedValue as Float
+ )
+ )
}
duration = 600
start()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
index 5cbbfafe..949f1ddd 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
@@ -45,11 +45,9 @@ import com.pitchedapps.frost.utils.frostEvent
import com.pitchedapps.frost.utils.frostJsoup
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.logFrostEvent
-import com.pitchedapps.frost.utils.setFrostColors
import com.pitchedapps.frost.utils.uniqueOnly
import com.pitchedapps.frost.web.LoginWebView
-import java.net.UnknownHostException
-import kotlin.coroutines.resume
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.channels.Channel
@@ -58,19 +56,24 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
-import org.koin.android.ext.android.inject
+import java.net.UnknownHostException
+import javax.inject.Inject
+import kotlin.coroutines.resume
/**
* Created by Allan Wang on 2017-06-01.
*/
+@AndroidEntryPoint
class LoginActivity : BaseActivity() {
+ @Inject
+ lateinit var cookieDao: CookieDao
+
private val toolbar: Toolbar by bindView(R.id.toolbar)
private val web: LoginWebView by bindView(R.id.login_webview)
private val swipeRefresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
private val textview: AppCompatTextView by bindView(R.id.textview)
private val profile: ImageView by bindView(R.id.profile)
- private val cookieDao: CookieDao by inject()
private lateinit var profileLoader: RequestManager
private val refreshChannel = Channel<Boolean>(10)
@@ -80,7 +83,7 @@ class LoginActivity : BaseActivity() {
setContentView(R.layout.activity_login)
setSupportActionBar(toolbar)
setTitle(R.string.kau_login)
- setFrostColors {
+ activityThemer.setFrostColors {
toolbar(toolbar)
}
profileLoader = GlideApp.with(profile)
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 33215c7e..a891c7c9 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt
@@ -29,7 +29,6 @@ import com.mikepenz.fastadapter.listeners.ClickEventHook
import com.pitchedapps.frost.R
import com.pitchedapps.frost.utils.cookies
import com.pitchedapps.frost.utils.launchNewTask
-import com.pitchedapps.frost.utils.setFrostColors
import com.pitchedapps.frost.views.AccountItem
import kotlinx.coroutines.launch
@@ -48,8 +47,8 @@ class SelectorActivity : BaseActivity() {
setContentView(R.layout.activity_selector)
recycler.layoutManager = GridLayoutManager(this, 2)
recycler.adapter = adapter
- adapter.add(cookies().map { AccountItem(it) })
- adapter.add(AccountItem(null)) // add account
+ adapter.add(cookies().map { AccountItem(it, themeProvider) })
+ adapter.add(AccountItem(null, themeProvider)) // add account
adapter.addEventHook(object : ClickEventHook<AccountItem>() {
override fun onBind(viewHolder: RecyclerView.ViewHolder): View? =
(viewHolder as? AccountItem.ViewHolder)?.itemView
@@ -67,7 +66,7 @@ class SelectorActivity : BaseActivity() {
}
}
})
- setFrostColors {
+ activityThemer.setFrostColors {
text(text)
background(container)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
index 9ce16ec7..bce3aa48 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
@@ -49,6 +49,7 @@ import com.pitchedapps.frost.settings.getFeedPrefs
import com.pitchedapps.frost.settings.getNotificationPrefs
import com.pitchedapps.frost.settings.getSecurityPrefs
import com.pitchedapps.frost.settings.sendDebug
+import com.pitchedapps.frost.utils.ActivityThemer
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.REQUEST_REFRESH
import com.pitchedapps.frost.utils.REQUEST_RESTART
@@ -57,20 +58,31 @@ import com.pitchedapps.frost.utils.frostChangelog
import com.pitchedapps.frost.utils.frostNavigationBar
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.loadAssets
-import com.pitchedapps.frost.utils.setFrostTheme
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-06.
*/
+@AndroidEntryPoint
class SettingsActivity : KPrefActivity() {
- val fbCookie: FbCookie by inject()
- val notifDao: NotificationDao by inject()
- val prefs: Prefs by inject()
- val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var fbCookie: FbCookie
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var notifDao: NotificationDao
+
+ @Inject
+ lateinit var activityThemer: ActivityThemer
private var resultFlag = Activity.RESULT_CANCELED
@@ -175,9 +187,12 @@ class SettingsActivity : KPrefActivity() {
descRes = R.string.about_frost_desc
iicon = GoogleMaterial.Icon.gmd_info
onClick = {
- startActivityForResult<AboutActivity>(9, bundleBuilder = {
- withSceneTransitionAnimation(this@SettingsActivity)
- })
+ startActivityForResult<AboutActivity>(
+ 9,
+ bundleBuilder = {
+ withSceneTransitionAnimation(this@SettingsActivity)
+ }
+ )
}
}
@@ -218,7 +233,7 @@ class SettingsActivity : KPrefActivity() {
@SuppressLint("MissingSuperCall")
override fun onCreate(savedInstanceState: Bundle?) {
- setFrostTheme(themeProvider, true)
+ activityThemer.setFrostTheme(forceTransparent = true)
super.onCreate(savedInstanceState)
animate = prefs.animate
themeExterior(false)
@@ -227,7 +242,11 @@ class SettingsActivity : KPrefActivity() {
fun themeExterior(animate: Boolean = true) {
if (animate) bgCanvas.fade(themeProvider.bgColor)
else bgCanvas.set(themeProvider.bgColor)
- if (animate) toolbarCanvas.ripple(themeProvider.headerColor, RippleCanvas.MIDDLE, RippleCanvas.END)
+ if (animate) toolbarCanvas.ripple(
+ themeProvider.headerColor,
+ RippleCanvas.MIDDLE,
+ RippleCanvas.END
+ )
else toolbarCanvas.set(themeProvider.headerColor)
frostNavigationBar(prefs, themeProvider)
}
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 f2827397..adf543df 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/TabCustomizerActivity.kt
@@ -42,18 +42,20 @@ import com.pitchedapps.frost.db.saveTabs
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.iitems.TabIItem
import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.setFrostColors
-import java.util.Collections
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
-import org.koin.android.ext.android.inject
+import java.util.Collections
+import javax.inject.Inject
/**
* Created by Allan Wang on 26/11/17.
*/
+@AndroidEntryPoint
class TabCustomizerActivity : BaseActivity() {
- private val genericDao: GenericDao by inject()
+ @Inject
+ lateinit var genericDao: GenericDao
private val adapter = FastItemAdapter<TabIItem>()
@@ -85,7 +87,7 @@ class TabCustomizerActivity : BaseActivity() {
val remaining = FbItem.values().filter { it.name[0] != '_' }.toMutableList()
remaining.removeAll(tabs)
tabs.addAll(remaining)
- adapter.set(tabs.map(::TabIItem))
+ adapter.set(tabs.map { TabIItem(it, themeProvider) })
bindSwapper(adapter, tabRecycler)
@@ -107,7 +109,7 @@ class TabCustomizerActivity : BaseActivity() {
fabCancel.setIcon(GoogleMaterial.Icon.gmd_close, themeProvider.iconColor)
fabCancel.backgroundTintList = ColorStateList.valueOf(themeProvider.accentColor)
fabCancel.setOnClickListener { finish() }
- setFrostColors {
+ activityThemer.setFrostColors {
themeWindow = true
}
}
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 42d84eb7..689d9a65 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
@@ -67,7 +67,6 @@ import com.pitchedapps.frost.utils.ARG_USER_ID
import com.pitchedapps.frost.utils.BiometricUtils
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.frostSnackbar
-import com.pitchedapps.frost.utils.setFrostColors
import com.pitchedapps.frost.views.FrostContentWeb
import com.pitchedapps.frost.views.FrostVideoViewer
import com.pitchedapps.frost.views.FrostWebView
@@ -156,9 +155,12 @@ class WebOverlayDesktopActivity : WebOverlayActivityBase(USER_AGENT_DESKTOP_CONS
class WebOverlayActivity : WebOverlayActivityBase()
@UseExperimental(ExperimentalCoroutinesApi::class)
-abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT) : BaseActivity(),
- ActivityContract, FrostContentContainer,
- VideoViewHolder, FileChooserContract by FileChooserDelegate() {
+abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT) :
+ BaseActivity(),
+ ActivityContract,
+ FrostContentContainer,
+ VideoViewHolder,
+ FileChooserContract by FileChooserDelegate() {
override val frameWrapper: FrameLayout by bindView(R.id.frame_wrapper)
val toolbar: Toolbar by bindView(R.id.overlay_toolbar)
@@ -202,10 +204,11 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
- toolbar.navigationIcon = GoogleMaterial.Icon.gmd_close.toDrawable(this, 16, themeProvider.iconColor)
+ toolbar.navigationIcon =
+ GoogleMaterial.Icon.gmd_close.toDrawable(this, 16, themeProvider.iconColor)
toolbar.setNavigationOnClickListener { finishSlideOut() }
- setFrostColors {
+ activityThemer.setFrostColors {
toolbar(toolbar)
themeWindow = false
}
@@ -228,7 +231,7 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT
authDefer.await()
reloadBase(true)
if (prefs.firstWebOverlay) {
- coordinator.frostSnackbar(R.string.web_overlay_swipe_hint) {
+ coordinator.frostSnackbar(R.string.web_overlay_swipe_hint, themeProvider) {
duration = BaseTransientBottomBar.LENGTH_INDEFINITE
setAction(R.string.kau_got_it) { dismiss() }
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/CacheDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/CacheDb.kt
index f0dacdc7..68d71a91 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/CacheDb.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/CacheDb.kt
@@ -36,12 +36,14 @@ import kotlinx.android.parcel.Parcelize
@Entity(
tableName = "frost_cache",
primaryKeys = ["id", "type"],
- foreignKeys = [ForeignKey(
- entity = CookieEntity::class,
- parentColumns = ["cookie_id"],
- childColumns = ["id"],
- onDelete = ForeignKey.CASCADE
- )]
+ foreignKeys = [
+ ForeignKey(
+ entity = CookieEntity::class,
+ parentColumns = ["cookie_id"],
+ childColumns = ["id"],
+ onDelete = ForeignKey.CASCADE
+ )
+ ]
)
@Parcelize
data class CacheEntity(
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 bd0b4ee0..ef763617 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
@@ -21,7 +21,12 @@ import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.pitchedapps.frost.BuildConfig
-import org.koin.dsl.module
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
interface FrostPrivateDao {
fun cookieDao(): CookieDao
@@ -91,13 +96,31 @@ class FrostDatabase(
).frostBuild()
return FrostDatabase(privateDb, publicDb)
}
-
- fun module() = module {
- single { create(get()) }
- single { get<FrostDatabase>().cookieDao() }
- single { get<FrostDatabase>().cacheDao() }
- single { get<FrostDatabase>().notifDao() }
- single { get<FrostDatabase>().genericDao() }
- }
}
}
+
+@Module
+@InstallIn(SingletonComponent::class)
+object DatabaseModule {
+
+ @Provides
+ @Singleton
+ fun frostDatabase(@ApplicationContext context: Context): FrostDatabase =
+ FrostDatabase.create(context)
+
+ @Provides
+ @Singleton
+ fun cookieDao(frostDatabase: FrostDatabase): CookieDao = frostDatabase.cookieDao()
+
+ @Provides
+ @Singleton
+ fun cacheDao(frostDatabase: FrostDatabase): CacheDao = frostDatabase.cacheDao()
+
+ @Provides
+ @Singleton
+ fun notifDao(frostDatabase: FrostDatabase): NotificationDao = frostDatabase.notifDao()
+
+ @Provides
+ @Singleton
+ fun genericDao(frostDatabase: FrostDatabase): GenericDao = frostDatabase.genericDao()
+}
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 93df01dc..f8f16e26 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/NotificationDb.kt
@@ -32,12 +32,14 @@ import com.pitchedapps.frost.utils.L
@Entity(
tableName = "notifications",
primaryKeys = ["notif_id", "userId"],
- foreignKeys = [ForeignKey(
- entity = CookieEntity::class,
- parentColumns = ["cookie_id"],
- childColumns = ["userId"],
- onDelete = ForeignKey.CASCADE
- )],
+ foreignKeys = [
+ ForeignKey(
+ entity = CookieEntity::class,
+ parentColumns = ["cookie_id"],
+ childColumns = ["userId"],
+ onDelete = ForeignKey.CASCADE
+ )
+ ],
indices = [Index("notif_id"), Index("userId")]
)
data class NotificationEntity(
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 18917bce..75a13295 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt
@@ -26,12 +26,6 @@ import com.pitchedapps.frost.utils.createFreshDir
import com.pitchedapps.frost.utils.createFreshFile
import com.pitchedapps.frost.utils.frostJsoup
import com.pitchedapps.frost.utils.unescapeHtml
-import java.io.File
-import java.io.FileOutputStream
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.atomic.AtomicInteger
-import java.util.zip.ZipEntry
-import java.util.zip.ZipOutputStream
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
@@ -43,6 +37,12 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.nodes.Entities
+import java.io.File
+import java.io.FileOutputStream
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.atomic.AtomicInteger
+import java.util.zip.ZipEntry
+import java.util.zip.ZipOutputStream
/**
* Created by Allan Wang on 04/01/18.
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt b/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt
index ec438df1..4a274b9b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/enums/MainActivityLayout.kt
@@ -28,13 +28,17 @@ enum class MainActivityLayout(
val iconColor: (ThemeProvider) -> Int
) {
- TOP_BAR(R.string.top_bar,
+ TOP_BAR(
+ R.string.top_bar,
{ it.headerColor },
- { it.iconColor }),
+ { it.iconColor }
+ ),
- BOTTOM_BAR(R.string.bottom_bar,
+ BOTTOM_BAR(
+ R.string.bottom_bar,
{ it.bgColor },
- { it.textColor });
+ { it.textColor }
+ );
companion object {
val values = values() // save one instance
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt b/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt
index 1c9d6aa5..fc6f6f9d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/enums/Theme.kt
@@ -39,53 +39,65 @@ enum class Theme(
val iconColorGetter: (ThemePrefs) -> Int
) {
- DEFAULT(R.string.kau_default,
+ DEFAULT(
+ R.string.kau_default,
"default",
{ 0xde000000.toInt() },
{ FACEBOOK_BLUE },
{ 0xfffafafa.toInt() },
{ FACEBOOK_BLUE },
- { Color.WHITE }),
+ { Color.WHITE }
+ ),
- LIGHT(R.string.kau_light,
+ LIGHT(
+ R.string.kau_light,
"material_light",
{ 0xde000000.toInt() },
{ FACEBOOK_BLUE },
{ 0xfffafafa.toInt() },
{ FACEBOOK_BLUE },
- { Color.WHITE }),
+ { Color.WHITE }
+ ),
- DARK(R.string.kau_dark,
+ DARK(
+ R.string.kau_dark,
"material_dark",
{ Color.WHITE },
{ BLUE_LIGHT },
{ 0xff303030.toInt() },
{ 0xff2e4b86.toInt() },
- { Color.WHITE }),
+ { Color.WHITE }
+ ),
- AMOLED(R.string.kau_amoled,
+ AMOLED(
+ R.string.kau_amoled,
"material_amoled",
{ Color.WHITE },
{ BLUE_LIGHT },
{ Color.BLACK },
{ Color.BLACK },
- { Color.WHITE }),
+ { Color.WHITE }
+ ),
- GLASS(R.string.kau_glass,
+ GLASS(
+ R.string.kau_glass,
"material_glass",
{ Color.WHITE },
{ BLUE_LIGHT },
{ 0x80000000.toInt() },
{ 0xb3000000.toInt() },
- { Color.WHITE }),
+ { Color.WHITE }
+ ),
- CUSTOM(R.string.kau_custom,
+ CUSTOM(
+ R.string.kau_custom,
"custom",
{ it.customTextColor },
{ it.customAccentColor },
{ it.customBackgroundColor },
{ it.customHeaderColor },
- { it.customIconColor });
+ { it.customIconColor }
+ );
@VisibleForTesting
internal val file = file?.let { "$it.css" }
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 4e932d09..ea1b0946 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
@@ -28,29 +28,28 @@ import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.cookies
import com.pitchedapps.frost.utils.launchLogin
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext
-import org.koin.dsl.module
+import javax.inject.Inject
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
/**
* Created by Allan Wang on 2017-05-30.
*
* The following component manages all cookie transfers.
*/
-class FbCookie(private val prefs: Prefs, private val cookieDao: CookieDao) {
+class FbCookie @Inject internal constructor(
+ private val prefs: Prefs,
+ private val cookieDao: CookieDao
+) {
companion object {
private const val FB_COOKIE_DOMAIN = HTTPS_FACEBOOK_COM
private const val MESSENGER_COOKIE_DOMAIN = HTTPS_MESSENGER_COM
-
- fun module() = module {
- single { FbCookie(get(), get()) }
- }
}
/**
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/SearchParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/SearchParser.kt
index 68c629a9..0c9a7e92 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/SearchParser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/parsers/SearchParser.kt
@@ -90,31 +90,33 @@ private class SearchParserImpl : FrostParserBase<FrostSearches>(false) {
?: doc.getElementById("root")
?: return null
- return FrostSearches(container.select("table[role=presentation]").mapNotNull { el ->
- // Our assumption is that search entries start with an image, followed by general info
- // There may be other <td />s, but we will not be parsing them
- // Furthermore, the <td /> entry wraps a link, containing all the necessary info
- val a = el.select("td")
- .getOrNull(1)
- ?.selectFirst("a")
- ?: return@mapNotNull null
- val url =
- a.attr("href").takeIf { it.isNotEmpty() }
- ?.formattedFbUrl?.formattedSearchUrl
+ return FrostSearches(
+ container.select("table[role=presentation]").mapNotNull { el ->
+ // Our assumption is that search entries start with an image, followed by general info
+ // There may be other <td />s, but we will not be parsing them
+ // Furthermore, the <td /> entry wraps a link, containing all the necessary info
+ val a = el.select("td")
+ .getOrNull(1)
+ ?.selectFirst("a")
?: return@mapNotNull null
- // Currently, children should all be <div /> elements, where the first entry is the name/title
- // And the other entries are additional info.
- // There are also cases of nested tables, eg for the "join" button in groups.
- // Those elements have <span /> texts, so we will filter by div to ignore those
- val texts = a.children().filter { it.tagName() == "div" && it.hasText() }
- val title = texts.firstOrNull()?.text() ?: return@mapNotNull null
- val info = texts.takeIf { it.size > 1 }?.last()?.text()
- L.e { a }
- create(
- href = url,
- title = title,
- description = info
- ).also { L.e { it } }
- })
+ val url =
+ a.attr("href").takeIf { it.isNotEmpty() }
+ ?.formattedFbUrl?.formattedSearchUrl
+ ?: return@mapNotNull null
+ // Currently, children should all be <div /> elements, where the first entry is the name/title
+ // And the other entries are additional info.
+ // There are also cases of nested tables, eg for the "join" button in groups.
+ // Those elements have <span /> texts, so we will filter by div to ignore those
+ val texts = a.children().filter { it.tagName() == "div" && it.hasText() }
+ val title = texts.firstOrNull()?.text() ?: return@mapNotNull null
+ val info = texts.takeIf { it.size > 1 }?.last()?.text()
+ L.e { a }
+ create(
+ href = url,
+ title = title,
+ description = info
+ ).also { L.e { it } }
+ }
+ )
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt
index c07884bc..79495b2a 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt
@@ -41,7 +41,7 @@ import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.REQUEST_REFRESH
import com.pitchedapps.frost.utils.REQUEST_TEXT_ZOOM
import com.pitchedapps.frost.utils.frostEvent
-import kotlin.coroutines.CoroutineContext
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
@@ -49,8 +49,8 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
-import org.koin.android.ext.android.inject
-import org.koin.core.component.inject
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
/**
* Created by Allan Wang on 2017-11-07.
@@ -59,7 +59,11 @@ import org.koin.core.component.inject
* Must be attached to activities implementing [MainActivityContract]
*/
@UseExperimental(ExperimentalCoroutinesApi::class)
-abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract,
+@AndroidEntryPoint
+abstract class BaseFragment :
+ Fragment(),
+ CoroutineScope,
+ FragmentContract,
DynamicUiContract {
companion object {
@@ -79,32 +83,41 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract,
ARG_URL to d.url,
ARG_POSITION to position
)
- d.put(fragment.arguments!!)
+ d.put(fragment.requireArguments())
return fragment
}
}
- protected val fbCookie: FbCookie by inject()
- protected val prefs: Prefs by inject()
- protected val themeProvider: ThemeProvider by inject()
+ @Inject
+ protected lateinit var mainContract: MainActivityContract
+
+ @Inject
+ protected lateinit var fbCookie: FbCookie
+
+ @Inject
+ protected lateinit var prefs: Prefs
+
+ @Inject
+ protected lateinit var themeProvider: ThemeProvider
+
open lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = ContextHelper.dispatcher + job
- override val baseUrl: String by lazy { arguments!!.getString(ARG_URL)!! }
+ override val baseUrl: String by lazy { requireArguments().getString(ARG_URL)!! }
override val baseEnum: FbItem by lazy { FbItem[arguments]!! }
- override val position: Int by lazy { arguments!!.getInt(ARG_POSITION) }
+ override val position: Int by lazy { requireArguments().getInt(ARG_POSITION) }
override var valid: Boolean
- get() = arguments!!.getBoolean(ARG_VALID, true)
+ get() = requireArguments().getBoolean(ARG_VALID, true)
set(value) {
if (!isActive || value || this is WebFragment) return
- arguments!!.putBoolean(ARG_VALID, value)
+ requireArguments().putBoolean(ARG_VALID, value)
frostEvent(
"Native Fallback",
"Item" to baseEnum.name
)
- (context as MainActivityContract).reloadFragment(this)
+ mainContract.reloadFragment(this)
}
override var firstLoad: Boolean = true
@@ -119,8 +132,6 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract,
super.onCreate(savedInstanceState)
job = SupervisorJob()
firstLoad = true
- if (context !is MainActivityContract)
- throw IllegalArgumentException("${this::class.java.simpleName} is not attached to a context implementing MainActivityContract")
}
final override fun onCreateView(
@@ -142,9 +153,7 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract,
onCreateRunnable = null
firstLoadRequest()
detachMainObservable()
- (context as? MainActivityContract)?.let {
- activityReceiver = attachMainObservable(it)
- }
+ activityReceiver = attachMainObservable(mainContract)
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
@@ -165,7 +174,7 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract,
}
override fun setTitle(title: String) {
- (context as? MainActivityContract)?.setTitle(title)
+ mainContract.setTitle(title)
}
override fun attachMainObservable(contract: MainActivityContract): ReceiveChannel<Int> {
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 b282b36c..28962230 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragments.kt
@@ -37,9 +37,9 @@ class NotificationFragment : FrostParserFragment<FrostNotifs, NotificationIItem>
override fun getDoc(cookie: String?) = frostJsoup(cookie, "${FbItem.NOTIFICATIONS.url}?more")
override fun toItems(response: ParseResponse<FrostNotifs>): List<NotificationIItem> =
- response.data.notifs.map { NotificationIItem(it, response.cookie) }
+ response.data.notifs.map { NotificationIItem(it, response.cookie, themeProvider) }
override fun bindImpl(recyclerView: FrostRecyclerView) {
- NotificationIItem.bindEvents(adapter, fbCookie, prefs)
+ NotificationIItem.bindEvents(adapter, fbCookie, prefs, themeProvider)
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt
index 7d9694fe..5600d49d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/glide/GlideUtils.kt
@@ -28,10 +28,8 @@ import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions
import com.pitchedapps.frost.facebook.FbCookie
import okhttp3.Interceptor
-import okhttp3.OkHttpClient
import okhttp3.Response
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
/**
* Created by Allan Wang on 28/12/17.
@@ -62,12 +60,12 @@ class FrostGlideModule : AppGlideModule() {
}
}
-private fun getFrostHttpClient(): OkHttpClient =
- OkHttpClient.Builder().addInterceptor(FrostCookieInterceptor()).build()
+// private fun getFrostHttpClient(): OkHttpClient =
+// OkHttpClient.Builder().addInterceptor(FrostCookieInterceptor()).build()
-class FrostCookieInterceptor : Interceptor, KoinComponent {
-
- private val fbCookie: FbCookie by inject()
+class FrostCookieInterceptor @Inject internal constructor(
+ private val fbCookie: FbCookie
+) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val origRequest = chain.request()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt
index 0c53a2b1..27263789 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/GenericIItems.kt
@@ -31,8 +31,6 @@ import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.launchWebOverlay
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 30/12/17.
@@ -74,13 +72,18 @@ interface ClickableIItemContract {
*/
open class HeaderIItem(
val text: String?,
- itemId: Int = R.layout.iitem_header
-) : KauIItem<HeaderIItem.ViewHolder>(R.layout.iitem_header, ::ViewHolder, itemId) {
-
- class ViewHolder(itemView: View) : FastAdapter.ViewHolder<HeaderIItem>(itemView),
- KoinComponent {
-
- private val themeProvider: ThemeProvider by inject()
+ itemId: Int = R.layout.iitem_header,
+ private val themeProvider: ThemeProvider
+) : KauIItem<HeaderIItem.ViewHolder>(
+ R.layout.iitem_header,
+ { ViewHolder(it, themeProvider) },
+ itemId
+) {
+
+ class ViewHolder(
+ itemView: View,
+ private val themeProvider: ThemeProvider
+ ) : FastAdapter.ViewHolder<HeaderIItem>(itemView) {
val text: TextView by bindView(R.id.item_header_text)
@@ -103,20 +106,23 @@ open class HeaderIItem(
open class TextIItem(
val text: String?,
override val url: String?,
- itemId: Int = R.layout.iitem_text
-) : KauIItem<TextIItem.ViewHolder>(R.layout.iitem_text, ::ViewHolder, itemId),
+ itemId: Int = R.layout.iitem_text,
+ private val themeProvider: ThemeProvider
+) : KauIItem<TextIItem.ViewHolder>(R.layout.iitem_text, { ViewHolder(it, themeProvider) }, itemId),
ClickableIItemContract {
- class ViewHolder(itemView: View) : FastAdapter.ViewHolder<TextIItem>(itemView), KoinComponent {
-
- private val themeProvider: ThemeProvider by inject()
+ class ViewHolder(
+ itemView: View,
+ private val themeProvider: ThemeProvider
+ ) : FastAdapter.ViewHolder<TextIItem>(itemView) {
val text: TextView by bindView(R.id.item_text_view)
override fun bindView(item: TextIItem, payloads: List<Any>) {
text.setTextColor(themeProvider.textColor)
text.text = item.text
- text.background = createSimpleRippleDrawable(themeProvider.bgColor, themeProvider.nativeBgColor)
+ text.background =
+ createSimpleRippleDrawable(themeProvider.bgColor, themeProvider.nativeBgColor)
}
override fun unbindView(item: TextIItem) {
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 8e0d5bec..f0fb1a28 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/NotificationIItem.kt
@@ -40,19 +40,25 @@ import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.isIndependent
import com.pitchedapps.frost.utils.launchWebOverlay
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 27/12/17.
*/
-class NotificationIItem(val notification: FrostNotif, val cookie: String) :
- KauIItem<NotificationIItem.ViewHolder>(
- R.layout.iitem_notification, ::ViewHolder
- ) {
+class NotificationIItem(
+ val notification: FrostNotif,
+ val cookie: String,
+ private val themeProvider: ThemeProvider
+) : KauIItem<NotificationIItem.ViewHolder>(
+ R.layout.iitem_notification, { ViewHolder(it, themeProvider) }
+) {
companion object {
- fun bindEvents(adapter: ItemAdapter<NotificationIItem>, fbCookie: FbCookie, prefs: Prefs) {
+ fun bindEvents(
+ adapter: ItemAdapter<NotificationIItem>,
+ fbCookie: FbCookie,
+ prefs: Prefs,
+ themeProvider: ThemeProvider
+ ) {
adapter.fastAdapter?.apply {
selectExtension {
isSelectable = false
@@ -62,7 +68,11 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) :
if (notif.unread) {
adapter.set(
position,
- NotificationIItem(notif.copy(unread = false), item.cookie)
+ NotificationIItem(
+ notif.copy(unread = false),
+ item.cookie,
+ themeProvider
+ )
)
}
// TODO temp fix. If url is dependent, we cannot load it directly
@@ -101,10 +111,10 @@ class NotificationIItem(val notification: FrostNotif, val cookie: String) :
}
}
- class ViewHolder(itemView: View) : FastAdapter.ViewHolder<NotificationIItem>(itemView),
- KoinComponent {
-
- private val themeProvider: ThemeProvider by inject()
+ class ViewHolder(
+ itemView: View,
+ private val themeProvider: ThemeProvider
+ ) : FastAdapter.ViewHolder<NotificationIItem>(itemView) {
private val frame: ViewGroup by bindView(R.id.item_frame)
private val avatar: ImageView by bindView(R.id.item_avatar)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt
index 0fd39d5c..f9f9064b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/iitems/TabIItem.kt
@@ -30,22 +30,23 @@ import com.mikepenz.fastadapter.drag.IDraggable
import com.pitchedapps.frost.R
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.injectors.ThemeProvider
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 26/11/17.
*/
-class TabIItem(val item: FbItem) : KauIItem<TabIItem.ViewHolder>(
- R.layout.iitem_tab_preview,
- { ViewHolder(it) }
-), IDraggable {
+class TabIItem(val item: FbItem, private val themeProvider: ThemeProvider) :
+ KauIItem<TabIItem.ViewHolder>(
+ R.layout.iitem_tab_preview,
+ { ViewHolder(it, themeProvider) }
+ ),
+ IDraggable {
override val isDraggable: Boolean = true
- class ViewHolder(itemView: View) : FastAdapter.ViewHolder<TabIItem>(itemView), KoinComponent {
-
- private val themeProvider: ThemeProvider by inject()
+ class ViewHolder(
+ itemView: View,
+ private val themeProvider: ThemeProvider
+ ) : FastAdapter.ViewHolder<TabIItem>(itemView) {
val image: ImageView by bindView(R.id.image)
val text: TextView by bindView(R.id.text)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
index 55eb198e..bceb9b3e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
@@ -22,11 +22,11 @@ import androidx.annotation.VisibleForTesting
import ca.allanwang.kau.kotlin.lazyContext
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.FileNotFoundException
import java.util.Locale
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
/**
* Created by Allan Wang on 2017-05-31.
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
index 2959974f..7c52fac7 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
@@ -21,8 +21,8 @@ import androidx.annotation.VisibleForTesting
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.web.FrostWebViewClient
-import kotlin.random.Random
import org.apache.commons.text.StringEscapeUtils
+import kotlin.random.Random
class JsBuilder {
private val css = StringBuilder()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt
index 570f3719..069c5d90 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/ThemeProvider.kt
@@ -30,58 +30,99 @@ import com.pitchedapps.frost.enums.Theme
import com.pitchedapps.frost.enums.ThemeCategory
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
-import java.io.BufferedReader
-import java.io.FileNotFoundException
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
-import org.koin.core.context.GlobalContext
+import java.io.BufferedReader
+import java.io.FileNotFoundException
+import javax.inject.Inject
+import javax.inject.Singleton
+
+interface ThemeProvider {
+ val textColor: Int
+
+ val accentColor: Int
+
+ val accentColorForWhite: Int
+
+ val nativeBgColor: Int
+
+ fun nativeBgColor(unread: Boolean): Int
+
+ val bgColor: Int
+
+ val headerColor: Int
+
+ val iconColor: Int
+
+ val isCustomTheme: Boolean
+
+ /**
+ * Note that while this can be loaded from any thread, it is typically done through [preload]]
+ */
+ fun injector(category: ThemeCategory): InjectorContract
+
+ fun setTheme(id: Int)
+
+ fun reset()
+
+ suspend fun preload()
+}
/**
* Provides [InjectorContract] for each [ThemeCategory].
* Can be reloaded to take in changes from [Prefs]
*/
-class ThemeProvider(private val context: Context, private val prefs: Prefs) {
+class ThemeProviderImpl @Inject internal constructor(
+ @ApplicationContext private val context: Context,
+ private val prefs: Prefs
+) : ThemeProvider {
private var theme: Theme = Theme.values[prefs.theme]
+ set(value) {
+ field = value
+ prefs.theme = value.ordinal
+ }
private val injectors: MutableMap<ThemeCategory, InjectorContract> = mutableMapOf()
- val textColor: Int
+ override val textColor: Int
get() = theme.textColorGetter(prefs)
- val accentColor: Int
+ override val accentColor: Int
get() = theme.accentColorGetter(prefs)
- val accentColorForWhite: Int
+ override val accentColorForWhite: Int
get() = when {
accentColor.isColorVisibleOn(Color.WHITE) -> accentColor
textColor.isColorVisibleOn(Color.WHITE) -> textColor
else -> FACEBOOK_BLUE
}
- val nativeBgColor: Int
+ override val nativeBgColor: Int
get() = bgColor.withAlpha(30)
- fun nativeBgColor(unread: Boolean) = bgColor
+ override fun nativeBgColor(unread: Boolean) = bgColor
.colorToForeground(if (unread) 0.7f else 0.0f)
.withAlpha(30)
- val bgColor: Int
+ override val bgColor: Int
get() = theme.backgroundColorGetter(prefs)
- val headerColor: Int
+ override val headerColor: Int
get() = theme.headerColorGetter(prefs)
- val iconColor: Int
+ override val iconColor: Int
get() = theme.iconColorGetter(prefs)
- val isCustomTheme: Boolean
+ override val isCustomTheme: Boolean
get() = theme == Theme.CUSTOM
- /**
- * Note that while this can be loaded from any thread, it is typically done through [preload]]
- */
- fun injector(category: ThemeCategory): InjectorContract =
+ override fun injector(category: ThemeCategory): InjectorContract =
injectors.getOrPut(category) { createInjector(category) }
/**
@@ -123,28 +164,28 @@ class ThemeProvider(private val context: Context, private val prefs: Prefs) {
}
}
- fun setTheme(id: Int) {
+ override fun setTheme(id: Int) {
+ if (theme.ordinal == id) return
theme = Theme.values[id]
reset()
}
- fun reset() {
+ override fun reset() {
injectors.clear()
}
- suspend fun preload() {
+ override suspend fun preload() {
withContext(Dispatchers.IO) {
reset()
ThemeCategory.values().forEach { injector(it) }
}
}
+}
- companion object {
-
- fun get(): ThemeProvider = GlobalContext.get().get()
-
- fun module() = org.koin.dsl.module {
- single { ThemeProvider(get(), get()) }
- }
- }
+@Module
+@InstallIn(SingletonComponent::class)
+interface ThemeProviderModule {
+ @Binds
+ @Singleton
+ fun themeProvider(to: ThemeProviderImpl): ThemeProvider
}
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 486b09a9..662c44e5 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroFragmentTheme.kt
@@ -64,7 +64,7 @@ class IntroFragmentTheme : BaseIntroFragment(R.layout.intro_theme) {
private fun View.setThemeClick(theme: Theme) {
setOnClickListener { v ->
- prefs.theme = theme.ordinal
+ themeProvider.setTheme(theme.ordinal)
(activity as IntroActivity).apply {
binding.ripple.ripple(themeProvider.bgColor, v.x + v.pivotX, v.y + v.pivotY)
theme()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt
index 8003cb2e..040fa96f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/intro/IntroMainFragments.kt
@@ -35,9 +35,9 @@ import com.pitchedapps.frost.R
import com.pitchedapps.frost.activities.IntroActivity
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
import kotlin.math.abs
-import org.koin.android.ext.android.inject
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 2017-07-28.
@@ -48,10 +48,14 @@ import org.koin.core.component.inject
/**
* The core intro fragment for all other fragments
*/
+@AndroidEntryPoint
abstract class BaseIntroFragment(val layoutRes: Int) : Fragment() {
- protected val prefs: Prefs by inject()
- protected val themeProvider: ThemeProvider by inject()
+ @Inject
+ protected lateinit var prefs: Prefs
+
+ @Inject
+ protected lateinit var themeProvider: ThemeProvider
val screenWidth
get() = resources.displayMetrics.widthPixels
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/CoroutineUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/CoroutineUtils.kt
index b657fa1a..6f8a60a9 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/CoroutineUtils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/CoroutineUtils.kt
@@ -16,12 +16,12 @@
*/
package com.pitchedapps.frost.kotlin
-import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.launch
+import kotlin.coroutines.CoroutineContext
@UseExperimental(ExperimentalCoroutinesApi::class)
fun <T> BroadcastChannel<T>.subscribeDuringJob(
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 854dcf28..74765b58 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/kotlin/Flyweight.kt
@@ -17,7 +17,6 @@
package com.pitchedapps.frost.kotlin
import com.pitchedapps.frost.utils.L
-import java.util.concurrent.ConcurrentHashMap
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineExceptionHandler
@@ -29,6 +28,7 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.select
+import java.util.concurrent.ConcurrentHashMap
/**
* Flyweight to keep track of values so long as they are valid.
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/OldPrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/OldPrefs.kt
index 1abed8fb..cfd8edbd 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/OldPrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/OldPrefs.kt
@@ -20,6 +20,7 @@ import ca.allanwang.kau.kpref.KPref
import ca.allanwang.kau.kpref.KPrefFactory
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.enums.FeedSort
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-28.
@@ -29,7 +30,8 @@ import com.pitchedapps.frost.enums.FeedSort
* As of 2020-07-18, prefs have been split up into multiple folders
*/
@Deprecated(level = DeprecationLevel.WARNING, message = "Use pref segments")
-class OldPrefs(factory: KPrefFactory) : KPref("${BuildConfig.APPLICATION_ID}.prefs", factory) {
+class OldPrefs @Inject internal constructor(factory: KPrefFactory) :
+ KPref("${BuildConfig.APPLICATION_ID}.prefs", factory) {
var lastLaunch: Long by kpref("last_launch", -1L)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/Prefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/Prefs.kt
index d31be432..0cf97c56 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/Prefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/Prefs.kt
@@ -16,6 +16,9 @@
*/
package com.pitchedapps.frost.prefs
+import android.content.Context
+import ca.allanwang.kau.kpref.KPrefFactory
+import ca.allanwang.kau.kpref.KPrefFactoryAndroid
import com.pitchedapps.frost.prefs.sections.BehaviourPrefs
import com.pitchedapps.frost.prefs.sections.BehaviourPrefsImpl
import com.pitchedapps.frost.prefs.sections.CorePrefs
@@ -28,8 +31,14 @@ import com.pitchedapps.frost.prefs.sections.ShowcasePrefs
import com.pitchedapps.frost.prefs.sections.ShowcasePrefsImpl
import com.pitchedapps.frost.prefs.sections.ThemePrefs
import com.pitchedapps.frost.prefs.sections.ThemePrefsImpl
-import org.koin.core.context.GlobalContext
-import org.koin.dsl.module
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Inject
+import javax.inject.Singleton
/**
* [Prefs] is no longer an actual pref, but we will expose the reset function as it is used elsewhere
@@ -46,34 +55,9 @@ interface Prefs :
NotifPrefs,
ThemePrefs,
ShowcasePrefs,
- PrefsBase {
- companion object {
- fun get(): Prefs = GlobalContext.get().get()
+ PrefsBase
- fun module() = module {
- single<BehaviourPrefs> { BehaviourPrefsImpl(factory = get()) }
- single<CorePrefs> { CorePrefsImpl(factory = get()) }
- single<FeedPrefs> { FeedPrefsImpl(factory = get()) }
- single<NotifPrefs> { NotifPrefsImpl(factory = get()) }
- single<ThemePrefs> { ThemePrefsImpl(factory = get()) }
- single<ShowcasePrefs> { ShowcasePrefsImpl(factory = get()) }
- single<Prefs> {
- PrefsImpl(
- behaviourPrefs = get(),
- corePrefs = get(),
- feedPrefs = get(),
- notifPrefs = get(),
- themePrefs = get(),
- showcasePrefs = get()
- )
- }
- // Needed for migration
- single<OldPrefs> { OldPrefs(factory = get()) }
- }
- }
-}
-
-class PrefsImpl(
+class PrefsImpl @Inject internal constructor(
private val behaviourPrefs: BehaviourPrefs,
private val corePrefs: CorePrefs,
private val feedPrefs: FeedPrefs,
@@ -106,3 +90,43 @@ class PrefsImpl(
showcasePrefs.deleteKeys()
}
}
+
+@Module
+@InstallIn(SingletonComponent::class)
+interface PrefModule {
+ @Binds
+ @Singleton
+ fun behaviour(to: BehaviourPrefsImpl): BehaviourPrefs
+
+ @Binds
+ @Singleton
+ fun core(to: CorePrefsImpl): CorePrefs
+
+ @Binds
+ @Singleton
+ fun feed(to: FeedPrefsImpl): FeedPrefs
+
+ @Binds
+ @Singleton
+ fun notif(to: NotifPrefsImpl): NotifPrefs
+
+ @Binds
+ @Singleton
+ fun theme(to: ThemePrefsImpl): ThemePrefs
+
+ @Binds
+ @Singleton
+ fun showcase(to: ShowcasePrefsImpl): ShowcasePrefs
+
+ @Binds
+ @Singleton
+ fun prefs(to: PrefsImpl): Prefs
+}
+
+@Module
+@InstallIn(SingletonComponent::class)
+object PrefFactoryModule {
+ @Provides
+ @Singleton
+ fun factory(@ApplicationContext context: Context): KPrefFactory = KPrefFactoryAndroid(context)
+}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/BehaviourPrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/BehaviourPrefs.kt
index 9d621048..8842d988 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/BehaviourPrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/BehaviourPrefs.kt
@@ -21,8 +21,7 @@ import ca.allanwang.kau.kpref.KPrefFactory
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.prefs.OldPrefs
import com.pitchedapps.frost.prefs.PrefsBase
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
interface BehaviourPrefs : PrefsBase {
var biometricsEnabled: Boolean
@@ -50,12 +49,10 @@ interface BehaviourPrefs : PrefsBase {
var autoExpandTextBox: Boolean
}
-class BehaviourPrefsImpl(
- factory: KPrefFactory
-) : KPref("${BuildConfig.APPLICATION_ID}.prefs.behaviour", factory),
- BehaviourPrefs, KoinComponent {
-
- private val oldPrefs: OldPrefs by inject()
+class BehaviourPrefsImpl @Inject internal constructor(
+ factory: KPrefFactory,
+ oldPrefs: OldPrefs,
+) : KPref("${BuildConfig.APPLICATION_ID}.prefs.behaviour", factory), BehaviourPrefs {
override var biometricsEnabled: Boolean by kpref(
"biometrics_enabled",
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/CorePrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/CorePrefs.kt
index 6d3885cb..880a7225 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/CorePrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/CorePrefs.kt
@@ -21,8 +21,7 @@ import ca.allanwang.kau.kpref.KPrefFactory
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.prefs.OldPrefs
import com.pitchedapps.frost.prefs.PrefsBase
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
interface CorePrefs : PrefsBase {
var lastLaunch: Long
@@ -56,12 +55,10 @@ interface CorePrefs : PrefsBase {
var messageScrollToBottom: Boolean
}
-class CorePrefsImpl(
- factory: KPrefFactory
-) : KPref("${BuildConfig.APPLICATION_ID}.prefs.core", factory),
- CorePrefs, KoinComponent {
-
- private val oldPrefs: OldPrefs by inject()
+class CorePrefsImpl @Inject internal constructor(
+ factory: KPrefFactory,
+ oldPrefs: OldPrefs,
+) : KPref("${BuildConfig.APPLICATION_ID}.prefs.core", factory), CorePrefs {
override var lastLaunch: Long by kpref("last_launch", oldPrefs.lastLaunch /* -1L */)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/FeedPrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/FeedPrefs.kt
index 3fe2cfd8..00df9743 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/FeedPrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/FeedPrefs.kt
@@ -22,8 +22,7 @@ import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.enums.MainActivityLayout
import com.pitchedapps.frost.prefs.OldPrefs
import com.pitchedapps.frost.prefs.PrefsBase
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
interface FeedPrefs : PrefsBase {
var webTextScaling: Int
@@ -51,12 +50,10 @@ interface FeedPrefs : PrefsBase {
var showPostReactions: Boolean
}
-class FeedPrefsImpl(
- factory: KPrefFactory
-) : KPref("${BuildConfig.APPLICATION_ID}.prefs.feed", factory),
- FeedPrefs, KoinComponent {
-
- private val oldPrefs: OldPrefs by inject()
+class FeedPrefsImpl @Inject internal constructor(
+ factory: KPrefFactory,
+ oldPrefs: OldPrefs
+) : KPref("${BuildConfig.APPLICATION_ID}.prefs.feed", factory), FeedPrefs {
override var webTextScaling: Int by kpref("web_text_scaling", oldPrefs.webTextScaling /* 100 */)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/NotifPrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/NotifPrefs.kt
index a9a6956f..5e34c105 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/NotifPrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/NotifPrefs.kt
@@ -21,8 +21,7 @@ import ca.allanwang.kau.kpref.KPrefFactory
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.prefs.OldPrefs
import com.pitchedapps.frost.prefs.PrefsBase
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
interface NotifPrefs : PrefsBase {
var notificationKeywords: Set<String>
@@ -48,12 +47,10 @@ interface NotifPrefs : PrefsBase {
var notificationFreq: Long
}
-class NotifPrefsImpl(
- factory: KPrefFactory
-) : KPref("${BuildConfig.APPLICATION_ID}.prefs.notif", factory),
- NotifPrefs, KoinComponent {
-
- private val oldPrefs: OldPrefs by inject()
+class NotifPrefsImpl @Inject internal constructor(
+ factory: KPrefFactory,
+ oldPrefs: OldPrefs,
+) : KPref("${BuildConfig.APPLICATION_ID}.prefs.notif", factory), NotifPrefs {
override var notificationKeywords: Set<String> by kpref(
"notification_keywords",
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ShowcasePrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ShowcasePrefs.kt
index 516a14c5..dce8b898 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ShowcasePrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ShowcasePrefs.kt
@@ -20,6 +20,7 @@ import ca.allanwang.kau.kpref.KPref
import ca.allanwang.kau.kpref.KPrefFactory
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.prefs.PrefsBase
+import javax.inject.Inject
interface ShowcasePrefs : PrefsBase {
/**
@@ -35,10 +36,9 @@ interface ShowcasePrefs : PrefsBase {
*
* Showcase prefs that offer one time helpers to guide new users
*/
-class ShowcasePrefsImpl(
+class ShowcasePrefsImpl @Inject internal constructor(
factory: KPrefFactory
-) : KPref("${BuildConfig.APPLICATION_ID}.showcase", factory),
- ShowcasePrefs {
+) : KPref("${BuildConfig.APPLICATION_ID}.showcase", factory), ShowcasePrefs {
override val firstWebOverlay: Boolean by kprefSingle("first_web_overlay")
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt
index 47496d6d..b024b2d3 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/prefs/sections/ThemePrefs.kt
@@ -19,11 +19,9 @@ package com.pitchedapps.frost.prefs.sections
import ca.allanwang.kau.kpref.KPref
import ca.allanwang.kau.kpref.KPrefFactory
import com.pitchedapps.frost.BuildConfig
-import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.OldPrefs
import com.pitchedapps.frost.prefs.PrefsBase
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
interface ThemePrefs : PrefsBase {
var theme: Int
@@ -41,17 +39,16 @@ interface ThemePrefs : PrefsBase {
var tintNavBar: Boolean
}
-class ThemePrefsImpl(
- factory: KPrefFactory
-) : KPref("${BuildConfig.APPLICATION_ID}.prefs.theme", factory),
- ThemePrefs, KoinComponent {
+class ThemePrefsImpl @Inject internal constructor(
+ factory: KPrefFactory,
+ oldPrefs: OldPrefs,
+) : KPref("${BuildConfig.APPLICATION_ID}.prefs.theme", factory), ThemePrefs {
- private val oldPrefs: OldPrefs by inject()
- private val themeProvider: ThemeProvider by inject()
-
- override var theme: Int by kpref("theme", oldPrefs.theme /* 0 */) {
- themeProvider.setTheme(it)
- }
+ /**
+ * Note that this is purely for the pref storage. Updating themes should use
+ * ThemeProvider
+ */
+ override var theme: Int by kpref("theme", oldPrefs.theme /* 0 */)
override var customTextColor: Int by kpref(
"color_text",
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/BaseJobService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/BaseJobService.kt
index 4d1317d5..0db08d0f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/BaseJobService.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/BaseJobService.kt
@@ -20,9 +20,9 @@ import android.app.job.JobParameters
import android.app.job.JobService
import androidx.annotation.CallSuper
import ca.allanwang.kau.utils.ContextHelper
-import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
+import kotlin.coroutines.CoroutineContext
abstract class BaseJobService : JobService(), CoroutineScope {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt
index 8219049a..3d66f1ee 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/LocalService.kt
@@ -24,10 +24,10 @@ import android.content.Context
import android.os.PersistableBundle
import com.pitchedapps.frost.activities.ImageActivity
import com.pitchedapps.frost.utils.L
-import java.io.FileFilter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import java.io.FileFilter
class LocalService : BaseJobService() {
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 55dad065..01f52caa 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
@@ -29,12 +29,13 @@ import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.frostEvent
import com.pitchedapps.frost.widgets.NotificationWidget
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
-import org.koin.android.ext.android.inject
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-14.
@@ -44,11 +45,17 @@ import org.koin.android.ext.android.inject
*
* All fetching is done through parsers
*/
+@AndroidEntryPoint
class NotificationService : BaseJobService() {
- private val prefs: Prefs by inject()
- private val notifDao: NotificationDao by inject()
- private val cookieDao: CookieDao by inject()
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var notifDao: NotificationDao
+
+ @Inject
+ lateinit var cookieDao: CookieDao
override fun onStopJob(params: JobParameters?): Boolean {
super.onStopJob(params)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt
index 439838a9..91a60d90 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/UpdateReceiver.kt
@@ -21,17 +21,19 @@ import android.content.Context
import android.content.Intent
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-31.
*
* Receiver that is triggered whenever the app updates so it can bind the notifications again
*/
-class UpdateReceiver : BroadcastReceiver(), KoinComponent {
+@AndroidEntryPoint
+class UpdateReceiver : BroadcastReceiver() {
- private val prefs: Prefs by inject()
+ @Inject
+ lateinit var prefs: Prefs
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != Intent.ACTION_MY_PACKAGE_REPLACED) return
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 64d9dba2..34f1ba1c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
@@ -33,7 +33,6 @@ import com.pitchedapps.frost.utils.frostEvent
import com.pitchedapps.frost.utils.frostNavigationBar
import com.pitchedapps.frost.utils.frostSnackbar
import com.pitchedapps.frost.utils.launchTabCustomizerActivity
-import com.pitchedapps.frost.utils.setFrostTheme
import com.pitchedapps.frost.views.KPrefTextSeekbar
/**
@@ -43,7 +42,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
header(R.string.theme_customization)
- text(R.string.theme, prefs::theme, { prefs.theme = it }) {
+ text(R.string.theme, prefs::theme, { themeProvider.setTheme(it) }) {
onClick = {
materialDialog {
title(R.string.theme)
@@ -55,7 +54,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
item.pref = index
shouldRestartMain()
reload()
- setFrostTheme(themeProvider, true)
+ activityThemer.setFrostTheme(forceTransparent = true)
themeExterior()
invalidateOptionsMenu()
frostEvent("Theme", "Count" to Theme(index).name)
@@ -70,7 +69,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
fun KPrefColorPicker.KPrefColorContract.dependsOnCustom() {
enabler = themeProvider::isCustomTheme
- onDisabledClick = { frostSnackbar(R.string.requires_custom_theme) }
+ onDisabledClick = { frostSnackbar(R.string.requires_custom_theme, themeProvider) }
allowCustom = true
}
@@ -78,53 +77,68 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
themeProvider.reset()
}
- colorPicker(R.string.text_color, prefs::customTextColor, {
- prefs.customTextColor = it
- reload()
- invalidateCustomTheme()
- shouldRestartMain()
- }) {
+ colorPicker(
+ R.string.text_color, prefs::customTextColor,
+ {
+ prefs.customTextColor = it
+ reload()
+ invalidateCustomTheme()
+ shouldRestartMain()
+ }
+ ) {
dependsOnCustom()
allowCustomAlpha = false
}
- colorPicker(R.string.accent_color, prefs::customAccentColor, {
- prefs.customAccentColor = it
- reload()
- invalidateCustomTheme()
- shouldRestartMain()
- }) {
+ colorPicker(
+ R.string.accent_color, prefs::customAccentColor,
+ {
+ prefs.customAccentColor = it
+ reload()
+ invalidateCustomTheme()
+ shouldRestartMain()
+ }
+ ) {
dependsOnCustom()
allowCustomAlpha = false
}
- colorPicker(R.string.background_color, prefs::customBackgroundColor, {
- prefs.customBackgroundColor = it
- bgCanvas.ripple(it, duration = 500L)
- invalidateCustomTheme()
- setFrostTheme(themeProvider, true)
- shouldRestartMain()
- }) {
+ colorPicker(
+ R.string.background_color, prefs::customBackgroundColor,
+ {
+ prefs.customBackgroundColor = it
+ bgCanvas.ripple(it, duration = 500L)
+ invalidateCustomTheme()
+ activityThemer.setFrostTheme(forceTransparent = true)
+ shouldRestartMain()
+ }
+ ) {
dependsOnCustom()
allowCustomAlpha = true
}
- colorPicker(R.string.header_color, prefs::customHeaderColor, {
- prefs.customHeaderColor = it
- frostNavigationBar(prefs, themeProvider)
- toolbarCanvas.ripple(it, RippleCanvas.MIDDLE, RippleCanvas.END, duration = 500L)
- reload()
- shouldRestartMain()
- }) {
+ colorPicker(
+ R.string.header_color, prefs::customHeaderColor,
+ {
+ prefs.customHeaderColor = it
+ frostNavigationBar(prefs, themeProvider)
+ toolbarCanvas.ripple(it, RippleCanvas.MIDDLE, RippleCanvas.END, duration = 500L)
+ reload()
+ shouldRestartMain()
+ }
+ ) {
dependsOnCustom()
allowCustomAlpha = true
}
- colorPicker(R.string.icon_color, prefs::customIconColor, {
- prefs.customIconColor = it
- invalidateOptionsMenu()
- shouldRestartMain()
- }) {
+ colorPicker(
+ R.string.icon_color, prefs::customIconColor,
+ {
+ prefs.customIconColor = it
+ invalidateOptionsMenu()
+ shouldRestartMain()
+ }
+ ) {
dependsOnCustom()
allowCustomAlpha = false
}
@@ -134,7 +148,8 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
text(
R.string.main_activity_layout,
prefs::mainActivityLayoutType,
- { prefs.mainActivityLayoutType = it }) {
+ { prefs.mainActivityLayoutType = it }
+ ) {
textGetter = { string(prefs.mainActivityLayout.titleRes) }
onClick = {
materialDialog {
@@ -158,11 +173,14 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
onClick = { launchTabCustomizerActivity() }
}
- checkbox(R.string.tint_nav, prefs::tintNavBar, {
- prefs.tintNavBar = it
- frostNavigationBar(prefs, themeProvider)
- setFrostResult(REQUEST_NAV)
- }) {
+ checkbox(
+ R.string.tint_nav, prefs::tintNavBar,
+ {
+ prefs.tintNavBar = it
+ frostNavigationBar(prefs, themeProvider)
+ setFrostResult(REQUEST_NAV)
+ }
+ ) {
descRes = R.string.tint_nav_desc
}
@@ -174,12 +192,16 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
) {
prefs.webTextScaling = it
setFrostResult(REQUEST_TEXT_ZOOM)
- })
+ }
+ )
)
- checkbox(R.string.enforce_black_media_bg, prefs::blackMediaBg, {
- prefs.blackMediaBg = it
- }) {
+ checkbox(
+ R.string.enforce_black_media_bg, prefs::blackMediaBg,
+ {
+ prefs.blackMediaBg = it
+ }
+ ) {
descRes = R.string.enforce_black_media_bg_desc
}
}
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 551b3ff1..a9d99763 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
@@ -36,21 +36,24 @@ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(
R.string.overlay_swipe,
prefs::overlayEnabled,
- { prefs.overlayEnabled = it; shouldRefreshMain() }) {
+ { prefs.overlayEnabled = it; shouldRefreshMain() }
+ ) {
descRes = R.string.overlay_swipe_desc
}
checkbox(
R.string.overlay_full_screen_swipe,
prefs::overlayFullScreenSwipe,
- { prefs.overlayFullScreenSwipe = it }) {
+ { prefs.overlayFullScreenSwipe = it }
+ ) {
descRes = R.string.overlay_full_screen_swipe_desc
}
checkbox(
R.string.open_links_in_default,
prefs::linksInDefaultApp,
- { prefs.linksInDefaultApp = it }) {
+ { prefs.linksInDefaultApp = it }
+ ) {
descRes = R.string.open_links_in_default_desc
}
@@ -61,14 +64,16 @@ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(
R.string.force_message_bottom,
prefs::messageScrollToBottom,
- { prefs.messageScrollToBottom = it }) {
+ { prefs.messageScrollToBottom = it }
+ ) {
descRes = R.string.force_message_bottom_desc
}
checkbox(
R.string.auto_expand_text_box,
prefs::autoExpandTextBox,
- { prefs.autoExpandTextBox = it; shouldRefreshMain() }) {
+ { prefs.autoExpandTextBox = it; shouldRefreshMain() }
+ ) {
descRes = R.string.auto_expand_text_box_desc
}
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 9a4751b8..b2bb1d11 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt
@@ -36,14 +36,15 @@ import com.pitchedapps.frost.facebook.parsers.FrostParser
import com.pitchedapps.frost.facebook.parsers.MessageParser
import com.pitchedapps.frost.facebook.parsers.NotifParser
import com.pitchedapps.frost.facebook.parsers.SearchParser
+import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.frostUriFromFile
import com.pitchedapps.frost.utils.sendFrostEmail
-import java.io.File
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
+import java.io.File
/**
* Created by Allan Wang on 2017-06-30.
@@ -89,10 +90,10 @@ fun SettingsActivity.getDebugPrefs(): KPrefAdapterBuilder.() -> Unit = {
val data = parser.parse(fbCookie.webCookie)
withMainContext {
loading.dismiss()
- createEmail(parser, data?.data)
+ createEmail(parser, data?.data, prefs)
}
} catch (e: Exception) {
- createEmail(parser, "Error: ${e.message}")
+ createEmail(parser, "Error: ${e.message}", prefs)
}
}
}
@@ -101,8 +102,11 @@ fun SettingsActivity.getDebugPrefs(): KPrefAdapterBuilder.() -> Unit = {
}
}
-private fun Context.createEmail(parser: FrostParser<*>, content: Any?) =
- sendFrostEmail("${string(R.string.debug_report)}: ${parser::class.java.simpleName}") {
+private fun Context.createEmail(parser: FrostParser<*>, content: Any?, prefs: Prefs) =
+ sendFrostEmail(
+ "${string(R.string.debug_report)}: ${parser::class.java.simpleName}",
+ prefs = prefs
+ ) {
addItem("Url", parser.url)
addItem("Contents", "$content")
}
@@ -148,7 +152,7 @@ fun SettingsActivity.sendDebug(url: String, html: String?) {
File(downloader.baseDir, "$ZIP_NAME.zip")
)
L.i { "Sending debug zip with uri $zipUri" }
- sendFrostEmail(R.string.debug_report_email_title) {
+ sendFrostEmail(R.string.debug_report_email_title, prefs = prefs) {
addItem("Url", url)
addAttachment(zipUri)
extras = {
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 30b16f81..995500f0 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
@@ -36,10 +36,13 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = {
// Experimental content ends here --------------------
- checkbox(R.string.verbose_logging, prefs::verboseLogging, {
- prefs.verboseLogging = it
- KL.shouldLog = { it != Log.VERBOSE }
- }) {
+ checkbox(
+ R.string.verbose_logging, prefs::verboseLogging,
+ {
+ prefs.verboseLogging = it
+ KL.shouldLog = { it != Log.VERBOSE }
+ }
+ ) {
descRes = R.string.verbose_logging_desc
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt
index f8d10437..914874a2 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt
@@ -49,66 +49,93 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = {
textGetter = { string(FeedSort(it).textRes) }
}
- checkbox(R.string.aggressive_recents, prefs::aggressiveRecents, {
- prefs.aggressiveRecents = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.aggressive_recents, prefs::aggressiveRecents,
+ {
+ prefs.aggressiveRecents = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.aggressive_recents_desc
}
- checkbox(R.string.composer, prefs::showComposer, {
- prefs.showComposer = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.composer, prefs::showComposer,
+ {
+ prefs.showComposer = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.composer_desc
}
- checkbox(R.string.create_fab, prefs::showCreateFab, {
- prefs.showCreateFab = it
- setFrostResult(REQUEST_FAB)
- }) {
+ checkbox(
+ R.string.create_fab, prefs::showCreateFab,
+ {
+ prefs.showCreateFab = it
+ setFrostResult(REQUEST_FAB)
+ }
+ ) {
descRes = R.string.create_fab_desc
}
- checkbox(R.string.suggested_friends, prefs::showSuggestedFriends, {
- prefs.showSuggestedFriends = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.suggested_friends, prefs::showSuggestedFriends,
+ {
+ prefs.showSuggestedFriends = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.suggested_friends_desc
}
- checkbox(R.string.suggested_groups, prefs::showSuggestedGroups, {
- prefs.showSuggestedGroups = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.suggested_groups, prefs::showSuggestedGroups,
+ {
+ prefs.showSuggestedGroups = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.suggested_groups_desc
}
- checkbox(R.string.show_stories, prefs::showStories, {
- prefs.showStories = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.show_stories, prefs::showStories,
+ {
+ prefs.showStories = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.show_stories_desc
}
- checkbox(R.string.show_post_actions, prefs::showPostActions, {
- prefs.showPostActions = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.show_post_actions, prefs::showPostActions,
+ {
+ prefs.showPostActions = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.show_post_actions_desc
}
- checkbox(R.string.show_post_reactions, prefs::showPostReactions, {
- prefs.showPostReactions = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.show_post_reactions, prefs::showPostReactions,
+ {
+ prefs.showPostReactions = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.show_post_reactions_desc
}
- checkbox(R.string.full_size_image, prefs::fullSizeImage, {
- prefs.fullSizeImage = it
- shouldRefreshMain()
- }) {
+ checkbox(
+ R.string.full_size_image, prefs::fullSizeImage,
+ {
+ prefs.fullSizeImage = it
+ shouldRefreshMain()
+ }
+ ) {
descRes = R.string.full_size_image_desc
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt
index c275227f..9df8bf86 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt
@@ -28,7 +28,8 @@ fun SettingsActivity.getNetworkPrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(
R.string.network_media_on_metered,
{ !prefs.loadMediaOnMeteredNetwork },
- { prefs.loadMediaOnMeteredNetwork = !it }) {
+ { prefs.loadMediaOnMeteredNetwork = !it }
+ ) {
descRes = R.string.network_media_on_metered_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 397825f6..a0fd2e3d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt
@@ -54,7 +54,8 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
text(
R.string.notification_frequency,
prefs::notificationFreq,
- { prefs.notificationFreq = it }) {
+ { 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) }
@@ -87,34 +88,42 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
}
}
- checkbox(R.string.notification_general, prefs::notificationsGeneral,
+ checkbox(
+ R.string.notification_general, prefs::notificationsGeneral,
{
prefs.notificationsGeneral = it
reloadByTitle(R.string.notification_general_all_accounts)
if (!prefs.notificationsInstantMessages)
reloadByTitle(R.string.notification_frequency)
- }) {
+ }
+ ) {
descRes = R.string.notification_general_desc
}
- checkbox(R.string.notification_general_all_accounts, prefs::notificationAllAccounts,
- { prefs.notificationAllAccounts = it }) {
+ checkbox(
+ R.string.notification_general_all_accounts, prefs::notificationAllAccounts,
+ { prefs.notificationAllAccounts = it }
+ ) {
descRes = R.string.notification_general_all_accounts_desc
enabler = { prefs.notificationsGeneral }
}
- checkbox(R.string.notification_messages, prefs::notificationsInstantMessages,
+ checkbox(
+ R.string.notification_messages, prefs::notificationsInstantMessages,
{
prefs.notificationsInstantMessages = it
reloadByTitle(R.string.notification_messages_all_accounts)
if (!prefs.notificationsGeneral)
reloadByTitle(R.string.notification_frequency)
- }) {
+ }
+ ) {
descRes = R.string.notification_messages_desc
}
- checkbox(R.string.notification_messages_all_accounts, prefs::notificationsImAllAccounts,
- { prefs.notificationsImAllAccounts = it }) {
+ checkbox(
+ R.string.notification_messages_all_accounts, prefs::notificationsImAllAccounts,
+ { prefs.notificationsImAllAccounts = it }
+ ) {
descRes = R.string.notification_messages_all_accounts_desc
enabler = { prefs.notificationsInstantMessages }
}
@@ -129,13 +138,16 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
}
}
} else {
- checkbox(R.string.notification_sound, prefs::notificationSound, {
- prefs.notificationSound = it
- reloadByTitle(
- R.string.notification_ringtone,
- R.string.message_ringtone
- )
- })
+ checkbox(
+ R.string.notification_sound, prefs::notificationSound,
+ {
+ prefs.notificationSound = it
+ reloadByTitle(
+ R.string.notification_ringtone,
+ R.string.message_ringtone
+ )
+ }
+ )
fun KPrefText.KPrefTextContract<String>.ringtone(code: Int) {
enabler = prefs::notificationSound
@@ -162,21 +174,29 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
}
}
- text(R.string.notification_ringtone, prefs::notificationRingtone,
- { prefs.notificationRingtone = it }) {
+ text(
+ R.string.notification_ringtone, prefs::notificationRingtone,
+ { prefs.notificationRingtone = it }
+ ) {
ringtone(SettingsActivity.REQUEST_NOTIFICATION_RINGTONE)
}
- text(R.string.message_ringtone, prefs::messageRingtone,
- { prefs.messageRingtone = it }) {
+ text(
+ R.string.message_ringtone, prefs::messageRingtone,
+ { prefs.messageRingtone = it }
+ ) {
ringtone(SettingsActivity.REQUEST_MESSAGE_RINGTONE)
}
- checkbox(R.string.notification_vibrate, prefs::notificationVibrate,
- { prefs.notificationVibrate = it })
+ checkbox(
+ R.string.notification_vibrate, prefs::notificationVibrate,
+ { prefs.notificationVibrate = it }
+ )
- checkbox(R.string.notification_lights, prefs::notificationLights,
- { prefs.notificationLights = it })
+ checkbox(
+ R.string.notification_lights, prefs::notificationLights,
+ { prefs.notificationLights = it }
+ )
}
if (BuildConfig.DEBUG) {
@@ -195,7 +215,7 @@ fun SettingsActivity.getNotificationPrefs(): KPrefAdapterBuilder.() -> Unit = {
val text =
if (fetchNotifications()) R.string.notification_fetch_success
else R.string.notification_fetch_fail
- frostSnackbar(text)
+ frostSnackbar(text, themeProvider)
}
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt
index aa38fffd..61c69f10 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Security.kt
@@ -31,18 +31,21 @@ fun SettingsActivity.getSecurityPrefs(): KPrefAdapterBuilder.() -> Unit = {
descRes = R.string.security_disclaimer_info
}
- checkbox(R.string.enable_biometrics, prefs::biometricsEnabled, {
- launch {
+ checkbox(
+ R.string.enable_biometrics, prefs::biometricsEnabled,
+ {
+ launch {
/*
* For security, we should request authentication when:
* - enabling to ensure that it is supported
* - disabling to ensure that it is permitted
*/
- BiometricUtils.authenticate(this@getSecurityPrefs, prefs, force = true).await()
- prefs.biometricsEnabled = it
- reloadByTitle(R.string.enable_biometrics)
+ BiometricUtils.authenticate(this@getSecurityPrefs, prefs, force = true).await()
+ prefs.biometricsEnabled = it
+ reloadByTitle(R.string.enable_biometrics)
+ }
}
- }) {
+ ) {
descRes = R.string.enable_biometrics_desc
enabler = { BiometricUtils.isSupported(this@getSecurityPrefs) }
}
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 80f83c8d..1860d6f6 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/BiometricUtils.kt
@@ -27,10 +27,10 @@ import androidx.lifecycle.OnLifecycleEvent
import ca.allanwang.kau.utils.string
import com.pitchedapps.frost.R
import com.pitchedapps.frost.prefs.Prefs
+import kotlinx.coroutines.CompletableDeferred
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
-import kotlinx.coroutines.CompletableDeferred
typealias BiometricDeferred = CompletableDeferred<BiometricPrompt.CryptoObject?>
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 13ce2920..ec8aec6c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
@@ -72,20 +72,20 @@ import com.pitchedapps.frost.facebook.formattedFbUrl
import com.pitchedapps.frost.injectors.JsAssets
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
-import java.io.File
-import java.io.IOException
-import java.net.URLEncoder
-import java.nio.charset.StandardCharsets
-import java.util.ArrayList
-import java.util.Locale
+import dagger.hilt.android.scopes.ActivityScoped
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.apache.commons.text.StringEscapeUtils
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import java.io.File
+import java.io.IOException
+import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
+import java.util.ArrayList
+import java.util.Locale
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-03.
@@ -101,9 +101,12 @@ inline fun <reified T : Activity> Context.launchNewTask(
cookieList: ArrayList<CookieEntity> = arrayListOf(),
clearStack: Boolean = false
) {
- startActivity<T>(clearStack, intentBuilder = {
- putParcelableArrayListExtra(EXTRA_COOKIES, cookieList)
- })
+ startActivity<T>(
+ clearStack,
+ intentBuilder = {
+ putParcelableArrayListExtra(EXTRA_COOKIES, cookieList)
+ }
+ )
}
fun Context.launchLogin(cookieList: ArrayList<CookieEntity>, clearStack: Boolean = true) {
@@ -133,9 +136,12 @@ private inline fun <reified T : WebOverlayActivityBase> Context.launchWebOverlay
fbCookie.logout(this@launchWebOverlayImpl)
}
} else if (!(prefs.linksInDefaultApp && resolveActivityForUri(Uri.parse(argUrl)))) {
- startActivity<T>(false, intentBuilder = {
- putExtra(ARG_URL, argUrl)
- })
+ startActivity<T>(
+ false,
+ intentBuilder = {
+ putExtra(ARG_URL, argUrl)
+ }
+ )
}
}
@@ -155,12 +161,14 @@ private fun Context.fadeBundle() = ActivityOptions.makeCustomAnimation(
).toBundle()
fun Context.launchImageActivity(imageUrl: String, text: String? = null, cookie: String? = null) {
- startActivity<ImageActivity>(intentBuilder = {
- putExtras(fadeBundle())
- putExtra(ARG_IMAGE_URL, imageUrl)
- putExtra(ARG_TEXT, text)
- putExtra(ARG_COOKIE, cookie)
- })
+ startActivity<ImageActivity>(
+ intentBuilder = {
+ putExtras(fadeBundle())
+ putExtra(ARG_IMAGE_URL, imageUrl)
+ putExtra(ARG_TEXT, text)
+ putExtra(ARG_COOKIE, cookie)
+ }
+ )
}
fun Activity.launchTabCustomizerActivity() {
@@ -168,30 +176,45 @@ fun Activity.launchTabCustomizerActivity() {
SettingsActivity.ACTIVITY_REQUEST_TABS,
bundleBuilder = {
with(fadeBundle())
- })
+ }
+ )
}
fun WebOverlayActivity.url(): String {
return intent.getStringExtra(ARG_URL) ?: FbItem.FEED.url
}
-fun Activity.setFrostTheme(themeProvider: ThemeProvider, forceTransparent: Boolean = false) {
- val isTransparent =
- forceTransparent || (Color.alpha(themeProvider.bgColor) != 255) || (Color.alpha(
- themeProvider.headerColor
- ) != 255)
- if (themeProvider.bgColor.isColorDark) {
- setTheme(if (isTransparent) R.style.FrostTheme_Transparent else R.style.FrostTheme)
- } else {
- setTheme(if (isTransparent) R.style.FrostTheme_Light_Transparent else R.style.FrostTheme_Light)
+@ActivityScoped
+class ActivityThemer @Inject constructor(
+ private val activity: Activity,
+ private val prefs: Prefs,
+ private val themeProvider: ThemeProvider
+) {
+ fun setFrostTheme(forceTransparent: Boolean = false) {
+ val isTransparent =
+ forceTransparent || (Color.alpha(themeProvider.bgColor) != 255) || (
+ Color.alpha(
+ themeProvider.headerColor
+ ) != 255
+ )
+ if (themeProvider.bgColor.isColorDark) {
+ activity.setTheme(if (isTransparent) R.style.FrostTheme_Transparent else R.style.FrostTheme)
+ } else {
+ activity.setTheme(if (isTransparent) R.style.FrostTheme_Light_Transparent else R.style.FrostTheme_Light)
+ }
}
-}
-
-class ActivityThemeUtils : KoinComponent {
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
+ fun setFrostColors(builder: ActivityThemeUtils.() -> Unit) {
+ val themer = ActivityThemeUtils(prefs = prefs, themeProvider = themeProvider)
+ themer.builder()
+ themer.theme(activity)
+ }
+}
+class ActivityThemeUtils(
+ private val prefs: Prefs,
+ private val themeProvider: ThemeProvider
+) {
private var toolbar: Toolbar? = null
var themeWindow = true
private var texts = mutableListOf<TextView>()
@@ -229,12 +252,6 @@ class ActivityThemeUtils : KoinComponent {
}
}
-inline fun Activity.setFrostColors(builder: ActivityThemeUtils.() -> Unit) {
- val themer = ActivityThemeUtils()
- themer.builder()
- themer.theme(this)
-}
-
fun frostEvent(name: String, vararg events: Pair<String, Any>) {
// todo bind
L.v { "Event: $name ${events.joinToString(", ")}" }
@@ -249,15 +266,23 @@ fun Throwable?.logFrostEvent(text: String) {
frostEvent("Errors", "text" to text, "message" to (this?.message ?: "NA"))
}
-fun Activity.frostSnackbar(@StringRes text: Int, builder: Snackbar.() -> Unit = {}) =
- snackbar(text, Snackbar.LENGTH_LONG, frostSnackbar(builder))
+fun Activity.frostSnackbar(
+ @StringRes text: Int,
+ themeProvider: ThemeProvider,
+ builder: Snackbar.() -> Unit = {}
+) = snackbar(text, Snackbar.LENGTH_LONG, frostSnackbar(themeProvider, builder))
-fun View.frostSnackbar(@StringRes text: Int, builder: Snackbar.() -> Unit = {}) =
- snackbar(text, Snackbar.LENGTH_LONG, frostSnackbar(builder))
+fun View.frostSnackbar(
+ @StringRes text: Int,
+ themeProvider: ThemeProvider,
+ builder: Snackbar.() -> Unit = {}
+) = snackbar(text, Snackbar.LENGTH_LONG, frostSnackbar(themeProvider, builder))
@SuppressLint("RestrictedApi")
-private inline fun frostSnackbar(crossinline builder: Snackbar.() -> Unit): Snackbar.() -> Unit = {
- val themeProvider = ThemeProvider.get()
+private inline fun frostSnackbar(
+ themeProvider: ThemeProvider,
+ crossinline builder: Snackbar.() -> Unit
+): Snackbar.() -> Unit = {
builder()
// hacky workaround, but it has proper checks and shouldn't crash
((view as? FrameLayout)?.getChildAt(0) as? SnackbarContentLayout)?.apply {
@@ -404,18 +429,20 @@ fun Context.frostUri(entry: String): Uri {
inline fun Context.sendFrostEmail(
@StringRes subjectId: Int,
+ prefs: Prefs,
crossinline builder: EmailBuilder.() -> Unit
-) =
- sendFrostEmail(string(subjectId), builder)
+) = sendFrostEmail(string(subjectId), prefs, builder)
-inline fun Context.sendFrostEmail(subjectId: String, crossinline builder: EmailBuilder.() -> Unit) =
- sendEmail("", subjectId) {
- builder()
- addFrostDetails()
- }
+inline fun Context.sendFrostEmail(
+ subjectId: String,
+ prefs: Prefs,
+ crossinline builder: EmailBuilder.() -> Unit
+) = sendEmail("", subjectId) {
+ builder()
+ addFrostDetails(prefs)
+}
-fun EmailBuilder.addFrostDetails() {
- val prefs = Prefs.get()
+fun EmailBuilder.addFrostDetails(prefs: Prefs) {
addItem("Prev version", prefs.prevVersionCode.toString())
val proTag = "FO"
addItem("Random Frost ID", "${prefs.frostId}-$proTag")
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 03dbb9fb..f3c81578 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt
@@ -32,7 +32,7 @@ import com.pitchedapps.frost.prefs.Prefs
/**
* Created by Allan Wang on 2017-07-07.
*/
-fun Context.showWebContextMenu(wc: WebContext, fbCookie: FbCookie) {
+fun Context.showWebContextMenu(wc: WebContext, fbCookie: FbCookie, prefs: Prefs) {
if (wc.isEmpty) return
var title = wc.url ?: string(R.string.menu)
title =
@@ -45,7 +45,7 @@ fun Context.showWebContextMenu(wc: WebContext, fbCookie: FbCookie) {
materialDialog {
title(text = title)
listItems(items = menuItems.map { string(it.textId) }) { _, position, _ ->
- menuItems[position].onClick(this@showWebContextMenu, wc, fbCookie)
+ menuItems[position].onClick(this@showWebContextMenu, wc, fbCookie, prefs)
}
onDismiss {
// showing the dialog interrupts the touch down event, so we must ensure that the viewpager's swipe is enabled
@@ -67,15 +67,16 @@ class WebContext(val unformattedUrl: String?, val text: String?) {
enum class WebContextType(
val textId: Int,
val constraint: (wc: WebContext) -> Boolean,
- val onClick: (c: Context, wc: WebContext, fc: FbCookie) -> Unit
+ val onClick: (c: Context, wc: WebContext, fc: FbCookie, prefs: Prefs) -> Unit
) {
OPEN_LINK(
R.string.open_link,
{ it.hasUrl },
- { c, wc, fc -> c.launchWebOverlay(wc.url!!, fc, Prefs.get()) }),
- 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) })
+ { c, wc, fc, prefs -> c.launchWebOverlay(wc.url!!, fc, prefs) }
+ ),
+ 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) })
;
companion object {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt
index 6eebd36f..e15538b8 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt
@@ -38,17 +38,14 @@ import com.pitchedapps.frost.facebook.profilePictureUrl
import com.pitchedapps.frost.glide.FrostGlide
import com.pitchedapps.frost.glide.GlideApp
import com.pitchedapps.frost.injectors.ThemeProvider
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 2017-06-05.
*/
-class AccountItem(val cookie: CookieEntity?) :
- KauIItem<AccountItem.ViewHolder>(R.layout.view_account, { ViewHolder(it) }, R.id.item_account),
- KoinComponent {
-
- private val themeProvider: ThemeProvider by inject()
+class AccountItem(
+ val cookie: CookieEntity?,
+ private val themeProvider: ThemeProvider
+) : KauIItem<AccountItem.ViewHolder>(R.layout.view_account, { ViewHolder(it) }, R.id.item_account) {
override fun bindView(holder: ViewHolder, payloads: List<Any>) {
super.bindView(holder, payloads)
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 78af4edf..61be271f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/BadgedIcon.kt
@@ -31,20 +31,25 @@ import com.mikepenz.iconics.typeface.IIcon
import com.pitchedapps.frost.databinding.ViewBadgedIconBinding
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-19.
*/
+@AndroidEntryPoint
class BadgedIcon @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : ConstraintLayout(context, attrs, defStyleAttr), KoinComponent {
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
private val binding: ViewBadgedIconBinding =
ViewBadgedIconBinding.inflate(LayoutInflater.from(context), this, true)
@@ -54,7 +59,8 @@ class BadgedIcon @JvmOverloads constructor(
private fun ViewBadgedIconBinding.init() {
val badgeColor =
- prefs.mainActivityLayout.backgroundColor(themeProvider).withAlpha(255).colorToForeground(0.2f)
+ prefs.mainActivityLayout.backgroundColor(themeProvider).withAlpha(255)
+ .colorToForeground(0.2f)
val badgeBackground =
GradientDrawable(
GradientDrawable.Orientation.BOTTOM_TOP,
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt
index 177b8862..124a75df 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostContentView.kt
@@ -42,13 +42,13 @@ import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.kotlin.subscribeDuringJob
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
import kotlinx.coroutines.channels.ReceiveChannel
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
class FrostContentWeb @JvmOverloads constructor(
context: Context,
@@ -76,17 +76,48 @@ abstract class FrostContentView<out T> @JvmOverloads constructor(
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
-) : FrameLayout(context, attrs, defStyleAttr, defStyleRes),
- FrostContentParent, KoinComponent where T : View, T : FrostContentCore {
+) : FrostContentViewBase(context, attrs, defStyleAttr, defStyleRes),
+ FrostContentParent where T : View, T : FrostContentCore {
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
- private val refresh: SwipeRefreshLayout by bindView(R.id.content_refresh)
- private val progress: ProgressBar by bindView(R.id.content_progress)
val coreView: T by bindView(R.id.content_core)
override val core: FrostContentCore
get() = coreView
+}
+
+/**
+ * Subsection of [FrostContentView] that is [AndroidEntryPoint] friendly (no generics)
+ */
+@UseExperimental(ExperimentalCoroutinesApi::class)
+@AndroidEntryPoint
+abstract class FrostContentViewBase(
+ context: Context,
+ attrs: AttributeSet?,
+ defStyleAttr: Int,
+ defStyleRes: Int
+) : FrameLayout(context, attrs, defStyleAttr, defStyleRes),
+ FrostContentParent {
+
+ // No JvmOverloads due to hilt
+ constructor(context: Context) : this(context, null)
+
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : this(
+ context,
+ attrs,
+ defStyleAttr,
+ 0
+ )
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ private val refresh: SwipeRefreshLayout by bindView(R.id.content_refresh)
+ private val progress: ProgressBar by bindView(R.id.content_progress)
/**
* While this can be conflated, there exist situations where we wish to watch refresh cycles.
@@ -129,7 +160,7 @@ abstract class FrostContentView<out T> @JvmOverloads constructor(
*/
protected fun init() {
inflate(context, layoutRes, this)
- coreView.parent = this
+ core.parent = this
reloadThemeSelf()
}
@@ -140,9 +171,7 @@ abstract class FrostContentView<out T> @JvmOverloads constructor(
scope = container
core.bind(container)
refresh.setOnRefreshListener {
- with(coreView) {
- reload(true)
- }
+ core.reload(true)
}
refreshChannel.subscribeDuringJob(scope, ContextHelper.coroutineContext) { r ->
@@ -160,11 +189,11 @@ abstract class FrostContentView<out T> @JvmOverloads constructor(
override fun reloadTheme() {
reloadThemeSelf()
- coreView.reloadTheme()
+ core.reloadTheme()
}
override fun reloadTextSize() {
- coreView.reloadTextSize()
+ core.reloadTextSize()
}
override fun reloadThemeSelf() {
@@ -195,7 +224,7 @@ abstract class FrostContentView<out T> @JvmOverloads constructor(
return false // still in progress; do not bother with load
}
L.v { "Registered transition" }
- with(coreView) {
+ with(core) {
refreshReceiver = refreshChannel.openSubscription().also { receiver ->
scope.launchMain {
var loading = false
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 89009b56..2ab00916 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostRecyclerView.kt
@@ -28,25 +28,25 @@ import com.pitchedapps.frost.contracts.FrostContentCore
import com.pitchedapps.frost.contracts.FrostContentParent
import com.pitchedapps.frost.fragments.RecyclerContentContract
import com.pitchedapps.frost.prefs.Prefs
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-29.
*
*/
@UseExperimental(ExperimentalCoroutinesApi::class)
+@AndroidEntryPoint
class FrostRecyclerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : RecyclerView(context, attrs, defStyleAttr),
- KoinComponent,
- FrostContentCore {
+) : RecyclerView(context, attrs, defStyleAttr), FrostContentCore {
- private val prefs: Prefs by inject()
+ @Inject
+ lateinit var prefs: Prefs
override fun reload(animate: Boolean) = reloadBase(animate)
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 a76aeea0..836d8666 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoViewer.kt
@@ -48,17 +48,18 @@ import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.frostDownload
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-10-13.
*/
+@AndroidEntryPoint
class FrostVideoViewer @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : FrameLayout(context, attrs, defStyleAttr), FrostVideoViewerContract, KoinComponent {
+) : FrameLayout(context, attrs, defStyleAttr), FrostVideoViewerContract {
companion object {
/**
@@ -88,9 +89,14 @@ class FrostVideoViewer @JvmOverloads constructor(
}
}
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
- private val cookieDao: CookieDao by inject()
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var cookieDao: CookieDao
private val binding: ViewVideoBinding =
ViewVideoBinding.inflate(LayoutInflater.from(context), this, true)
@@ -192,12 +198,12 @@ class FrostVideoViewer @JvmOverloads constructor(
fun updateLocation() {
with(binding) {
viewTreeObserver.addOnGlobalLayoutListener(object :
- ViewTreeObserver.OnGlobalLayoutListener {
- override fun onGlobalLayout() {
- video.updateLocation()
- viewTreeObserver.removeOnGlobalLayoutListener(this)
- }
- })
+ ViewTreeObserver.OnGlobalLayoutListener {
+ override fun onGlobalLayout() {
+ video.updateLocation()
+ viewTreeObserver.removeOnGlobalLayoutListener(this)
+ }
+ })
}
}
@@ -206,7 +212,8 @@ class FrostVideoViewer @JvmOverloads constructor(
if (video.isExpanded)
videoToolbar.fadeIn(
duration = CONTROL_ANIMATION_DURATION,
- onStart = { videoToolbar.visible() })
+ onStart = { videoToolbar.visible() }
+ )
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt
index e3a23e12..f04a2f57 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostViewPager.kt
@@ -22,18 +22,23 @@ import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager
import com.pitchedapps.frost.prefs.Prefs
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-07-07.
*
* Basic override to allow us to control swiping
*/
-class FrostViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
- ViewPager(context, attrs), KoinComponent {
+@AndroidEntryPoint
+class FrostViewPager @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null
+) : ViewPager(context, attrs) {
+
+ @Inject
+ lateinit var prefs: Prefs
- private val prefs: Prefs by inject()
var enableSwipe = true
override fun onInterceptTouchEvent(ev: MotionEvent?) =
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt
index ecd8c093..ec012ed5 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostWebView.kt
@@ -43,28 +43,34 @@ import com.pitchedapps.frost.web.FrostChromeClient
import com.pitchedapps.frost.web.FrostJSI
import com.pitchedapps.frost.web.FrostWebViewClient
import com.pitchedapps.frost.web.NestedWebView
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
/**
* Created by Allan Wang on 2017-05-29.
*
*/
+@AndroidEntryPoint
class FrostWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : NestedWebView(context, attrs, defStyleAttr),
- FrostContentCore,
- KoinComponent {
+) : NestedWebView(context, attrs, defStyleAttr), FrostContentCore {
- val fbCookie: FbCookie by inject()
- val prefs: Prefs by inject()
- val themeProvider: ThemeProvider by inject()
- val cookieDao: CookieDao by inject()
+ @Inject
+ lateinit var fbCookie: FbCookie
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var cookieDao: CookieDao
override fun reload(animate: Boolean) {
if (parent.registerTransition(false, animate))
@@ -92,7 +98,7 @@ class FrostWebView @JvmOverloads constructor(
// attempt to get custom client; otherwise fallback to original
frostWebClient = (container as? WebFragment)?.client(this) ?: FrostWebViewClient(this)
webViewClient = frostWebClient
- webChromeClient = FrostChromeClient(this)
+ webChromeClient = FrostChromeClient(this, themeProvider)
addJavascriptInterface(FrostJSI(this), "Frost")
setBackgroundColor(Color.TRANSPARENT)
setDownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
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 c3d5a90e..a0a7e5b1 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/Keywords.kt
@@ -39,20 +39,25 @@ import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.pitchedapps.frost.R
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.prefs.Prefs
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-19.
*/
+@AndroidEntryPoint
class Keywords @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : ConstraintLayout(context, attrs, defStyleAttr), KoinComponent {
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
val editText: AppCompatEditText by bindView(R.id.edit_text)
val addIcon: ImageView by bindView(R.id.add_icon)
val recycler: RecyclerView by bindView(R.id.recycler)
@@ -61,16 +66,21 @@ class Keywords @JvmOverloads constructor(
init {
inflate(context, R.layout.view_keywords, this)
editText.tint(themeProvider.textColor)
- addIcon.setImageDrawable(GoogleMaterial.Icon.gmd_add.keywordDrawable(context, themeProvider))
+ addIcon.setImageDrawable(
+ GoogleMaterial.Icon.gmd_add.keywordDrawable(
+ context,
+ themeProvider
+ )
+ )
addIcon.setOnClickListener {
if (editText.text.isNullOrEmpty()) editText.error =
context.string(R.string.empty_keyword)
else {
- adapter.add(0, KeywordItem(editText.text.toString()))
+ adapter.add(0, KeywordItem(editText.text.toString(), themeProvider))
editText.text?.clear()
}
}
- adapter.add(prefs.notificationKeywords.map { KeywordItem(it) })
+ adapter.add(prefs.notificationKeywords.map { KeywordItem(it, themeProvider) })
recycler.layoutManager = LinearLayoutManager(context)
recycler.adapter = adapter
adapter.addEventHook(object : ClickEventHook<KeywordItem>() {
@@ -96,9 +106,12 @@ class Keywords @JvmOverloads constructor(
private fun IIcon.keywordDrawable(context: Context, themeProvider: ThemeProvider): Drawable =
toDrawable(context, 20, themeProvider.textColor)
-class KeywordItem(val keyword: String) : AbstractItem<KeywordItem.ViewHolder>() {
+class KeywordItem(
+ val keyword: String,
+ private val themeProvider: ThemeProvider
+) : AbstractItem<KeywordItem.ViewHolder>() {
- override fun getViewHolder(v: View): ViewHolder = ViewHolder(v)
+ override fun getViewHolder(v: View): ViewHolder = ViewHolder(v, themeProvider)
override val layoutRes: Int
get() = R.layout.item_keyword
@@ -116,9 +129,11 @@ class KeywordItem(val keyword: String) : AbstractItem<KeywordItem.ViewHolder>()
holder.text.text = null
}
- class ViewHolder(v: View) : RecyclerView.ViewHolder(v), KoinComponent {
+ class ViewHolder(
+ v: View,
+ themeProvider: ThemeProvider
+ ) : RecyclerView.ViewHolder(v) {
- private val themeProvider: ThemeProvider by inject()
val text: AppCompatTextView by bindView(R.id.keyword_text)
val delete: ImageView by bindView(R.id.keyword_delete)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt
index fe85ab9c..187e7d4e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt
@@ -34,25 +34,30 @@ import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.createFreshFile
import com.pitchedapps.frost.utils.isFacebookUrl
-import java.io.File
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import java.io.File
+import javax.inject.Inject
/**
* Created by Allan Wang on 2018-01-05.
*
* A barebone webview with a refresh listener
*/
+@AndroidEntryPoint
class DebugWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : WebView(context, attrs, defStyleAttr), KoinComponent {
+) : WebView(context, attrs, defStyleAttr) {
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
var onPageFinished: (String?) -> Unit = {}
init {
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 43b7071e..e687dd2d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt
@@ -32,6 +32,7 @@ import com.afollestad.materialdialogs.callbacks.onDismiss
import com.afollestad.materialdialogs.input.input
import com.pitchedapps.frost.R
import com.pitchedapps.frost.contracts.ActivityContract
+import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.frostSnackbar
import com.pitchedapps.frost.views.FrostWebView
@@ -46,7 +47,10 @@ import kotlinx.coroutines.channels.SendChannel
/**
* The default chrome client
*/
-class FrostChromeClient(web: FrostWebView) : WebChromeClient() {
+class FrostChromeClient(
+ web: FrostWebView,
+ private val themeProvider: ThemeProvider
+) : WebChromeClient() {
private val refresh: SendChannel<Boolean> = web.parent.refreshChannel
private val progress: SendChannel<Int> = web.parent.progressChannel
@@ -80,7 +84,7 @@ class FrostChromeClient(web: FrostWebView) : WebChromeClient() {
fileChooserParams: FileChooserParams
): Boolean {
activity?.openFileChooser(filePathCallback, fileChooserParams)
- ?: webView.frostSnackbar(R.string.file_chooser_not_found)
+ ?: webView.frostSnackbar(R.string.file_chooser_not_found, themeProvider)
return activity != null
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
index 12e10e10..0d7bbb79 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
@@ -84,7 +84,8 @@ class FrostJSI(val web: FrostWebView) {
web.post {
context.showWebContextMenu(
WebContext(url.takeIf { it.isIndependent }, text),
- fbCookie
+ fbCookie,
+ prefs
)
}
}
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 f38e5ced..5586d479 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt
@@ -21,8 +21,8 @@ import android.webkit.WebResourceResponse
import android.webkit.WebView
import com.pitchedapps.frost.utils.FrostPglAdBlock
import com.pitchedapps.frost.utils.L
-import java.io.ByteArrayInputStream
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import java.io.ByteArrayInputStream
/**
* Created by Allan Wang on 2017-07-13.
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 fadbadf9..bcfcc109 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
@@ -42,23 +42,30 @@ import com.pitchedapps.frost.injectors.jsInject
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.isFacebookUrl
+import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.coroutineScope
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-29.
*/
+@AndroidEntryPoint
class LoginWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : WebView(context, attrs, defStyleAttr), KoinComponent {
+) : WebView(context, attrs, defStyleAttr) {
+
+ @Inject
+ lateinit var fbCookie: FbCookie
+
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
- private val fbCookie: FbCookie by inject()
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
private val completable: CompletableDeferred<CookieEntity> = CompletableDeferred()
private lateinit var progressCallback: (Int) -> Unit
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
index da0ebf0d..294c2ac1 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
@@ -30,12 +30,17 @@ import androidx.core.view.ViewCompat
*
* Webview extension that handles nested scrolls
*/
-open class NestedWebView @JvmOverloads constructor(
+open class NestedWebView(
context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
+ attrs: AttributeSet?,
+ defStyleAttr: Int
) : WebView(context, attrs, defStyleAttr), NestedScrollingChild {
+ // No JvmOverloads due to hilt
+ constructor(context: Context) : this(context, null)
+
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+
private lateinit var childHelper: NestedScrollingChildHelper
private var lastY: Int = 0
private val scrollOffset = IntArray(2)
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 3bf37f7d..9efe83f6 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/widgets/NotificationWidget.kt
@@ -48,13 +48,17 @@ import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.services.NotificationContent
import com.pitchedapps.frost.services.NotificationType
import com.pitchedapps.frost.utils.toReadableTime
-import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
-class NotificationWidget : AppWidgetProvider(), KoinComponent {
+@AndroidEntryPoint
+class NotificationWidget : AppWidgetProvider() {
- private val prefs: Prefs by inject()
- private val themeProvider: ThemeProvider by inject()
+ @Inject
+ lateinit var prefs: Prefs
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
override fun onUpdate(
context: Context,
@@ -142,9 +146,17 @@ private fun RemoteViews.setIcon(
}
}
+@AndroidEntryPoint
class NotificationWidgetService : RemoteViewsService() {
+
+ @Inject
+ lateinit var themeProvider: ThemeProvider
+
+ @Inject
+ lateinit var notifDao: NotificationDao
+
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory =
- NotificationWidgetDataProvider(this, intent)
+ NotificationWidgetDataProvider(this, intent, themeProvider, notifDao)
companion object {
fun createIntent(context: Context, type: NotificationType, userId: Long): Intent =
@@ -154,13 +166,12 @@ class NotificationWidgetService : RemoteViewsService() {
}
}
-class NotificationWidgetDataProvider(val context: Context, val intent: Intent) :
- RemoteViewsService.RemoteViewsFactory,
- KoinComponent {
-
- private val themeProvider: ThemeProvider by inject()
-
- private val notifDao: NotificationDao by inject()
+class NotificationWidgetDataProvider(
+ private val context: Context,
+ private val intent: Intent,
+ private val themeProvider: ThemeProvider,
+ private val notifDao: NotificationDao
+) : RemoteViewsService.RemoteViewsFactory {
@Volatile
private var content: List<NotificationContent> = emptyList()
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt
index 4064a5ff..48587ea9 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/debugger/OfflineWebsiteTest.kt
@@ -18,6 +18,12 @@ package com.pitchedapps.frost.debugger
import com.pitchedapps.frost.facebook.FB_URL_BASE
import com.pitchedapps.frost.internal.COOKIE
+import kotlinx.coroutines.runBlocking
+import okhttp3.mockwebserver.Dispatcher
+import okhttp3.mockwebserver.MockResponse
+import okhttp3.mockwebserver.MockWebServer
+import okhttp3.mockwebserver.RecordedRequest
+import org.junit.Assume.assumeTrue
import java.io.File
import java.util.zip.ZipFile
import kotlin.test.AfterTest
@@ -27,12 +33,6 @@ import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
-import kotlinx.coroutines.runBlocking
-import okhttp3.mockwebserver.Dispatcher
-import okhttp3.mockwebserver.MockResponse
-import okhttp3.mockwebserver.MockWebServer
-import okhttp3.mockwebserver.RecordedRequest
-import org.junit.Assume.assumeTrue
/**
* Created by Allan Wang on 05/01/18.
@@ -46,8 +46,9 @@ class OfflineWebsiteTest {
fun before() {
val buildPath =
if (File("").absoluteFile.name == "app") "build/offline_test" else "app/build/offline_test"
- baseDir = File(buildPath)
- assertTrue(baseDir.deleteRecursively(), "Failed to clean base dir")
+ val rootDir = File(buildPath)
+ rootDir.deleteRecursively()
+ baseDir = rootDir.resolve(System.currentTimeMillis().toString())
server = MockWebServer()
server.start()
}
@@ -61,7 +62,7 @@ class OfflineWebsiteTest {
url: String = server.url("/").toString(),
cookie: String = ""
): ZipFile {
- val name = "test${System.currentTimeMillis()}"
+ val name = "test"
runBlocking {
val success = OfflineWebsite(url, cookie, baseDir = baseDir)
.loadAndZip(name)
@@ -247,7 +248,8 @@ class OfflineWebsiteTest {
assertEquals(5, zip.size(), "2 files expected")
zip.assertContentEquals(
- "index.html", content
+ "index.html",
+ content
.replace(css1Url.toString(), "assets/a0_1.css")
.replace(css2Url.toString(), "assets/a1_2.css")
.replace(js1Url.toString(), "assets/a2_1.js.txt")
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbDomTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbDomTest.kt
index 544d904f..9472adfe 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbDomTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbDomTest.kt
@@ -18,9 +18,9 @@ package com.pitchedapps.frost.facebook
import com.pitchedapps.frost.internal.authDependent
import com.pitchedapps.frost.internal.testJsoup
-import kotlin.test.assertNotNull
import org.junit.BeforeClass
import org.junit.Test
+import kotlin.test.assertNotNull
class FbDomTest {
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbRegexTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbRegexTest.kt
index 08957ea9..d37e55c1 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbRegexTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbRegexTest.kt
@@ -16,9 +16,9 @@
*/
package com.pitchedapps.frost.facebook
-import kotlin.test.assertEquals
import org.apache.commons.text.StringEscapeUtils
import org.junit.Test
+import kotlin.test.assertEquals
/**
* Created by Allan Wang on 24/12/17.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt
index 433fdb2a..558cffa1 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/FbUrlTest.kt
@@ -18,10 +18,10 @@ package com.pitchedapps.frost.facebook
import com.pitchedapps.frost.utils.isImageUrl
import com.pitchedapps.frost.utils.isIndirectImageUrl
+import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
-import org.junit.Test
/**
* Created by Allan Wang on 2017-07-07.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/parsers/FbParseTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/parsers/FbParseTest.kt
index e3b449c0..a5955101 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/facebook/parsers/FbParseTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/parsers/FbParseTest.kt
@@ -20,12 +20,12 @@ import com.pitchedapps.frost.internal.COOKIE
import com.pitchedapps.frost.internal.assertComponentsNotEmpty
import com.pitchedapps.frost.internal.assertDescending
import com.pitchedapps.frost.internal.authDependent
+import org.junit.BeforeClass
+import org.junit.Test
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlin.test.fail
-import org.junit.BeforeClass
-import org.junit.Test
/**
* Created by Allan Wang on 24/12/17.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/facebook/requests/FbFullImageTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/facebook/requests/FbFullImageTest.kt
index 64a9fe31..cb8dd5e1 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/facebook/requests/FbFullImageTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/facebook/requests/FbFullImageTest.kt
@@ -18,10 +18,10 @@ package com.pitchedapps.frost.facebook.requests
import com.pitchedapps.frost.internal.COOKIE
import com.pitchedapps.frost.internal.authDependent
-import kotlin.test.assertNotNull
import kotlinx.coroutines.runBlocking
import org.junit.BeforeClass
import org.junit.Test
+import kotlin.test.assertNotNull
/**
* Created by Allan Wang on 12/04/18.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/internal/Internal.kt b/app/src/test/kotlin/com/pitchedapps/frost/internal/Internal.kt
index 17ce847c..7c12ba73 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/internal/Internal.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/internal/Internal.kt
@@ -20,6 +20,7 @@ import com.pitchedapps.frost.facebook.FB_USER_MATCHER
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.get
import com.pitchedapps.frost.utils.frostJsoup
+import org.junit.Assume
import java.io.File
import java.io.FileInputStream
import java.util.Properties
@@ -27,7 +28,6 @@ import kotlin.reflect.full.starProjectedType
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
-import org.junit.Assume
/**
* Created by Allan Wang on 21/12/17.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/kotlin/FlyweightTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/kotlin/FlyweightTest.kt
index 20cdd5ec..89289322 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/kotlin/FlyweightTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/kotlin/FlyweightTest.kt
@@ -16,6 +16,11 @@
*/
package com.pitchedapps.frost.kotlin
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.runBlocking
+import org.junit.Rule
+import org.junit.rules.Timeout
import java.util.concurrent.atomic.AtomicInteger
import kotlin.test.BeforeTest
import kotlin.test.Test
@@ -23,11 +28,6 @@ import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlin.test.fail
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.runBlocking
-import org.junit.Rule
-import org.junit.rules.Timeout
class FlyweightTest {
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/prefs/PrefsTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/prefs/PrefsTest.kt
index 28c0c899..a51dc460 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/prefs/PrefsTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/prefs/PrefsTest.kt
@@ -16,9 +16,9 @@
*/
package com.pitchedapps.frost.prefs
-import kotlin.test.assertEquals
import org.junit.Before
import org.junit.Test
+import kotlin.test.assertEquals
/**
* Created by Allan Wang on 2017-05-31.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/utils/BuildUtilsTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/utils/BuildUtilsTest.kt
index 596693e7..a40372af 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/utils/BuildUtilsTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/BuildUtilsTest.kt
@@ -17,10 +17,10 @@
package com.pitchedapps.frost.utils
import com.pitchedapps.frost.BuildConfig
+import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
-import org.junit.Test
class BuildUtilsTest {
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 cb427faa..2744d0d8 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/CoroutineTest.kt
@@ -17,13 +17,6 @@
package com.pitchedapps.frost.utils
import com.pitchedapps.frost.kotlin.Flyweight
-import java.util.concurrent.Executors
-import kotlin.coroutines.EmptyCoroutineContext
-import kotlin.test.Ignore
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
@@ -33,12 +26,26 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
-import kotlinx.coroutines.channels.count
import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.count
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
+import java.util.concurrent.Executors
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlin.test.Ignore
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
/**
* Collection of tests around coroutines
@@ -67,6 +74,7 @@ class CoroutineTest {
): List<T> =
withContext(Dispatchers.IO) {
val data = mutableListOf<T>()
+ channel.receiveAsFlow()
for (c in channel) {
data.add(c)
if (shouldEnd(c)) break
@@ -118,6 +126,9 @@ class CoroutineTest {
}
}
+ private fun <T : Any> SharedFlow<T?>.takeUntilNull(): Flow<T> =
+ takeWhile { it != null }.filterNotNull()
+
/**
* Sanity check to ensure that contexts are being honoured
*/
@@ -128,13 +139,10 @@ class CoroutineTest {
Thread(r, mainTag)
}.asCoroutineDispatcher()
- val channel = BroadcastChannel<String>(100)
-
+ val flow = MutableSharedFlow<String?>(100)
runBlocking(Dispatchers.IO) {
- val receiver1 = channel.openSubscription()
- val receiver2 = channel.openSubscription()
launch(mainDispatcher) {
- for (thread in receiver1) {
+ flow.takeUntilNull().collect { thread ->
assertTrue(
Thread.currentThread().name.startsWith(mainTag),
"Channel should be received in main thread"
@@ -146,10 +154,11 @@ class CoroutineTest {
}
}
listOf(EmptyCoroutineContext, Dispatchers.IO, Dispatchers.Default, Dispatchers.IO).map {
- async(it) { channel.send(Thread.currentThread().name) }
+ async(it) { flow.emit(Thread.currentThread().name) }
}.joinAll()
- channel.close()
- assertEquals(4, receiver2.count(), "Not all events received")
+ flow.emit(null)
+ val count = flow.takeUntilNull().count()
+ assertEquals(4, count, "Not all events received")
}
}
@@ -159,6 +168,7 @@ class CoroutineTest {
* Events should be consumed when there is no pending consumer on previous elements.
*/
@Test
+ @Ignore("Move to flow")
fun throttledChannel() {
val channel = Channel<Int>(Channel.CONFLATED)
runBlocking {
@@ -177,7 +187,7 @@ class CoroutineTest {
val received = deferred.await()
assertTrue(
received.size < 20,
- "Received data should be throttled; expected that around 1/10th of all events are consumed"
+ "Received data should be throttled; expected that around 1/10th of all events are consumed, but received ${received.size}"
)
println(received)
}
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/utils/JsoupCleanerTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/utils/JsoupCleanerTest.kt
index 7c277dc7..7ec01e6d 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/utils/JsoupCleanerTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/JsoupCleanerTest.kt
@@ -16,8 +16,8 @@
*/
package com.pitchedapps.frost.utils
-import kotlin.test.assertEquals
import org.junit.Test
+import kotlin.test.assertEquals
/**
* Created by Allan Wang on 2017-08-10.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/utils/StringEscapeUtilsTest.kt b/app/src/test/kotlin/com/pitchedapps/frost/utils/StringEscapeUtilsTest.kt
index 408dd214..f5ea56ae 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/utils/StringEscapeUtilsTest.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/StringEscapeUtilsTest.kt
@@ -16,8 +16,8 @@
*/
package com.pitchedapps.frost.utils
-import kotlin.test.assertEquals
import org.junit.Test
+import kotlin.test.assertEquals
/**
* Created by Allan Wang on 11/03/18.
diff --git a/app/src/test/kotlin/com/pitchedapps/frost/utils/UrlTests.kt b/app/src/test/kotlin/com/pitchedapps/frost/utils/UrlTests.kt
index ac6068ef..485d0a7a 100644
--- a/app/src/test/kotlin/com/pitchedapps/frost/utils/UrlTests.kt
+++ b/app/src/test/kotlin/com/pitchedapps/frost/utils/UrlTests.kt
@@ -17,10 +17,10 @@
package com.pitchedapps.frost.utils
import com.pitchedapps.frost.facebook.FACEBOOK_COM
+import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
-import org.junit.Test
/**
* Created by Allan Wang on 2017-11-15.
diff --git a/build.gradle b/build.gradle
index 0a7aae8a..013222fb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,6 +11,7 @@ buildscript {
classpath kau.Plugins.kotlin
classpath kau.Plugins.spotless
classpath kau.Plugins.dexCount
+ classpath kau.Plugins.hilt
classpath kau.Plugins.gitVersion
}
diff --git a/spotless.gradle b/spotless.gradle
index 29474895..16e1ff1a 100644
--- a/spotless.gradle
+++ b/spotless.gradle
@@ -3,7 +3,7 @@ apply plugin: "com.diffplug.spotless"
spotless {
kotlin {
target "**/*.kt"
- ktlint()
+ ktlint("0.41.0").userData(["disabled_rules": "no-wildcard-imports"])
licenseHeaderFile '../spotless.license.kt'
trimTrailingWhitespace()
endWithNewline()