Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dapp browser tabs #1287

Open
wants to merge 36 commits into
base: base/seamless-dapp-browser
Choose a base branch
from

Conversation

svojsu
Copy link
Contributor

@svojsu svojsu commented Nov 21, 2024

  • Introduce DAppBrowserTabManager to manage persistence and in-memory state for tabs.
  • Introduce WebViewPool to reuse webviews.
  • Introduce WebViewRenderFilesOperationFactory to manage cache for webview renders.
  • Introduce DAppBrowserTabList module
  • Refactor DAppBrowserInteractor to deal with tabs instead of dApps or just user queries.

@svojsu svojsu marked this pull request as ready for review November 21, 2024 23:43
@svojsu svojsu requested a review from ERussel November 22, 2024 11:27
@@ -8,6 +8,7 @@ protocol FileRepositoryProtocol {
func writeOperation(dataClosure: @escaping () throws -> Data, at path: String) -> BaseOperation<Void>
func copyOperation(from fromPath: String, to toPath: String) -> BaseOperation<Void>
func removeOperation(at path: String) -> BaseOperation<Void>
func removeOperation(at paths: [String]) -> BaseOperation<Void>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like removeOperation(at path: String) can now move to the protocol extension and implemented via new method added. Don't see necessity to have both methods in the protocol

let updatedTab = currentTab.updating(with: dApp)
updateWrapper = tabManager.updateTab(updatedTab)

dataSource.replace(tab: updatedTab)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why to we skip dataSource update in the .query case?

transports.first(where: { $0.name == name })?.processConfirmation(response: response)
}

func process(
stateRender: Data,
tabId: UUID
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need tabId here as we have current tab in the state?

render: stateRender
)

execute(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just use operationQueue.addOperations(wrapper.allOperations, wait: false) if we don't need to handle result


transports.forEach { $0.stop() }
completeSetupIfNeeded()
if case let .dApp(dApp) = newQuery, !currentTab.isBlankPage {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we confirm the logic: if user selects search string then replace current tab and if user selects dapp then select new tab?

func updating(
transportStates: [DAppTransportState]? = nil,
name: String? = nil,
lastModified _: Date? = nil,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need lastModified here it seems

final class DAppBrowserTabManager {
private let cacheBasePath: String
private let fileRepository: WebViewRenderFilesOperationFactoryProtocol
private let repository: CoreDataRepository<DAppBrowserTab.PersistenceModel, CDDAppBrowserTab>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be AnyDataProviderRepository<DAppBrowserTab.PersistenceModel> here

)

let saveRenderWrapper: CompoundOperationWrapper<Void> = if let renderData = tab.stateRender {
fileRepository.saveRenderOperation(for: tab.uuid, data: { renderData })
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we could serialise renderData from UIImage to Data in the closure instead of doing this in the main thread in the UIViewController


private var dAppTransportStates: [UUID: [DAppTransportState]] = [:]
private var tabs: [UUID: DAppBrowserTab] = [:]
private var observers: [WeakWrapper] = []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we completely forgot here about primitives we have to organise reactive code based on the database. I would suggest the following approach:

  1. Make PersistentTabLocalSubscriptionFactory factory the returns StreamableProvider for the entity. There are a lot of examples. For example, DAppLocalSubscriptionFactory
  2. Subscribe to the provider in the TabManager. Now once you update Tab entity the update will automatically arrive to the TabManager
  3. Make tabs Observable<[UUID: DAppBrowserTab]> = [:] and update once you receive changes from the provider
  4. Add observers to the state.

That approach avoids a lot of additional logic we have now. Such as fetch tabs and subscribing at the same time (saw in the interactor).

func removeRenders(for ids: [UUID]) -> CompoundOperationWrapper<Void>
}

extension RuntimeFilesOperationFactory: WebViewRenderFilesOperationFactoryProtocol {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RuntimeFilesOperationFactory is a separate factory to manage blockchain runtimes. I would create new operation factory for WebViewRenderFilesOperationFactoryProtocol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants