diff --git a/CLAUDE.md b/CLAUDE.md index cea3944bd..9d77cfb63 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,7 +3,7 @@ ## Build and Development - `./gradlew assembleFreeDebug` will compile the debug version of the app -- For fast feedback, run single tests i.e. `./gradlew :capy:testDebugUnitTest --tests com.jocmp.capy.persistence.ArticleRecordsTest` replacing the module - `:capy` - and Java package accordingly +- For fast feedback, run single tests i.e. `./gradlew :capy:test --tests com.jocmp.capy.persistence.ArticleRecordsTest` replacing the module - `:capy` - and Java package accordingly. Note `:capy` is a JVM module (use `:capy:test`); Android modules like `:app` use the variant task `testFreeDebugUnitTest` - `make test` will run all tests via Fastlane. - When modifying the `.js` and `.liquid` files, be sure to run `make` to compile those assets, and `make check` to typecheck diff --git a/app/src/main/java/com/capyreader/app/CommonModule.kt b/app/src/main/java/com/capyreader/app/CommonModule.kt index a45711e2c..e41cc080d 100644 --- a/app/src/main/java/com/capyreader/app/CommonModule.kt +++ b/app/src/main/java/com/capyreader/app/CommonModule.kt @@ -6,6 +6,7 @@ import com.capyreader.app.common.AndroidClientCertManager import com.capyreader.app.common.AppFaviconPolicy import com.capyreader.app.common.SharedPreferenceStoreProvider import com.capyreader.app.preferences.AppPreferences +import com.capyreader.app.refresher.RefreshScheduler import com.jocmp.capy.AccountManager import com.jocmp.capy.ClientCertManager import com.jocmp.capy.DatabaseProvider @@ -24,6 +25,7 @@ internal val common = module { single { AndroidDatabaseProvider(context = get()) } single { AndroidClientCertManager(context = get()) } single { + val userAgent = lazy { WebSettings.getDefaultUserAgent(androidContext()) } AccountManager( rootFolder = androidContext().filesDir.toURI(), databaseProvider = get(), @@ -31,11 +33,12 @@ internal val common = module { preferenceStoreProvider = get(), faviconPolicy = AppFaviconPolicy(get()), clientCertManager = get(), - userAgent = WebSettings.getDefaultUserAgent(androidContext()), + userAgent = { userAgent.value }, acceptLanguage = Locale.getDefault().toAcceptLanguageTag(), ) } single { AppPreferences(get()) } + single { RefreshScheduler(get(), get()) } } private fun Locale.toAcceptLanguageTag(): String { diff --git a/app/src/main/java/com/capyreader/app/MainApplication.kt b/app/src/main/java/com/capyreader/app/MainApplication.kt index 52bbd67ab..37ac8d37b 100644 --- a/app/src/main/java/com/capyreader/app/MainApplication.kt +++ b/app/src/main/java/com/capyreader/app/MainApplication.kt @@ -12,7 +12,6 @@ import coil3.svg.SvgDecoder import coil3.video.VideoFrameDecoder import com.capyreader.app.common.AndroidLogging import com.capyreader.app.preferences.AppPreferences -import com.capyreader.app.refresher.RefreshScheduler import com.capyreader.app.ui.widget.HeadlinesWidgetReceiver import com.capyreader.app.ui.widget.SpotlightWidgetReceiver import com.google.android.material.color.DynamicColors @@ -39,16 +38,11 @@ class MainApplication : Application(), SingletonImageLoader.Factory { if (get().isLoggedIn) { loadAccountModules() - initializeRefreshScheduler() } loadWidgetPreview() } - private fun initializeRefreshScheduler() { - get().initialize() - } - override fun newImageLoader(context: PlatformContext): ImageLoader { return ImageLoader.Builder(context) .components { diff --git a/app/src/main/java/com/capyreader/app/refresher/RefresherModule.kt b/app/src/main/java/com/capyreader/app/refresher/RefresherModule.kt index 79cab65c4..eacf25b13 100644 --- a/app/src/main/java/com/capyreader/app/refresher/RefresherModule.kt +++ b/app/src/main/java/com/capyreader/app/refresher/RefresherModule.kt @@ -5,6 +5,5 @@ import org.koin.dsl.module val refresherModule = module { single { FeedRefresher(account = get(), get(), get(), get()) } - single { RefreshScheduler(get(), get()) } worker { RefreshFeedsWorker(get(), get()) } } diff --git a/app/src/main/java/com/capyreader/app/ui/accounts/AddAccountViewModel.kt b/app/src/main/java/com/capyreader/app/ui/accounts/AddAccountViewModel.kt index bff546291..efbbc39b7 100644 --- a/app/src/main/java/com/capyreader/app/ui/accounts/AddAccountViewModel.kt +++ b/app/src/main/java/com/capyreader/app/ui/accounts/AddAccountViewModel.kt @@ -5,10 +5,12 @@ import com.jocmp.capy.AccountManager import com.jocmp.capy.accounts.Source import com.capyreader.app.preferences.AppPreferences import com.capyreader.app.loadAccountModules +import com.capyreader.app.refresher.RefreshScheduler class AddAccountViewModel( private val accountManager: AccountManager, private val appPreferences: AppPreferences, + private val refreshScheduler: RefreshScheduler, ) : ViewModel() { fun addLocalAccount() { val accountID = accountManager.createAccount(source = Source.LOCAL) @@ -16,6 +18,8 @@ class AddAccountViewModel( selectAccount(accountID) loadAccountModules() + + refreshScheduler.initialize() } private fun selectAccount(id: String) { diff --git a/app/src/main/java/com/capyreader/app/ui/accounts/LoginModule.kt b/app/src/main/java/com/capyreader/app/ui/accounts/LoginModule.kt index d407b36a8..db2551a7b 100644 --- a/app/src/main/java/com/capyreader/app/ui/accounts/LoginModule.kt +++ b/app/src/main/java/com/capyreader/app/ui/accounts/LoginModule.kt @@ -7,7 +7,8 @@ val loginModule = module { viewModel { AddAccountViewModel( accountManager = get(), - appPreferences = get() + appPreferences = get(), + refreshScheduler = get(), ) } viewModel { @@ -16,6 +17,7 @@ val loginModule = module { accountManager = get(), appPreferences = get(), clientCertManager = get(), + refreshScheduler = get(), ) } viewModel { diff --git a/app/src/main/java/com/capyreader/app/ui/accounts/LoginViewModel.kt b/app/src/main/java/com/capyreader/app/ui/accounts/LoginViewModel.kt index 4a90c36f3..47ef8802c 100644 --- a/app/src/main/java/com/capyreader/app/ui/accounts/LoginViewModel.kt +++ b/app/src/main/java/com/capyreader/app/ui/accounts/LoginViewModel.kt @@ -11,6 +11,7 @@ import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.capyreader.app.loadAccountModules import com.capyreader.app.preferences.AppPreferences +import com.capyreader.app.refresher.RefreshScheduler import com.capyreader.app.ui.Route import com.jocmp.capy.AccountManager import com.jocmp.capy.ClientCertManager @@ -30,6 +31,7 @@ class LoginViewModel( private val accountManager: AccountManager, private val appPreferences: AppPreferences, private val clientCertManager: ClientCertManager, + private val refreshScheduler: RefreshScheduler, ) : ViewModel() { private var _username by mutableStateOf("") private var _password by mutableStateOf("") @@ -158,6 +160,8 @@ class LoginViewModel( selectAccount(accountID) loadAccountModules() + + refreshScheduler.initialize() } private fun selectAccount(id: String) { diff --git a/bench/src/main/kotlin/com/jocmp/bench/BenchAccount.kt b/bench/src/main/kotlin/com/jocmp/bench/BenchAccount.kt index 5453d62ae..0857e6285 100644 --- a/bench/src/main/kotlin/com/jocmp/bench/BenchAccount.kt +++ b/bench/src/main/kotlin/com/jocmp/bench/BenchAccount.kt @@ -52,7 +52,7 @@ fun loadOrCreateAccount(benchDir: File, config: BenchConfig): Pair builder }, - private val userAgent: String, + private val userAgent: () -> String, private val acceptLanguage: String, private val localHttpClient: OkHttpClient = LocalOkHttpClient.forAccount(path = cacheDirectory), val delegate: AccountDelegate = when (source) { diff --git a/capy/src/main/java/com/jocmp/capy/AccountManager.kt b/capy/src/main/java/com/jocmp/capy/AccountManager.kt index 51db22e0c..e959f5d8a 100644 --- a/capy/src/main/java/com/jocmp/capy/AccountManager.kt +++ b/capy/src/main/java/com/jocmp/capy/AccountManager.kt @@ -15,7 +15,7 @@ class AccountManager( private val preferenceStoreProvider: PreferenceStoreProvider, private val faviconPolicy: FaviconPolicy, private val clientCertManager: ClientCertManager = ClientCertManager { builder, _ -> builder }, - private val userAgent: String, + private val userAgent: () -> String, private val acceptLanguage: String, ) { fun findByID( diff --git a/capy/src/main/java/com/jocmp/capy/UserAgentInterceptor.kt b/capy/src/main/java/com/jocmp/capy/UserAgentInterceptor.kt index e2d52a87c..04dd7b2ed 100644 --- a/capy/src/main/java/com/jocmp/capy/UserAgentInterceptor.kt +++ b/capy/src/main/java/com/jocmp/capy/UserAgentInterceptor.kt @@ -19,13 +19,13 @@ class UserAgentInterceptor(private val userAgent: String = USER_AGENT) : Interce } class BrowserHeadersInterceptor( - private val userAgent: String, + private val userAgent: () -> String, private val acceptLanguage: String, ) : Interceptor { override fun intercept(chain: Chain): Response { val originalRequest = chain.request() val request = originalRequest.newBuilder() - .header("User-Agent", userAgent) + .header("User-Agent", userAgent()) .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8") .header("Accept-Language", acceptLanguage) .header("Sec-Fetch-Dest", "document") diff --git a/capy/src/main/java/com/jocmp/capy/accounts/FaviconFinder.kt b/capy/src/main/java/com/jocmp/capy/accounts/FaviconFinder.kt index 99c38ff1d..6e59e72e0 100644 --- a/capy/src/main/java/com/jocmp/capy/accounts/FaviconFinder.kt +++ b/capy/src/main/java/com/jocmp/capy/accounts/FaviconFinder.kt @@ -12,7 +12,7 @@ import java.net.URL class FaviconFinder( private val httpClient: OkHttpClient, private val faviconPolicy: FaviconPolicy, - private val userAgent: String = "", + private val userAgent: () -> String = { "" }, private val acceptLanguage: String = "", ) { suspend fun find(url: URL): String? { diff --git a/capy/src/main/java/com/jocmp/capy/articles/ArticleContent.kt b/capy/src/main/java/com/jocmp/capy/articles/ArticleContent.kt index e12dee99c..e35047fe0 100644 --- a/capy/src/main/java/com/jocmp/capy/articles/ArticleContent.kt +++ b/capy/src/main/java/com/jocmp/capy/articles/ArticleContent.kt @@ -11,7 +11,7 @@ import java.net.URL class ArticleContent( client: OkHttpClient, - userAgent: String, + userAgent: () -> String, acceptLanguage: String, ) { private val httpClient = diff --git a/capy/src/test/java/com/jocmp/capy/AccountManagerTest.kt b/capy/src/test/java/com/jocmp/capy/AccountManagerTest.kt index 40d11b555..f1a3428a7 100644 --- a/capy/src/test/java/com/jocmp/capy/AccountManagerTest.kt +++ b/capy/src/test/java/com/jocmp/capy/AccountManagerTest.kt @@ -22,7 +22,7 @@ class AccountManagerTest { cacheDirectory = rootFolder.newFolder().toURI(), databaseProvider = InMemoryDatabaseProvider, faviconPolicy = FakeFaviconPolicy, - userAgent = "TestUserAgent", + userAgent = { "TestUserAgent" }, acceptLanguage = "en-US", ) } diff --git a/capy/src/test/java/com/jocmp/capy/accounts/ArticleContentTest.kt b/capy/src/test/java/com/jocmp/capy/accounts/ArticleContentTest.kt index 477fdcc95..143753c0d 100644 --- a/capy/src/test/java/com/jocmp/capy/accounts/ArticleContentTest.kt +++ b/capy/src/test/java/com/jocmp/capy/accounts/ArticleContentTest.kt @@ -50,7 +50,7 @@ class ArticleContentTest { fun setup() { extractor = ArticleContent( client = client, - userAgent = "TestUserAgent", + userAgent = { "TestUserAgent" }, acceptLanguage = "en-US", ) } diff --git a/capy/src/test/java/com/jocmp/capy/fixtures/AccountFixture.kt b/capy/src/test/java/com/jocmp/capy/fixtures/AccountFixture.kt index 4d4a8928d..6f3b2d0d9 100644 --- a/capy/src/test/java/com/jocmp/capy/fixtures/AccountFixture.kt +++ b/capy/src/test/java/com/jocmp/capy/fixtures/AccountFixture.kt @@ -29,7 +29,7 @@ object AccountFixture { source = source, delegate = accountDelegate, faviconPolicy = FakeFaviconPolicy, - userAgent = "TestUserAgent", + userAgent = { "TestUserAgent" }, acceptLanguage = "en-US", ) }