Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions IonicPortals/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies {
implementation(kotlin("reflect"))

api("com.capacitorjs:core:[8.0.0,9.0.0)")
api("io.ionic:liveupdateprovider:0.1.0")
compileOnly("io.ionic:liveupdates:0.5.5")

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
Expand Down
117 changes: 99 additions & 18 deletions IonicPortals/src/main/kotlin/io/ionic/portals/Portal.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package io.ionic.portals

import android.content.Context
import android.util.Log
import com.getcapacitor.Plugin
import io.ionic.liveupdateprovider.LiveUpdateProviderError
import io.ionic.liveupdateprovider.LiveUpdateProviderManager
import io.ionic.liveupdateprovider.LiveUpdateProviderSyncCallback
import io.ionic.liveupdateprovider.LiveUpdateProviderSyncResult
import io.ionic.liveupdates.LiveUpdate
import io.ionic.liveupdates.LiveUpdateManager
import java.io.File

/**
* A class representing a Portal that contains information about the web content to load and any
Expand All @@ -25,6 +31,21 @@ import io.ionic.liveupdates.LiveUpdateManager
* @property name the name of the Portal
*/
class Portal(val name: String) {
/**
* The live update source for a [Portal].
*/
sealed class LiveUpdateSource {
/**
* Uses Ionic Live Updates to sync and locate the latest web application assets.
*/
data class Ionic(val liveUpdateConfig: LiveUpdate) : LiveUpdateSource()

/**
* Uses a [LiveUpdateProviderManager] to sync and locate the latest web application assets.
*/
data class Provider(val manager: LiveUpdateProviderManager) : LiveUpdateSource()
}

/**
* Capacitor [Plugin] registered with the Portal.
*/
Expand Down Expand Up @@ -73,22 +94,30 @@ class Portal(val name: String) {
var devMode: Boolean = true

/**
* A LiveUpdate config, if live updates is being used.
* The live update source for this Portal.
*
* Use [LiveUpdateSource.Ionic] for Ionic Live Updates, or [LiveUpdateSource.Provider] for
* an external provider built with the Live Update Provider SDK.
*/
var liveUpdateConfig: LiveUpdate? = null
var liveUpdateSource: LiveUpdateSource? = null
set(value) {
field = value
if (value != null) {
if(value.assetPath == null) {
value.assetPath = this.startDir
}
if (value is LiveUpdateSource.Ionic && value.liveUpdateConfig.assetPath == null) {
value.liveUpdateConfig.assetPath = this.startDir
}
}

/**
* Whether to run a live update sync when the portal is added to the manager.
* The directory of the latest synced web application assets for this Portal.
* Returns null when no live update source is configured or no sync has completed.
*/
var liveUpdateOnAppLoad: Boolean = true
fun latestAppDirectory(context: Context): File? {
return when (val source = liveUpdateSource) {
is LiveUpdateSource.Ionic -> LiveUpdateManager.getLatestAppDirectory(context, source.liveUpdateConfig.appId)
is LiveUpdateSource.Provider -> source.manager.latestAppDirectory
null -> null
}
}

/**
* Add a Capacitor [Plugin] to be loaded with this Portal.
Expand Down Expand Up @@ -308,7 +337,7 @@ class PortalBuilder(val name: String) {
private var initialContext: Any? = null
private var portalFragmentType: Class<out PortalFragment?> = PortalFragment::class.java
private var onCreate: (portal: Portal) -> Unit = {}
private var liveUpdateConfig: LiveUpdate? = null
private var liveUpdateSource: Portal.LiveUpdateSource? = null
private var devMode: Boolean = true

internal constructor(name: String, onCreate: (portal: Portal) -> Unit) : this(name) {
Expand Down Expand Up @@ -526,31 +555,32 @@ class PortalBuilder(val name: String) {
}

/**
* Set the [LiveUpdate] config if using the Live Updates SDK with Portals.
* Set the [LiveUpdate] config if using Ionic Live Updates with Portals.
*
* Example usage (kotlin):
* ```kotlin
* val liveUpdateConfig = LiveUpdate("appId", "production")
* builder = builder.setLiveUpdateConfig(liveUpdateConfig)
* builder = builder.setLiveUpdateConfig(context, liveUpdateConfig)
* ```
*
* Example usage (java):
* ```java
* LiveUpdate liveUpdateConfig = new LiveUpdate("appId", "production");
* builder = builder.setLiveUpdateConfig(liveUpdateConfig);
* builder = builder.setLiveUpdateConfig(context, liveUpdateConfig);
* ```
*
* @param context the Android [Context] used with Live Update configuration
* @param liveUpdateConfig the Live Update config object
* @param updateOnAppLoad if a Live Update sync should occur as soon as the Portal loads
* @return the instance of the PortalBuilder with the Live Update config set
* @param context the Android [Context] used with Ionic Live Updates configuration.
* @param liveUpdateConfig the Ionic Live Updates config object.
* @param updateOnAppLoad whether to start an Ionic Live Updates sync when the Portal is configured.
* @return the instance of the PortalBuilder with the Ionic Live Updates config set.
*/
@JvmOverloads
fun setLiveUpdateConfig(context: Context, liveUpdateConfig: LiveUpdate, updateOnAppLoad: Boolean = true): PortalBuilder {
this.liveUpdateConfig = liveUpdateConfig
requireNoLiveUpdateSource()
if(liveUpdateConfig.assetPath == null) {
liveUpdateConfig.assetPath = this._startDir ?: this.name
}
this.liveUpdateSource = Portal.LiveUpdateSource.Ionic(liveUpdateConfig)

LiveUpdateManager.initialize(context)
LiveUpdateManager.cleanVersions(context, liveUpdateConfig.appId)
Expand All @@ -561,6 +591,57 @@ class PortalBuilder(val name: String) {
return this
}

/**
* Set a live update provider manager to be used with the Portal.
*
* Example usage (kotlin):
* ```kotlin
* builder = builder.setLiveUpdateProviderManager(providerManager)
* ```
*
* Example usage (java):
* ```java
* builder = builder.setLiveUpdateProviderManager(providerManager);
* ```
*
* To trigger a provider sync after the Portal is created, use the provider manager directly.
*
* @param liveUpdateProviderManager the external live update provider manager.
* @param updateOnAppLoad whether to start an external provider sync when the Portal is configured.
* @return the instance of the PortalBuilder with the external live update provider manager set.
*/
@JvmOverloads
fun setLiveUpdateProviderManager(
liveUpdateProviderManager: LiveUpdateProviderManager,
updateOnAppLoad: Boolean = true
): PortalBuilder {
requireNoLiveUpdateSource()
this.liveUpdateSource = Portal.LiveUpdateSource.Provider(liveUpdateProviderManager)
if (updateOnAppLoad) {
liveUpdateProviderManager.sync(
callback = object : LiveUpdateProviderSyncCallback {
override fun onSuccess(result: LiveUpdateProviderSyncResult) {
Log.d(
"PortalBuilder",
"Live Update sync complete. Latest app dir: ${liveUpdateProviderManager.latestAppDirectory}"
)
}

override fun onFailure(error: LiveUpdateProviderError.SyncFailed) {
Log.e("PortalBuilder", "Live Update sync failed: ${error.message}")
}
}
)
}
return this
}

private fun requireNoLiveUpdateSource() {
check(liveUpdateSource == null) {
"A live update source is already configured for this Portal."
}
}

/**
* Set development mode on the Portal which will look for a server URL set by the Portals CLI.
* This is set to true by default but can be turned off manually if desired.
Expand Down Expand Up @@ -597,7 +678,7 @@ class PortalBuilder(val name: String) {
portal.addAssetMaps(assetMaps)
portal.initialContext = this.initialContext
portal.portalFragmentType = this.portalFragmentType
portal.liveUpdateConfig = this.liveUpdateConfig
portal.liveUpdateSource = this.liveUpdateSource
portal.devMode = this.devMode
onCreate(portal)
return portal
Expand Down
11 changes: 5 additions & 6 deletions IonicPortals/src/main/kotlin/io/ionic/portals/PortalFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import androidx.annotation.NonNull
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.getcapacitor.*
import io.ionic.liveupdates.LiveUpdateManager
import org.json.JSONException
import org.json.JSONObject
import java.io.File
Expand Down Expand Up @@ -265,11 +264,11 @@ open class PortalFragment : Fragment {

/**
* Reloads the Portal.
* If Live Updates is used and the web content was updated, the new content will be loaded.
* If a live update source is configured and the web content was updated, the new content will be loaded.
*/
fun reload() {
if(portal?.liveUpdateConfig != null) {
val latestLiveUpdateFiles = LiveUpdateManager.getLatestAppDirectory(requireContext(), portal?.liveUpdateConfig?.appId!!)
if(portal?.liveUpdateSource != null) {
val latestLiveUpdateFiles = portal?.latestAppDirectory(requireContext())
if (latestLiveUpdateFiles != null) {
if (liveUpdateFiles == null || liveUpdateFiles!!.path != latestLiveUpdateFiles.path) {
liveUpdateFiles = latestLiveUpdateFiles
Expand Down Expand Up @@ -323,8 +322,8 @@ open class PortalFragment : Fragment {
.addPluginInstances(initialPluginInstances)
.addWebViewListeners(webViewListeners)

if (portal?.liveUpdateConfig != null) {
liveUpdateFiles = LiveUpdateManager.getLatestAppDirectory(requireContext(), portal?.liveUpdateConfig?.appId!!)
if (portal?.liveUpdateSource != null) {
liveUpdateFiles = portal?.latestAppDirectory(requireContext())
bridgeBuilder = if (liveUpdateFiles != null) {
if (config == null) {
val configFile = File(liveUpdateFiles!!.path + "/capacitor.config.json")
Expand Down
27 changes: 3 additions & 24 deletions IonicPortals/src/main/kotlin/io/ionic/portals/PortalManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ object PortalManager {
* ```
*
* @param name the portal name
* @throws NoSuchElementException throws this exception if the Portal does not exist
* @throws IllegalStateException throws this exception if the Portal does not exist
*/
@JvmStatic
fun getPortal(name: String): Portal {
Expand All @@ -62,8 +62,8 @@ object PortalManager {

/**
* Removes the Portal from the Portal Manager. The Portal will be returned if it was present. If not, null is returned.
* Note: if the Portal uses Live Updates and registered an instance on creation, the Live Update instance for the app
* is not removed.
* Note: removing a Portal does not remove its Ionic Live Updates app instance from the
* Ionic Live Updates manager.
*
* @param name the name of the Portal to remove
*/
Expand Down Expand Up @@ -92,27 +92,6 @@ object PortalManager {
return portals.size
}

/**
* Portals registration is no longer required. This function is retained for source
* compatibility and has no effect.
*
* @param key A previously required Portals registration key.
*/
@Deprecated("Portals registration is no longer required. This method has no effect.")
@JvmStatic
fun register(key: String) {}

/**
* Portals registration is no longer required.
*
* @return true.
*/
@Deprecated("Portals registration is no longer required. This method always returns true.")
@JvmStatic
fun isRegistered(): Boolean {
return true
}

/**
* A helper function to build portal classes and add them to the manager.
* Classes built with newPortal are added to the PortalManager automatically.
Expand Down
4 changes: 2 additions & 2 deletions IonicPortals/src/main/kotlin/io/ionic/portals/PortalView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import java.util.ArrayList
* </androidx.constraintlayout.widget.ConstraintLayout>
* ```
*
* Jetpack Composd example usage:
* Jetpack Compose example usage:
* ```kotlin
* @Composable
* fun loadPortal(portalId: String) {
Expand Down Expand Up @@ -361,4 +361,4 @@ class PortalView : FrameLayout {
mDisappearingFragmentChildren!!.add(v)
}
}
}
}
Loading