1
0
mirror of https://github.com/AllanWang/Frost-for-Facebook.git synced 2024-11-08 12:02:33 +01:00

Add back custom component. Original issue was because of inline value classes

This commit is contained in:
Allan Wang 2023-06-20 23:52:15 -07:00
parent 36a38deb10
commit 8c833bc97f
No known key found for this signature in database
GPG Key ID: C93E3F9C679D7A56
12 changed files with 131 additions and 95 deletions

View File

@ -29,9 +29,7 @@ import com.pitchedapps.frost.ext.launchActivity
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.main.MainActivity
import com.pitchedapps.frost.web.state.FrostWebStore
import com.pitchedapps.frost.web.state.TabAction
import com.pitchedapps.frost.web.state.TabListAction
import com.pitchedapps.frost.web.state.state.HomeTabSessionState
import com.pitchedapps.frost.web.usecases.UseCases
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
@ -53,6 +51,7 @@ class StartActivity : ComponentActivity() {
@Inject lateinit var dataStore: FrostDataStore
@Inject lateinit var store: FrostWebStore
@Inject lateinit var useCases: UseCases
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -63,22 +62,7 @@ class StartActivity : ComponentActivity() {
logger.atInfo().log("Starting Frost with id %s", id)
// TODO load real tabs
store.dispatch(TabListAction.SetHomeTabs(data = listOf(FbItem.Feed, FbItem.Menu)))
// Test something scrollable
// store.dispatch(
// TabAction(
// tabId = HomeTabSessionState.homeTabId(0),
// TabAction.ContentAction.UpdateUrlAction(
// "https://github.com/AllanWang/Frost-for-Facebook"
// ),
// ),
// )
store.dispatch(
TabAction(
tabId = HomeTabSessionState.homeTabId(1),
TabAction.ContentAction.UpdateUrlAction("https://github.com/AllanWang/KAU"),
),
)
useCases.homeTabs.setHomeTabs(listOf(FbItem.Feed, FbItem.Menu))
launchActivity<MainActivity>(
intentBuilder = {

View File

@ -16,6 +16,7 @@
*/
package com.pitchedapps.frost.components
import com.pitchedapps.frost.web.usecases.UseCases
import javax.inject.Inject
import javax.inject.Singleton

View File

@ -39,7 +39,10 @@ import com.pitchedapps.frost.web.state.TabAction.ResponseAction.WebStepResponseA
import com.pitchedapps.frost.web.state.get
import com.pitchedapps.frost.web.state.state.ContentState
import com.pitchedapps.frost.webview.FrostChromeClient
import com.pitchedapps.frost.webview.FrostWeb
import com.pitchedapps.frost.webview.FrostWebScoped
import com.pitchedapps.frost.webview.FrostWebViewClient
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
@ -48,8 +51,11 @@ import kotlinx.coroutines.launch
import mozilla.components.lib.state.ext.flow
import mozilla.components.lib.state.ext.observeAsState
class FrostWebCompose(
val tabId: WebTargetId,
@FrostWebScoped
class FrostWebCompose
@Inject
internal constructor(
@FrostWeb val tabId: WebTargetId,
private val store: FrostWebStore,
private val client: FrostWebViewClient,
private val chromeClient: FrostChromeClient,

View File

@ -21,14 +21,19 @@ import com.pitchedapps.frost.proto.Account
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
/*
* Cannot use inline value classes with Dagger due to Kapt:
* https://github.com/google/dagger/issues/2930
*/
/**
* Representation of unique frost account id.
*
* Account ids are identifiers specific to Frost, and group ids/info from other sites.
*/
@JvmInline value class FrostAccountId(val id: Long)
data class FrostAccountId(val id: Long)
@JvmInline value class WebTargetId(val id: String)
data class WebTargetId(val id: String)
/**
* Representation of gecko context id.

View File

@ -41,7 +41,6 @@ internal constructor(
val components: FrostComponents,
val store: FrostWebStore,
val frostWebComposer: FrostWebComposer,
// sample: FrostWebEntrySample,
) : ViewModel() {
val contextIdFlow: Flow<GeckoContextId?> =

View File

@ -31,7 +31,7 @@ class HomeTabsUseCases @Inject internal constructor(private val store: FrostWebS
*
* If there are existing tabs, they will be replaced.
*/
fun createHomeTabs(items: List<FbItem>) {
fun setHomeTabs(items: List<FbItem>) {
store.dispatch(SetHomeTabs(items))
}

View File

@ -0,0 +1,90 @@
/*
* Copyright 2023 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.web.usecases
import com.pitchedapps.frost.ext.WebTargetId
import com.pitchedapps.frost.web.state.FrostWebStore
import com.pitchedapps.frost.web.state.TabAction
import javax.inject.Inject
class TabUseCases
@Inject
internal constructor(
private val store: FrostWebStore,
val requests: TabRequestUseCases,
val responses: TabResponseUseCases,
) {
fun updateUrl(tabId: WebTargetId, url: String) {
store.dispatch(TabAction(tabId = tabId, action = TabAction.ContentAction.UpdateUrlAction(url)))
}
fun updateTitle(tabId: WebTargetId, title: String?) {
store.dispatch(
TabAction(
tabId = tabId,
action = TabAction.ContentAction.UpdateTitleAction(title),
),
)
}
fun updateNavigation(tabId: WebTargetId, canGoBack: Boolean, canGoForward: Boolean) {
store.dispatch(
TabAction(
tabId = tabId,
action =
TabAction.ContentAction.UpdateNavigationAction(
canGoBack = canGoBack,
canGoForward = canGoForward,
),
),
)
}
}
class TabRequestUseCases @Inject internal constructor(private val store: FrostWebStore) {
fun requestUrl(tabId: WebTargetId, url: String) {
store.dispatch(TabAction(tabId = tabId, action = TabAction.UserAction.LoadUrlAction(url)))
}
fun goBack(tabId: WebTargetId) {
store.dispatch(TabAction(tabId = tabId, action = TabAction.UserAction.GoBackAction))
}
fun goForward(tabId: WebTargetId) {
store.dispatch(TabAction(tabId = tabId, action = TabAction.UserAction.GoForwardAction))
}
}
class TabResponseUseCases @Inject internal constructor(private val store: FrostWebStore) {
fun respondUrl(tabId: WebTargetId, url: String) {
store.dispatch(
TabAction(
tabId = tabId,
action = TabAction.ResponseAction.LoadUrlResponseAction(url),
),
)
}
fun respondSteps(tabId: WebTargetId, steps: Int) {
store.dispatch(
TabAction(
tabId = tabId,
action = TabAction.ResponseAction.WebStepResponseAction(steps),
),
)
}
}

View File

@ -14,9 +14,8 @@
* 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.components
package com.pitchedapps.frost.web.usecases
import com.pitchedapps.frost.web.usecases.HomeTabsUseCases
import javax.inject.Inject
import javax.inject.Singleton
@ -30,4 +29,5 @@ class UseCases
@Inject
internal constructor(
val homeTabs: HomeTabsUseCases,
val tabs: TabUseCases,
)

View File

@ -27,9 +27,13 @@ import com.pitchedapps.frost.web.state.TabAction
import com.pitchedapps.frost.web.state.TabAction.ContentAction.UpdateProgressAction
import com.pitchedapps.frost.web.state.TabAction.ContentAction.UpdateTitleAction
import com.pitchedapps.frost.web.state.get
import javax.inject.Inject
/** The default chrome client */
class FrostChromeClient(private val tabId: WebTargetId, private val store: FrostWebStore) :
@FrostWebScoped
class FrostChromeClient
@Inject
internal constructor(@FrostWeb private val tabId: WebTargetId, private val store: FrostWebStore) :
WebChromeClient() {
private fun FrostWebStore.dispatch(action: TabAction.Action) {

View File

@ -16,19 +16,14 @@
*/
package com.pitchedapps.frost.webview
import android.webkit.WebViewClient
import com.pitchedapps.frost.compose.webview.FrostWebCompose
import com.pitchedapps.frost.ext.WebTargetId
import com.pitchedapps.frost.web.FrostWebHelper
import com.pitchedapps.frost.web.state.FrostWebStore
import com.pitchedapps.frost.webview.injection.FrostJsInjectors
import dagger.BindsInstance
import dagger.Module
import dagger.Provides
import dagger.hilt.DefineComponent
import dagger.hilt.EntryPoint
import dagger.hilt.EntryPoints
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.hilt.android.components.ViewModelComponent
import javax.inject.Inject
import javax.inject.Qualifier
import javax.inject.Scope
@ -45,45 +40,32 @@ annotation class FrostWebScoped
@Qualifier annotation class FrostWeb
@FrostWebScoped @DefineComponent(parent = SingletonComponent::class) interface FrostWebComponent
@FrostWebScoped @DefineComponent(parent = ViewModelComponent::class) interface FrostWebComponent
@DefineComponent.Builder
interface FrostWebComponentBuilder {
@BindsInstance fun tabId(@FrostWeb tabId: WebTargetId): FrostWebComponentBuilder
fun tabId(@BindsInstance @FrostWeb tabId: WebTargetId): FrostWebComponentBuilder
fun build(): FrostWebComponent
}
@Module
@InstallIn(FrostWebComponent::class)
internal object FrostWebModule {
@Provides
fun client(
@FrostWeb tabId: WebTargetId,
store: FrostWebStore,
webHelper: FrostWebHelper,
frostJsInjectors: FrostJsInjectors,
): WebViewClient = FrostWebViewClient(tabId, store, webHelper, frostJsInjectors)
}
/**
* Using this injection seems to be buggy, leading to an invalid param tabId error:
*
* Cause: not a valid name: tabId-4xHwVBUParam
*/
class FrostWebEntrySample
class FrostWebComposer
@Inject
internal constructor(private val frostWebComponentBuilder: FrostWebComponentBuilder) {
fun test(tabId: WebTargetId): WebViewClient {
fun create(tabId: WebTargetId): FrostWebCompose {
val component = frostWebComponentBuilder.tabId(tabId).build()
return EntryPoints.get(component, FrostWebEntryPoint::class.java).client()
return EntryPoints.get(component, FrostWebEntryPoint::class.java).compose()
}
@EntryPoint
@InstallIn(FrostWebComponent::class)
interface FrostWebEntryPoint {
fun client(): WebViewClient
fun compose(): FrostWebCompose
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright 2023 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.webview
import com.pitchedapps.frost.compose.webview.FrostWebCompose
import com.pitchedapps.frost.ext.WebTargetId
import com.pitchedapps.frost.web.FrostWebHelper
import com.pitchedapps.frost.web.state.FrostWebStore
import com.pitchedapps.frost.webview.injection.FrostJsInjectors
import javax.inject.Inject
class FrostWebComposer
@Inject
internal constructor(
private val store: FrostWebStore,
private val webHelper: FrostWebHelper,
private val frostJsInjectors: FrostJsInjectors,
) {
fun create(tabId: WebTargetId): FrostWebCompose {
val client = FrostWebViewClient(tabId, store, webHelper, frostJsInjectors)
val chromeClient = FrostChromeClient(tabId, store)
return FrostWebCompose(tabId, store, client, chromeClient)
}
}

View File

@ -36,6 +36,7 @@ import com.pitchedapps.frost.web.state.TabAction.ContentAction.UpdateProgressAct
import com.pitchedapps.frost.web.state.TabAction.ContentAction.UpdateTitleAction
import com.pitchedapps.frost.webview.injection.FrostJsInjectors
import java.io.ByteArrayInputStream
import javax.inject.Inject
/**
* Created by Allan Wang on 2017-05-31.
@ -63,8 +64,11 @@ abstract class BaseWebViewClient : WebViewClient() {
}
/** The default webview client */
class FrostWebViewClient(
private val tabId: WebTargetId,
@FrostWebScoped
class FrostWebViewClient
@Inject
internal constructor(
@FrostWeb private val tabId: WebTargetId,
private val store: FrostWebStore,
override val webHelper: FrostWebHelper,
private val frostJsInjectors: FrostJsInjectors,