diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 2acc6d0a3..c43861506 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -9,6 +9,7 @@ plugins { id("com.google.gms.google-services") id("com.google.firebase.crashlytics") id("io.github.takahirom.roborazzi") + id("org.jetbrains.compose") } configureCompilerOptions() diff --git a/androidApp/src/main/java/dev/johnoreilly/confetti/speakers/SpeakerView.kt b/androidApp/src/main/java/dev/johnoreilly/confetti/speakers/SpeakerView.kt index be861dbef..bb807dee3 100644 --- a/androidApp/src/main/java/dev/johnoreilly/confetti/speakers/SpeakerView.kt +++ b/androidApp/src/main/java/dev/johnoreilly/confetti/speakers/SpeakerView.kt @@ -56,7 +56,7 @@ fun SpeakersRoute( when (val state = uiState) { is SpeakersUiState.Success -> { if (windowSizeClass.isExpanded) { - SpeakerGridView(state.speakers, component::onSpeakerClicked) + SpeakerGridView(state.conference, state.speakers, component::onSpeakerClicked) } else { SpeakerListView(state.speakers, component::onSpeakerClicked) } diff --git a/build.gradle.kts b/build.gradle.kts index d7ad24eef..a153eb4be 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ tasks.register("quickChecks") { allprojects { afterEvaluate { extensions.findByType()?.apply { - kotlinCompilerPlugin.set("1.5.9-kt-2.0.0-Beta4") + kotlinCompilerPlugin.set("1.5.11-kt-2.0.0-RC1") } } } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 054c7ef62..37f8c63c5 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -15,6 +15,7 @@ pluginManagement { includeGroupByRegex(".*android.*") } } + mavenLocal() mavenCentral() gradlePluginPortal() } diff --git a/compose-desktop/src/main/kotlin/HomeUI.kt b/compose-desktop/src/main/kotlin/HomeUI.kt index abff086ac..83fd61b3e 100644 --- a/compose-desktop/src/main/kotlin/HomeUI.kt +++ b/compose-desktop/src/main/kotlin/HomeUI.kt @@ -1,3 +1,4 @@ +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.padding import androidx.compose.material.BottomNavigation import androidx.compose.material.BottomNavigationItem @@ -7,6 +8,10 @@ import androidx.compose.material.icons.outlined.Home import androidx.compose.material.icons.outlined.LocationOn import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.Search +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -17,6 +22,7 @@ import com.arkivanov.decompose.extensions.compose.stack.Children import com.arkivanov.decompose.extensions.compose.subscribeAsState import dev.johnoreilly.confetti.decompose.ConferenceComponent import dev.johnoreilly.confetti.decompose.HomeComponent +import dev.johnoreilly.confetti.decompose.SessionsUiState import dev.johnoreilly.confetti.ui.ConferenceMaterialTheme import dev.johnoreilly.confetti.ui.SessionListGridView @@ -38,12 +44,27 @@ fun ConferenceView(component: ConferenceComponent) { } +@OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeView(component: HomeComponent) { val stack by component.stack.subscribeAsState() val activeChild = stack.active.instance + val topBarActions: @Composable RowScope.() -> Unit = { + IconButton(onClick = { + component.onSwitchConferenceClicked() + }) { + androidx.compose.material3.Icon(Icons.Outlined.Settings, contentDescription = "Switch Conference") + } + } + Scaffold( + topBar = { + CenterAlignedTopAppBar( + title = { Text("") }, + actions = topBarActions + ) + }, bottomBar = { BottomNavigation(backgroundColor = MaterialTheme.colorScheme.surface) { BottomNavigationItem( diff --git a/compose-desktop/src/main/kotlin/SpeakersUI.kt b/compose-desktop/src/main/kotlin/SpeakersUI.kt index 41e08a757..0e9f547c5 100644 --- a/compose-desktop/src/main/kotlin/SpeakersUI.kt +++ b/compose-desktop/src/main/kotlin/SpeakersUI.kt @@ -26,7 +26,7 @@ fun SpeakersUI(component: SpeakersComponent) { ) { when (val state = uiState) { is SpeakersUiState.Success -> { - SpeakerGridView(state.speakers, component::onSpeakerClicked) + SpeakerGridView(state.conference, state.speakers, component::onSpeakerClicked) } is SpeakersUiState.Loading -> LoadingView() is SpeakersUiState.Error -> ErrorView {} diff --git a/compose-web/build.gradle.kts b/compose-web/build.gradle.kts new file mode 100644 index 000000000..93c64f615 --- /dev/null +++ b/compose-web/build.gradle.kts @@ -0,0 +1,52 @@ +import org.jetbrains.compose.ExperimentalComposeLibrary + +plugins { + kotlin("multiplatform") + id("kotlinx-serialization") + id("org.jetbrains.compose") +} + +group = "com.example" +version = "1.0-SNAPSHOT" + + +val copyWasmResources = tasks.create("copyWasmResourcesWorkaround", Copy::class.java) { + from(project(":shared").file("src/commonMain/composeResources")) + into("build/processedResources/wasmJs/main") +} + + +afterEvaluate { + project.tasks.getByName("wasmJsProcessResources").finalizedBy(copyWasmResources) + project.tasks.getByName("wasmJsDevelopmentExecutableCompileSync").dependsOn(copyWasmResources) + project.tasks.getByName("wasmJsProductionExecutableCompileSync").dependsOn(copyWasmResources) +} + +kotlin { + wasmJs { + moduleName = "confetti" + browser { + commonWebpackConfig { + outputFileName = "confetti.js" + } + } + binaries.executable() + } + + sourceSets { + commonMain { + dependencies { + implementation(compose.ui) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.components.resources) + implementation(project(":shared")) + } + } + } +} + +compose.experimental { + web.application {} +} diff --git a/compose-web/src/wasmJsMain/kotlin/HomeUI.kt b/compose-web/src/wasmJsMain/kotlin/HomeUI.kt new file mode 100644 index 000000000..f1ab90901 --- /dev/null +++ b/compose-web/src/wasmJsMain/kotlin/HomeUI.kt @@ -0,0 +1,222 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawingPadding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Person +import androidx.compose.material.icons.outlined.Home +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationRailItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi +import androidx.compose.material3.windowsizeclass.WindowSizeClass +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass +import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import dev.johnoreilly.confetti.decompose.ConferenceComponent +import dev.johnoreilly.confetti.decompose.HomeComponent +import dev.johnoreilly.confetti.decompose.SessionsComponent +import dev.johnoreilly.confetti.decompose.SessionsUiState +import dev.johnoreilly.confetti.ui.ConferenceMaterialTheme +import dev.johnoreilly.confetti.ui.SessionListGridView +import dev.johnoreilly.confetti.ui.SessionListView +import dev.johnoreilly.confetti.utils.isExpanded + + +@Composable +fun ConferenceView(component: ConferenceComponent) { + ConferenceMaterialTheme(component.conferenceThemeColor) { + Children( + stack = component.stack, + ) { + when (val child = it.instance) { + is ConferenceComponent.Child.Home -> HomeView(child.component) + is ConferenceComponent.Child.SessionDetails -> SessionDetailsUI(child.component) + is ConferenceComponent.Child.SpeakerDetails -> SpeakerDetailsUI(child.component) + is ConferenceComponent.Child.Settings -> {} //SettingsRoute(child.component) + } + } + } +} + + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3WindowSizeClassApi::class) +@Composable +fun HomeView(component: HomeComponent) { + val windowSizeClass = calculateWindowSizeClass() + val shouldShowNavRail = windowSizeClass.isExpanded + Row { + if (shouldShowNavRail) { + NavigationRail(component) + } + + Scaffold( + bottomBar = { if (!shouldShowNavRail) BottomBar(component) } + ) { + Column(modifier = Modifier.padding(it)) { + Children(stack = component.stack,) { + when (val child = it.instance) { + is HomeComponent.Child.Sessions -> SessionsUI(child.component, windowSizeClass, component::onSwitchConferenceClicked) + is HomeComponent.Child.MultiPane -> Text(text = "Multi-pane mode is not yet supported") + is HomeComponent.Child.Speakers -> SpeakersUI(child.component) + is HomeComponent.Child.Bookmarks -> {} + is HomeComponent.Child.Venue -> VenueUI(child.component) + is HomeComponent.Child.Search -> {} + is HomeComponent.Child.Recommendations -> {} + } + } + + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun SessionsUI(component: SessionsComponent, windowSizeClass: WindowSizeClass, onSwitchConferenceSelected: () -> Unit) { + + val uiState by component.uiState.subscribeAsState() + + val topBarActions: @Composable RowScope.() -> Unit = { + IconButton(onClick = { onSwitchConferenceSelected() }) { + Icon(Icons.Outlined.Settings, contentDescription = "Switch Conference") + } + } + + val title = (uiState as? SessionsUiState.Success)?.conferenceName ?: "" + Scaffold(topBar = { + CenterAlignedTopAppBar( + title = { Text(title) }, + actions = topBarActions + ) + }) { + Column(Modifier.padding(it)) { + if (windowSizeClass.isExpanded) { + SessionListGridView( + uiState = uiState, + sessionSelected = component::onSessionClicked, + onRefresh = {}, + addBookmark = {}, + removeBookmark = {}, + onNavigateToSignIn = {}, + isLoggedIn = component.isLoggedIn, + ) + } else { + SessionListView( + uiState = uiState, + sessionSelected = component::onSessionClicked, + addBookmark = component::addBookmark, + removeBookmark = component::removeBookmark, + onRefresh = component::refresh, + onNavigateToSignIn = component::onSignInClicked, + isLoggedIn = component.isLoggedIn, + ) + } + + } + } + +} + + + +@Composable +private fun NavigationRail(component: HomeComponent) { + androidx.compose.material3.NavigationRail( + modifier = Modifier.safeDrawingPadding(), + containerColor = Color.Transparent, + contentColor = MaterialTheme.colorScheme.onSurfaceVariant, + ) { + NavigationButtons(component = component) { isSelected, selectedIcon, unselectedIcon, text, onClick -> + NavigationRailItem( + selected = isSelected, + onClick = onClick, + icon = { + Icon( + imageVector = if (isSelected) selectedIcon else unselectedIcon, + contentDescription = text + ) + }, + ) + } + } +} + + + +@Composable +private fun BottomBar(component: HomeComponent) { + Column { + HorizontalDivider() + NavigationBar( + contentColor = MaterialTheme.colorScheme.onSurfaceVariant, + tonalElevation = 0.dp, + ) { + NavigationButtons(component = component) { isSelected, selectedIcon, unselectedIcon, text, onClick -> + NavigationBarItem( + selected = isSelected, + onClick = onClick, + icon = { + Icon( + imageVector = if (isSelected) selectedIcon else unselectedIcon, + contentDescription = text, + ) + }, + label = { Text(text) }, + ) + } + } + } +} + + +@Composable +private fun T.NavigationButtons( + component: HomeComponent, + content: @Composable T.( + isSelected: Boolean, + selectedIcon: ImageVector, + unselectedIcon: ImageVector, + text: String, + onClick: () -> Unit, + ) -> Unit, +) { + val stack by component.stack.subscribeAsState() + val activeChild = stack.active.instance + + content( + activeChild is HomeComponent.Child.Sessions, + Icons.Filled.Home, + Icons.Outlined.Home, + "Schedule", + component::onSessionsTabClicked, + ) + + content( + activeChild is HomeComponent.Child.Speakers, + Icons.Filled.Person, + Icons.Outlined.Person, + "Speakers", + component::onSpeakersTabClicked, + ) +} diff --git a/compose-web/src/wasmJsMain/kotlin/Main.kt b/compose-web/src/wasmJsMain/kotlin/Main.kt new file mode 100644 index 000000000..22709ca25 --- /dev/null +++ b/compose-web/src/wasmJsMain/kotlin/Main.kt @@ -0,0 +1,60 @@ +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.window.CanvasBasedWindow +import com.apollographql.apollo3.ApolloClient +import com.arkivanov.decompose.DefaultComponentContext +import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.essenty.lifecycle.Lifecycle +import com.arkivanov.essenty.lifecycle.LifecycleRegistry +import dev.johnoreilly.confetti.decompose.AppComponent +import dev.johnoreilly.confetti.decompose.DefaultAppComponent +import dev.johnoreilly.confetti.di.initKoin +import dev.johnoreilly.confetti.ui.ConferenceListView +import dev.johnoreilly.confetti.ui.LoadingView +import org.koin.dsl.module + + +private fun mainModule() = module { + factory { + ApolloClient.Builder() + .serverUrl("https://confetti-app.dev/graphql") + } +} + +val koin = initKoin { + modules(mainModule()) +}.koin + +@OptIn(ExperimentalComposeUiApi::class) +fun main() { + val lifecycle = LifecycleRegistry(Lifecycle.State.STARTED) + + val appComponent = + DefaultAppComponent( + componentContext = DefaultComponentContext(lifecycle), + onSignOut = {}, + onSignIn = {} + ) + + + CanvasBasedWindow("Confetti", canvasElementId = "confettiCanvas") { + MaterialTheme { + MainLayout(appComponent) + } + } +} + + +@Composable +fun MainLayout(component: DefaultAppComponent) { + Children( + stack = component.stack + ) { + when (val child = it.instance) { + is AppComponent.Child.Loading -> LoadingView() + is AppComponent.Child.Conferences -> ConferenceListView(child.component) + is AppComponent.Child.Conference -> ConferenceView(child.component) + } + } +} diff --git a/compose-web/src/wasmJsMain/kotlin/SessionsUI.kt b/compose-web/src/wasmJsMain/kotlin/SessionsUI.kt new file mode 100644 index 000000000..cb79bff0d --- /dev/null +++ b/compose-web/src/wasmJsMain/kotlin/SessionsUI.kt @@ -0,0 +1,54 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import dev.johnoreilly.confetti.decompose.SessionDetailsComponent +import dev.johnoreilly.confetti.decompose.SessionDetailsUiState +import dev.johnoreilly.confetti.dev.johnoreilly.confetti.ui.SessionDetailViewSharedWrapper +import dev.johnoreilly.confetti.ui.ErrorView +import dev.johnoreilly.confetti.ui.LoadingView + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SessionDetailsUI(component: SessionDetailsComponent) { + val uriHandler = LocalUriHandler.current + + val uiState by component.uiState.subscribeAsState() + + Scaffold(topBar = { + CenterAlignedTopAppBar( + title = { }, + navigationIcon = { + IconButton(onClick = component::onCloseClicked ) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back") + } + } + ) + }) { + Column(Modifier.padding(it)) { + when (val state = uiState) { + is SessionDetailsUiState.Loading -> LoadingView() + is SessionDetailsUiState.Error -> ErrorView() + + is SessionDetailsUiState.Success -> + SessionDetailViewSharedWrapper( + state.conference, state.sessionDetails, + component::onSpeakerClicked + ) { url -> + uriHandler.openUri(url) + } + } + } + } +} diff --git a/compose-web/src/wasmJsMain/kotlin/SpeakersUI.kt b/compose-web/src/wasmJsMain/kotlin/SpeakersUI.kt new file mode 100644 index 000000000..636a7a9e8 --- /dev/null +++ b/compose-web/src/wasmJsMain/kotlin/SpeakersUI.kt @@ -0,0 +1,62 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import dev.johnoreilly.confetti.decompose.SessionsUiState +import dev.johnoreilly.confetti.decompose.SpeakerDetailsComponent +import dev.johnoreilly.confetti.decompose.SpeakerDetailsUiState +import dev.johnoreilly.confetti.decompose.SpeakersComponent +import dev.johnoreilly.confetti.decompose.SpeakersUiState +import dev.johnoreilly.confetti.ui.ErrorView +import dev.johnoreilly.confetti.ui.LoadingView +import dev.johnoreilly.confetti.ui.SpeakerDetailsView +import dev.johnoreilly.confetti.ui.SpeakerGridView + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SpeakersUI(component: SpeakersComponent) { + val uiState by component.uiState.subscribeAsState() + + Scaffold( + topBar = { + CenterAlignedTopAppBar(title = { + // TODO need cleaner way of doing this + val conference = (uiState as? SpeakersUiState.Success)?.conference ?: "" + Text("Speakers ($conference)") + }) + } + ) { + Column(Modifier.padding(it)) { + when (val state = uiState) { + is SpeakersUiState.Success -> { + SpeakerGridView(state.conference, state.speakers, component::onSpeakerClicked) + } + is SpeakersUiState.Loading -> LoadingView() + is SpeakersUiState.Error -> ErrorView {} + } + } + } +} + +@Composable +fun SpeakerDetailsUI(component: SpeakerDetailsComponent) { + val uiState by component.uiState.subscribeAsState() + + when (val state = uiState) { + is SpeakerDetailsUiState.Loading -> LoadingView() + is SpeakerDetailsUiState.Error -> ErrorView() + is SpeakerDetailsUiState.Success -> SpeakerDetailsView( + state.conference, + state.details, + component::onSessionClicked, + component::onCloseClicked, + ) + } + +} diff --git a/compose-web/src/wasmJsMain/kotlin/VenueUI.kt b/compose-web/src/wasmJsMain/kotlin/VenueUI.kt new file mode 100644 index 000000000..604faa217 --- /dev/null +++ b/compose-web/src/wasmJsMain/kotlin/VenueUI.kt @@ -0,0 +1,30 @@ +import androidx.compose.material3.Scaffold +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import dev.johnoreilly.confetti.decompose.VenueComponent +import dev.johnoreilly.confetti.ui.ErrorView +import dev.johnoreilly.confetti.ui.LoadingView +import dev.johnoreilly.confetti.ui.VenueView + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun VenueUI(component: VenueComponent) { + val uiState by component.uiState.subscribeAsState() + + Scaffold( + topBar = { + CenterAlignedTopAppBar(title = { Text("Venue")}) + } + ) { + when (val state = uiState) { + is VenueComponent.Success -> VenueView(state.data) + is VenueComponent.Loading -> LoadingView() + is VenueComponent.Error -> ErrorView {} + } + } +} + diff --git a/compose-web/src/wasmJsMain/resources/images/confetti.png b/compose-web/src/wasmJsMain/resources/images/confetti.png new file mode 100644 index 000000000..7544feaa5 Binary files /dev/null and b/compose-web/src/wasmJsMain/resources/images/confetti.png differ diff --git a/compose-web/src/wasmJsMain/resources/images/splash.png b/compose-web/src/wasmJsMain/resources/images/splash.png new file mode 100644 index 000000000..490858e11 Binary files /dev/null and b/compose-web/src/wasmJsMain/resources/images/splash.png differ diff --git a/compose-web/src/wasmJsMain/resources/index.html b/compose-web/src/wasmJsMain/resources/index.html new file mode 100644 index 000000000..75c465a21 --- /dev/null +++ b/compose-web/src/wasmJsMain/resources/index.html @@ -0,0 +1,61 @@ + + + + Confetti + + + + + + + + + + + + diff --git a/compose-web/src/wasmJsMain/resources/manifest.json b/compose-web/src/wasmJsMain/resources/manifest.json new file mode 100644 index 000000000..3d47a6b9e --- /dev/null +++ b/compose-web/src/wasmJsMain/resources/manifest.json @@ -0,0 +1,13 @@ +{ + "name": "Confetti", + "icons": [ + { + "src": "/images/confetti.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": "/", + "display": "standalone", + "background_color": "white" +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index d54f0e06a..e06dff4b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,9 +17,14 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 org.jetbrains.compose.experimental.uikit.enabled=true org.jetbrains.compose.experimental.macos.enabled=true org.jetbrains.compose.experimental.wasm.enabled=true +org.jetbrains.compose.experimental.jscanvas.enabled=true kotlin.experimental.tryK2=true +kotlin.daemon.jvmargs=-Xmx4096m +xcodeproj=./iosApp + + # KMMBridge LIBRARY_VERSION=0.9 GROUP=dev.johnoreilly.confetti diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 348ae45e0..af6a47260 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,12 +3,13 @@ accompanist = "0.34.0" activity-compose = "1.9.0" androidx-lifecycle = "2.7.0" androidx-datastore = "1.1.0" -apollo = "4.0.0-beta.5" +apollo = "4.0.0-beta.6" compose = "1.6.6" compose-multiplatform = "1.6.2" -compose-compiler = "1.5.11-dev-k2.0.0-Beta4-21f5e479a96" +compose-compiler = "1.5.11-dev-k2.0.0-Beta5-b5a216d0ac6" compose-material-3 = "1.2.1" compose-ui-tooling = "1.3.1" +composeWindowSize = "0.5.0" credentials-play-services-auth = "1.2.2" decompose = "3.0.0-beta01" essenty = "2.0.0-beta02" @@ -22,9 +23,9 @@ kmm-viewmodel = "1.0.0-ALPHA-20" kmmbridge = "0.5.4" koin-android = "3.5.6" koin-android-compose = "3.5.6" -koin-compose-multiplatform = "1.1.5" -koin-core = "3.5.6" -kotlin = "2.0.0-Beta4" +koin-compose-multiplatform = "1.2.0-alpha3" +koin-core = "3.6.0-alpha3" +kotlin = "2.0.0-RC1" ksp-plugin = "2.0.0-RC1-1.0.20" kotlin-coroutines = "1.8.0" kotlinx-coroutines-play-services = "1.8.0" @@ -32,7 +33,7 @@ kotlinx-datetime = "0.6.0-RC.2" lifecycle = "2.7.0" lifecycle-livedata-ktx = "2.7.0" materialkolor = "1.4.4" -multiplatform-settings = "1.1.1" +multiplatform-settings = "1.2.0" nav-compose = "2.7.7" okio = "3.9.0" protolayout-expression = "1.1.0" @@ -43,7 +44,7 @@ roborazzi-gradle-plugin = "1.12.0" room = "2.6.1" tiles-tooling-preview = "1.3.0" work-runtime-ktx = "2.9.0" -generativeai = "0.2.2-1.0.0" +generativeai = "0.2.2-1.0.0-wasm" buildkonfig = "0.15.1" roborazzi = "1.12.0" @@ -154,9 +155,13 @@ ktor-status-pages = "io.ktor:ktor-server-status-pages:2.3.10" lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" } material3-core = { module = "androidx.compose.material3:material3", version.ref = "compose-material-3" } material3-window-size = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "compose-material-3" } + +compose-window-size = { module = "dev.chrisbanes.material3:material3-window-size-class-multiplatform", version.ref = "composeWindowSize" } + multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" } multiplatform-settings-coroutines = { module = "com.russhwolf:multiplatform-settings-coroutines", version.ref = "multiplatform-settings" } multiplatform-settings-datastore = { module = "com.russhwolf:multiplatform-settings-datastore", version.ref = "multiplatform-settings" } +multiplatform-settings-runtime-observable = { module = "com.russhwolf:multiplatform-settings-runtime-observable", version.ref = "multiplatform-settings" } okhttp = "com.squareup.okhttp3:okhttp:5.0.0-alpha.14" okhttp-coroutines = "com.squareup.okhttp3:okhttp-coroutines:5.0.0-alpha.14" okhttp-logging-interceptor = "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.14" @@ -202,8 +207,8 @@ roborazzi-compose = { group = "io.github.takahirom.roborazzi", name = "roborazzi roborazzi-rule = { group = "io.github.takahirom.roborazzi", name = "roborazzi-junit-rule", version.ref = "roborazzi" } [bundles] -multiplatform-settings = ["multiplatform-settings", "multiplatform-settings-coroutines"] -apollo = ["apollo-normalized-cache-in-memory", "apollo-normalized-cache-sqlite", "apollo-adapters"] +multiplatform-settings = ["multiplatform-settings", "multiplatform-settings-coroutines", "multiplatform-settings-runtime-observable"] +apollo = ["apollo-normalized-cache-in-memory", "apollo-adapters"] [plugins] buildkonfig = { id = "com.codingfeline.buildkonfig", version.ref = "buildkonfig" } diff --git a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 30951972e..000000000 --- a/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,149 +0,0 @@ -{ - "pins" : [ - { - "identity" : "abseil-cpp-swiftpm", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/abseil-cpp-SwiftPM.git", - "state" : { - "revision" : "583de9bd60f66b40e78d08599cc92036c2e7e4e1", - "version" : "0.20220203.2" - } - }, - { - "identity" : "boringssl-swiftpm", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/boringssl-SwiftPM.git", - "state" : { - "revision" : "dd3eda2b05a3f459fc3073695ad1b28659066eab", - "version" : "0.9.1" - } - }, - { - "identity" : "firebase-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/firebase-ios-sdk.git", - "state" : { - "revision" : "7e80c25b51c2ffa238879b07fbfc5baa54bb3050", - "version" : "9.6.0" - } - }, - { - "identity" : "googleappmeasurement", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleAppMeasurement.git", - "state" : { - "revision" : "c1cfde8067668027b23a42c29d11c246152fe046", - "version" : "9.6.0" - } - }, - { - "identity" : "googledatatransport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleDataTransport.git", - "state" : { - "revision" : "aae45a320fd0d11811820335b1eabc8753902a40", - "version" : "9.2.5" - } - }, - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities.git", - "state" : { - "revision" : "c38ce365d77b04a9a300c31061c5227589e5597b", - "version" : "7.11.5" - } - }, - { - "identity" : "grpc-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-ios.git", - "state" : { - "revision" : "8440b914756e0d26d4f4d054a1c1581daedfc5b6", - "version" : "1.44.3-grpc" - } - }, - { - "identity" : "gtm-session-fetcher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/gtm-session-fetcher.git", - "state" : { - "revision" : "5ccda3981422a84186387dbb763ba739178b529c", - "version" : "2.3.0" - } - }, - { - "identity" : "leveldb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/leveldb.git", - "state" : { - "revision" : "0706abcc6b0bd9cedfbb015ba840e4a780b5159b", - "version" : "1.22.2" - } - }, - { - "identity" : "markdownui", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gonzalezreal/MarkdownUI", - "state" : { - "revision" : "ae799d015a5374708f7b4c85f3294c05f2a564e2", - "version" : "2.3.0" - } - }, - { - "identity" : "nanopb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/nanopb.git", - "state" : { - "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", - "version" : "2.30909.0" - } - }, - { - "identity" : "networkimage", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gonzalezreal/NetworkImage", - "state" : { - "revision" : "7aff8d1b31148d32c5933d75557d42f6323ee3d1", - "version" : "6.0.0" - } - }, - { - "identity" : "promises", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/promises.git", - "state" : { - "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", - "version" : "2.3.1" - } - }, - { - "identity" : "swift-async-algorithms", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-async-algorithms", - "state" : { - "revision" : "cca423ff03ab657062f3781847e65a867b51bb01", - "version" : "0.0.3" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "ce20dc083ee485524b802669890291c0d8090170", - "version" : "1.22.1" - } - }, - { - "identity" : "swiftui-flow-layout", - "kind" : "remoteSourceControl", - "location" : "https://github.com/globulus/swiftui-flow-layout", - "state" : { - "branch" : "main", - "revision" : "de7da3440c3b87ba94adfa98c698828d7746a76d" - } - } - ], - "version" : 2 -} diff --git a/iosApp/iosApp.xcodeproj/xcuserdata/joreilly.xcuserdatad/xcschemes/xcschememanagement.plist b/iosApp/iosApp.xcodeproj/xcuserdata/joreilly.xcuserdatad/xcschemes/xcschememanagement.plist index 86c05b5f3..796d72228 100644 --- a/iosApp/iosApp.xcodeproj/xcuserdata/joreilly.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/iosApp/iosApp.xcodeproj/xcuserdata/joreilly.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ ConfettiMac.xcscheme_^#shared#^_ orderHint - 1 + 2 Promises (Playground) 1.xcscheme diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index aabcd8155..d1b2fecdd 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -12,6 +12,18 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@jridgewell/gen-mapping@^0.3.0": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -44,7 +56,15 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.20": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@jridgewell/trace-mapping@^0.3.9": version "0.3.20" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== @@ -52,11 +72,21 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@js-joda/core@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273" + integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -70,14 +100,14 @@ "@types/connect" "*" "@types/node" "*" -"@types/bonjour@^3.5.9": +"@types/bonjour@^3.5.13": version "3.5.13" resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" -"@types/connect-history-api-fallback@^1.3.5": +"@types/connect-history-api-fallback@^1.5.4": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== @@ -120,7 +150,7 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.0": +"@types/estree@*", "@types/estree@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== @@ -135,7 +165,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@*", "@types/express@^4.17.13": +"@types/express@*", "@types/express@^4.17.21": version "4.17.21" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== @@ -196,10 +226,10 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== "@types/send@*": version "0.17.4" @@ -209,14 +239,14 @@ "@types/mime" "^1" "@types/node" "*" -"@types/serve-index@^1.9.1": +"@types/serve-index@^1.9.4": version "1.9.4" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" -"@types/serve-static@*", "@types/serve-static@^1.13.10": +"@types/serve-static@*": version "1.15.5" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== @@ -225,24 +255,33 @@ "@types/mime" "*" "@types/node" "*" -"@types/sockjs@^0.3.33": +"@types/serve-static@^1.15.5": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + +"@types/sockjs@^0.3.36": version "0.3.36" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== dependencies: "@types/node" "*" -"@types/ws@^8.5.1": +"@types/ws@^8.5.10": version "8.5.10" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== dependencies: "@types/node" "*" -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" - integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: "@webassemblyjs/helper-numbers" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" @@ -257,10 +296,10 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" - integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== "@webassemblyjs/helper-numbers@1.11.6": version "1.11.6" @@ -276,15 +315,15 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" - integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" "@webassemblyjs/ieee754@1.11.6": version "1.11.6" @@ -305,72 +344,72 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" - integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-opt" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" - "@webassemblyjs/wast-printer" "1.11.6" - -"@webassemblyjs/wasm-gen@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" - integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== - dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wasm-opt@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" - integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" - integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-api-error" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wast-printer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" - integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^2.1.0": +"@webpack-cli/configtest@^2.1.1": version "2.1.1" resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== -"@webpack-cli/info@^2.0.1": +"@webpack-cli/info@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== -"@webpack-cli/serve@^2.0.3": +"@webpack-cli/serve@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== @@ -385,10 +424,12 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abab@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" - integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== +abort-controller@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" @@ -398,7 +439,7 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.7.6: +acorn-import-assertions@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== @@ -462,6 +503,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -469,6 +515,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -487,11 +538,6 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -507,6 +553,11 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== +big.js@5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -548,13 +599,11 @@ body-parser@^1.19.0: type-is "~1.6.18" unpipe "1.0.0" -bonjour-service@^1.0.11: - version "1.1.1" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" - integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== +bonjour-service@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -585,13 +634,13 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserslist@^4.14.5: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== +browserslist@^4.21.10: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" node-releases "^2.0.14" update-browserslist-db "^1.0.13" @@ -600,6 +649,13 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -624,10 +680,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001565: - version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== +caniuse-lite@^1.0.30001587: + version "1.0.30001609" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz#fc34fad75c0c6d6d6303bdbceec2da8f203dabd6" + integrity sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA== chalk@^4.1.0: version "4.1.2" @@ -637,7 +693,7 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chokidar@3.5.3, chokidar@^3.5.1, chokidar@^3.5.3: +chokidar@3.5.3, chokidar@^3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -652,6 +708,21 @@ chokidar@3.5.3, chokidar@^3.5.1, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -782,7 +853,7 @@ cors@~2.8.5: object-assign "^4" vary "^1" -cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -820,6 +891,19 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" @@ -836,10 +920,10 @@ define-data-property@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== depd@2.0.0: version "2.0.0" @@ -871,11 +955,6 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - dns-packet@^5.2.2: version "5.6.1" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" @@ -893,21 +972,31 @@ dom-serialize@^2.2.1: extend "^3.0.0" void-elements "^2.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.601: - version "1.4.614" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" - integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== +electron-to-chromium@^1.4.668: + version "1.4.735" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.735.tgz#c32914ef2cd0a3a545a3def841d253a31a8a93be" + integrity sha512-pkYpvwg8VyOTQAeBqZ7jsmpCjko1Qc6We1ZtZCjRyYbT5v4AIUKDy5cQTRotQlSSZmMr8jqpEt6JtOj5k7lR7A== emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -934,10 +1023,10 @@ engine.io@~6.5.2: engine.io-parser "~5.2.1" ws "~8.11.0" -enhanced-resolve@^5.13.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" - integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== +enhanced-resolve@^5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" + integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -1002,6 +1091,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -1155,6 +1249,14 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + format-util@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" @@ -1179,11 +1281,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-monkey@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" - integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1231,17 +1328,27 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^5.0.1" once "^1.3.0" - path-is-absolute "^1.0.0" + +glob@^10.3.7: + version "10.3.12" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" + integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.6" + minimatch "^9.0.1" + minipass "^7.0.4" + path-scurry "^1.10.2" glob@^7.1.3, glob@^7.1.7: version "7.2.3" @@ -1262,7 +1369,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -1316,10 +1423,10 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-entities@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" - integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== +html-entities@^2.4.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== http-deceiver@^1.2.7: version "1.2.7" @@ -1427,7 +1534,7 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -ipaddr.js@^2.0.1: +ipaddr.js@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== @@ -1446,10 +1553,10 @@ is-core-module@^2.13.0: dependencies: hasown "^2.0.0" -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== is-extglob@^2.1.1: version "2.1.1" @@ -1468,6 +1575,18 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1500,12 +1619,12 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== dependencies: - is-docker "^2.0.0" + is-inside-container "^1.0.0" isarray@~1.0.0: version "1.0.0" @@ -1527,6 +1646,15 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +jackspeak@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -1586,19 +1714,19 @@ karma-sourcemap-loader@0.4.0: dependencies: graceful-fs "^4.2.10" -karma-webpack@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" - integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== +karma-webpack@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.1.tgz#4eafd31bbe684a747a6e8f3e4ad373e53979ced4" + integrity sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ== dependencies: glob "^7.1.3" - minimatch "^3.0.4" + minimatch "^9.0.3" webpack-merge "^4.1.5" -karma@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.2.tgz#a983f874cee6f35990c4b2dcc3d274653714de8e" - integrity sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ== +karma@6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.3.tgz#763e500f99597218bbb536de1a14acc4ceea7ce8" + integrity sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q== dependencies: "@colors/colors" "1.5.0" body-parser "^1.19.0" @@ -1619,7 +1747,7 @@ karma@6.4.2: qjobs "^1.2.0" range-parser "^1.2.1" rimraf "^3.0.2" - socket.io "^4.4.1" + socket.io "^4.7.2" source-map "^0.6.1" tmp "^0.2.1" ua-parser-js "^0.7.30" @@ -1630,7 +1758,7 @@ kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -launch-editor@^2.6.0: +launch-editor@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.1.tgz#f259c9ef95cbc9425620bbbd14b468fcdb4ffe3c" integrity sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw== @@ -1681,17 +1809,22 @@ log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.1.5" +lru-cache@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@^3.4.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" - integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== +memfs@^4.6.0: + version "4.8.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.8.1.tgz#1e02c15c4397212a9a1b037fa4324c6f7dd45b47" + integrity sha512-7q/AdPzf2WpwPlPL4v1kE2KsJsHl7EF4+hAeVzlyanr2+YnR21NVn9mDqo+7DEaKDRsQy8nvxPlKH4WqMtiO0w== dependencies: - fs-monkey "^1.0.4" + tslib "^2.0.0" merge-descriptors@1.0.1: version "1.0.1" @@ -1762,11 +1895,30 @@ minimatch@^3.0.4, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.1, minimatch@^9.0.3: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.3, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -1774,10 +1926,10 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.6" -mocha@10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== +mocha@10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.3.0.tgz#0e185c49e6dccf582035c05fa91084a4ff6e3fe9" + integrity sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg== dependencies: ansi-colors "4.1.1" browser-stdout "1.3.1" @@ -1786,13 +1938,12 @@ mocha@10.2.0: diff "5.0.0" escape-string-regexp "4.0.0" find-up "5.0.0" - glob "7.2.0" + glob "8.1.0" he "1.2.0" js-yaml "4.1.0" log-symbols "4.1.0" minimatch "5.0.1" ms "2.1.3" - nanoid "3.3.3" serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" @@ -1824,11 +1975,6 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -1839,6 +1985,13 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -1876,7 +2029,7 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -1909,14 +2062,15 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^8.0.9: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== +open@^10.0.3: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^3.1.0" p-limit@^2.2.0: version "2.3.0" @@ -1946,12 +2100,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== +p-retry@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.0.tgz#8d6df01af298750009691ce2f9b3ad2d5968f3bd" + integrity sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA== dependencies: - "@types/retry" "0.12.0" + "@types/retry" "0.12.2" + is-network-error "^1.0.0" retry "^0.13.1" p-try@^2.0.0: @@ -1984,6 +2139,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" + integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -2157,6 +2320,18 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" + integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== + dependencies: + glob "^10.3.7" + +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -2172,7 +2347,7 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -schema-utils@^3.1.1, schema-utils@^3.1.2: +schema-utils@^3.1.1, schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -2181,7 +2356,7 @@ schema-utils@^3.1.1, schema-utils@^3.1.2: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: +schema-utils@^4.0.0, schema-utils@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== @@ -2196,7 +2371,7 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== -selfsigned@^2.1.1: +selfsigned@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== @@ -2318,6 +2493,11 @@ signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + socket.io-adapter@~2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" @@ -2333,10 +2513,10 @@ socket.io-parser@~4.2.4: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -socket.io@^4.4.1: - version "4.7.2" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002" - integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw== +socket.io@^4.7.2: + version "4.7.5" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" + integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== dependencies: accepts "~1.3.4" base64id "~2.0.0" @@ -2360,12 +2540,11 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-loader@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.1.tgz#72f00d05f5d1f90f80974eda781cbd7107c125f2" - integrity sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA== +source-map-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-5.0.0.tgz#f593a916e1cc54471cfc8851b905c8a845fc7e38" + integrity sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA== dependencies: - abab "^2.0.6" iconv-lite "^0.6.3" source-map-js "^1.0.2" @@ -2424,7 +2603,7 @@ streamroller@^3.1.5: debug "^4.3.4" fs-extra "^8.1.0" -string-width@^4.1.0, string-width@^4.2.0: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2433,6 +2612,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -2447,13 +2635,20 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -2488,21 +2683,21 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser-webpack-plugin@^5.3.7: - version "5.3.9" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" - integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.17" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" serialize-javascript "^6.0.1" - terser "^5.16.8" + terser "^5.26.0" -terser@^5.16.8: - version "5.26.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" - integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== +terser@^5.26.0: + version "5.30.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.3.tgz#f1bb68ded42408c316b548e3ec2526d7dd03f4d2" + integrity sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -2533,6 +2728,16 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tslib@^2.0.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -2541,10 +2746,10 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" - integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +typescript@5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== ua-parser-js@^0.7.30: version "0.7.37" @@ -2606,10 +2811,10 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -2621,15 +2826,20 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -webpack-cli@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.0.tgz#abc4b1f44b50250f2632d8b8b536cfe2f6257891" - integrity sha512-a7KRJnCxejFoDpYTOwzm5o21ZXMaNqtRlvS183XzGDUPRdVEzJNImcQokqYZ8BNTnk9DkKiuWxw75+DCCoZ26w== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-cli@5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^2.1.0" - "@webpack-cli/info" "^2.0.1" - "@webpack-cli/serve" "^2.0.3" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" colorette "^2.0.14" commander "^10.0.1" cross-spawn "^7.0.3" @@ -2640,52 +2850,53 @@ webpack-cli@5.1.0: rechoir "^0.8.0" webpack-merge "^5.7.3" -webpack-dev-middleware@^5.3.1: - version "5.3.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" - integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== +webpack-dev-middleware@^7.1.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz#2af00538b6e4eda05f5afdd5d711dbebc05958f7" + integrity sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA== dependencies: colorette "^2.0.10" - memfs "^3.4.3" + memfs "^4.6.0" mime-types "^2.1.31" + on-finished "^2.4.1" range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@4.15.0: - version "4.15.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.0.tgz#87ba9006eca53c551607ea0d663f4ae88be7af21" - integrity sha512-HmNB5QeSl1KpulTBQ8UT4FPrByYyaLxpJoQ0+s7EvUrMc16m0ZS1sgb1XGqzmgCPk0c9y+aaXxn11tbLzuM7NQ== - dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/serve-static" "^1.13.10" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.1" +webpack-dev-server@5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz#cb6ea47ff796b9251ec49a94f24a425e12e3c9b8" + integrity sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA== + dependencies: + "@types/bonjour" "^3.5.13" + "@types/connect-history-api-fallback" "^1.5.4" + "@types/express" "^4.17.21" + "@types/serve-index" "^1.9.4" + "@types/serve-static" "^1.15.5" + "@types/sockjs" "^0.3.36" + "@types/ws" "^8.5.10" ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" + bonjour-service "^1.2.1" + chokidar "^3.6.0" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^2.0.0" default-gateway "^6.0.3" express "^4.17.3" graceful-fs "^4.2.6" - html-entities "^2.3.2" + html-entities "^2.4.0" http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - launch-editor "^2.6.0" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.1.1" + ipaddr.js "^2.1.0" + launch-editor "^2.6.1" + open "^10.0.3" + p-retry "^6.2.0" + rimraf "^5.0.5" + schema-utils "^4.2.0" + selfsigned "^2.4.1" serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" - ws "^8.13.0" + webpack-dev-middleware "^7.1.0" + ws "^8.16.0" webpack-merge@^4.1.5: version "4.2.2" @@ -2708,34 +2919,34 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@5.82.0: - version "5.82.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.82.0.tgz#3c0d074dec79401db026b4ba0fb23d6333f88e7d" - integrity sha512-iGNA2fHhnDcV1bONdUu554eZx+XeldsaeQ8T67H6KKHl2nUSwX8Zm7cmzOA46ox/X1ARxf7Bjv8wQ/HsB5fxBg== +webpack@5.91.0: + version "5.91.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" + integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.0" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-assertions "^1.9.0" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.13.0" + enhanced-resolve "^5.16.0" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.2" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.3.7" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: @@ -2752,6 +2963,14 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which@^1.2.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -2776,7 +2995,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -2785,15 +3004,29 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^8.13.0: - version "8.15.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.15.1.tgz#271ba33a45ca0cc477940f7f200cd7fba7ee1997" - integrity sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ== +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + +ws@^8.16.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== ws@~8.11.0: version "8.11.0" diff --git a/proto/.gitignore b/proto/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/proto/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/proto/build.gradle.kts b/proto/build.gradle.kts new file mode 100644 index 000000000..f3b9c3eab --- /dev/null +++ b/proto/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + kotlin("multiplatform") + id("com.android.library") + id("com.google.devtools.ksp") + id("com.squareup.wire") +} + +wire { + kotlin { + } +} + +kotlin { + jvmToolchain(17) + + androidTarget() + jvm() + + sourceSets { + androidMain { + dependencies { + implementation(libs.androidx.datastore) + } + } + } +} + +android { + compileSdk = AndroidSdk.compile + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + + defaultConfig { + minSdk = AndroidSdk.min + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + } + + namespace = "dev.johnoreilly.confetti.proto" +} + + +dependencies { + coreLibraryDesugaring(libs.desugar) +} diff --git a/proto/proguard-rules.pro b/proto/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/proto/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/proto/src/androidMain/AndroidManifest.xml b/proto/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..a5918e68a --- /dev/null +++ b/proto/src/androidMain/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/dev/johnoreilly/confetti/settings/WearSettingsSerializer.kt b/proto/src/androidMain/kotlin/dev/johnoreilly/confetti/settings/WearSettingsSerializer.kt similarity index 100% rename from shared/src/androidMain/kotlin/dev/johnoreilly/confetti/settings/WearSettingsSerializer.kt rename to proto/src/androidMain/kotlin/dev/johnoreilly/confetti/settings/WearSettingsSerializer.kt diff --git a/shared/src/commonMain/proto/wear.proto b/proto/src/commonMain/proto/wear.proto similarity index 100% rename from shared/src/commonMain/proto/wear.proto rename to proto/src/commonMain/proto/wear.proto diff --git a/settings.gradle.kts b/settings.gradle.kts index b08baf8b1..e9dc90468 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,9 +9,11 @@ pluginManagement { includeGroupByRegex(".*android.*") } } + mavenLocal() mavenCentral() maven(url = "https://androidx.dev/storage/compose-compiler/repository") maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev") + maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental") gradlePluginPortal { content { } @@ -45,6 +47,9 @@ include(":wearApp") include(":wearBenchmark") include(":webApp") include(":compose-desktop") +include(":compose-web") +include(":proto") + check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { "This project needs to be run with Java 17 or higher (found: ${JavaVersion.current()})." diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index eec36961d..bd515465d 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,5 +1,6 @@ @file:Suppress("OPT_IN_USAGE") import com.codingfeline.buildkonfig.compiler.FieldSpec +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl import java.util.Properties plugins { @@ -8,7 +9,6 @@ plugins { id("com.apollographql.apollo3") id("org.jetbrains.compose") id("com.google.devtools.ksp") - id("com.squareup.wire") id("maven-publish") id("kotlinx-serialization") alias(libs.plugins.kmmbridge) @@ -21,12 +21,19 @@ dependencies { implementation(platform(libs.firebase.bom)) } -wire { - kotlin { - } -} kotlin { + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + moduleName = "confetti" + browser { + commonWebpackConfig { + outputFileName = "confetti.js" + } + } + binaries.executable() + } + androidTarget() jvm() @@ -63,9 +70,15 @@ kotlin { implementation(libs.atomicfu) api(libs.kotlinx.datetime) + api("io.github.qdsfdhvh:image-loader:1.7.8") { + exclude(group = "io.ktor") + + // group = "io.ktor", name = "ktor-client-core" + } + + implementation("io.ktor:ktor-client-core:3.0.0-wasm2") + api(libs.bundles.multiplatform.settings) - api(libs.androidx.datastore) - api(libs.androidx.datastore.preferences) api(libs.koin.core) implementation(libs.koin.compose.multiplatform) @@ -75,10 +88,8 @@ kotlin { api(libs.decompose.decompose) api(libs.decompose.extensions.compose) - api(libs.essenty.lifecycle) - // Multiplatform Logging api(libs.kermit) implementation(compose.ui) @@ -86,9 +97,11 @@ kotlin { implementation(compose.foundation) implementation(compose.material3) implementation(compose.components.resources) + implementation(compose.materialIconsExtended) implementation(libs.coil3.compose) implementation(libs.coil3.network.ktor) api(libs.materialkolor) + api(libs.compose.window.size) api(libs.generativeai) } } @@ -101,6 +114,7 @@ kotlin { val mobileMain by getting { dependencies { implementation(libs.firebase.mpp.auth) + implementation(libs.apollo.normalized.cache.sqlite) } } @@ -111,6 +125,7 @@ kotlin { androidMain { dependsOn(mobileMain) dependencies { + api(project(":proto")) api(libs.androidx.lifecycle.viewmodel.ktx) implementation(libs.okhttp) implementation(libs.okhttp.coroutines) @@ -129,6 +144,9 @@ kotlin { api(libs.androidx.work.runtime.ktx) api(libs.multiplatform.settings.datastore) + api(libs.androidx.datastore) + api(libs.androidx.datastore.preferences) + api("com.mikepenz:multiplatform-markdown-renderer:0.14.0") } @@ -147,6 +165,13 @@ kotlin { implementation(libs.okhttp) implementation(libs.okhttp.coroutines) implementation(libs.apollo.testing) + implementation(libs.apollo.normalized.cache.sqlite) + } + } + + val wasmJsMain by getting { + dependencies { + implementation("io.ktor:ktor-client-js:3.0.0-wasm2") } } } diff --git a/shared/src/androidMain/kotlin/dev/johnoreilly/confetti/di/KoinAndroid.kt b/shared/src/androidMain/kotlin/dev/johnoreilly/confetti/di/KoinAndroid.kt index ed1e2a828..b86708955 100644 --- a/shared/src/androidMain/kotlin/dev/johnoreilly/confetti/di/KoinAndroid.kt +++ b/shared/src/androidMain/kotlin/dev/johnoreilly/confetti/di/KoinAndroid.kt @@ -14,6 +14,9 @@ import coil.ImageLoader import coil.decode.SvgDecoder import com.apollographql.apollo3.ApolloClient import com.apollographql.apollo3.cache.normalized.FetchPolicy +import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory +import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory +import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory import com.apollographql.apollo3.network.http.DefaultHttpEngine import com.apollographql.apollo3.network.ws.DefaultWebSocketEngine import com.google.android.horologist.annotations.ExperimentalHorologistApi @@ -45,6 +48,7 @@ import org.koin.core.module.dsl.singleOf import org.koin.core.qualifier.named import org.koin.dsl.module +@OptIn(ExperimentalHorologistApi::class, ExperimentalSettingsImplementation::class) actual fun platformModule() = module { singleOf(::AndroidDateService) { bind() } single { @@ -115,4 +119,9 @@ actual fun platformModule() = module { val Context.settingsStore by preferencesDataStore("settings") -actual fun getDatabaseName(conference: String, uid: String?) = "$conference$uid.db" + +actual fun getNormalizedCacheFactory(conference: String, uid: String?): NormalizedCacheFactory { + val sqlNormalizedCacheFactory = SqlNormalizedCacheFactory("$conference$uid.db") + return MemoryCacheFactory(10 * 1024 * 1024) + .chain(sqlNormalizedCacheFactory) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ApolloClientCache.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ApolloClientCache.kt index 0534c1da6..cef4148bc 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ApolloClientCache.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ApolloClientCache.kt @@ -6,17 +6,14 @@ import com.apollographql.apollo3.api.ApolloRequest import com.apollographql.apollo3.api.ApolloResponse import com.apollographql.apollo3.api.ExecutionContext import com.apollographql.apollo3.api.Operation -import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory import com.apollographql.apollo3.cache.normalized.apolloStore import com.apollographql.apollo3.cache.normalized.normalizedCache -import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory import com.apollographql.apollo3.exception.ApolloException import com.apollographql.apollo3.exception.ApolloHttpException import com.apollographql.apollo3.interceptor.ApolloInterceptor import com.apollographql.apollo3.interceptor.ApolloInterceptorChain import com.apollographql.apollo3.network.NetworkMonitor -import com.apollographql.apollo3.network.http.HttpNetworkTransport -import dev.johnoreilly.confetti.di.getDatabaseName +import dev.johnoreilly.confetti.di.getNormalizedCacheFactory import dev.johnoreilly.confetti.utils.registerApolloDebugServer import dev.johnoreilly.confetti.utils.unregisterApolloDebugServer import kotlinx.atomicfu.locks.reentrantLock @@ -42,8 +39,8 @@ class TokenProviderContext(val tokenProvider: TokenProvider) : ExecutionContext. } class ApolloClientCache : KoinComponent { - val _clients = mutableMapOf() - val mutex = reentrantLock() + private val _clients = mutableMapOf() + private val mutex = reentrantLock() private val tokenProviderInterceptor = object : ApolloInterceptor { override fun intercept( @@ -107,22 +104,20 @@ class ApolloClientCache : KoinComponent { uid: String?, writeToCacheAsynchronously: Boolean ): ApolloClient { - val sqlNormalizedCacheFactory = SqlNormalizedCacheFactory(getDatabaseName(conference, uid)) - val memoryFirstThenSqlCacheFactory = MemoryCacheFactory(10 * 1024 * 1024) - .chain(sqlNormalizedCacheFactory) + val normalizedCacheFactory = getNormalizedCacheFactory(conference, uid) return get() - .networkMonitor( - object : NetworkMonitor { - override val isOnline: Boolean - get() = true - override suspend fun waitForNetwork() {} - override fun close() {} - } - ) +// .networkMonitor( +// object : NetworkMonitor { +// override val isOnline: Boolean +// get() = true +// override suspend fun waitForNetwork() {} +// override fun close() {} +// } +// ) .addHttpHeader("conference", conference) .normalizedCache( - memoryFirstThenSqlCacheFactory, + normalizedCacheFactory, writeToCacheAsynchronously = writeToCacheAsynchronously ) .autoPersistedQueries() diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ConfettiRepository.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ConfettiRepository.kt index ed68d3587..4566ff17d 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ConfettiRepository.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ConfettiRepository.kt @@ -70,7 +70,6 @@ class ConfettiRepository : KoinComponent { return response.data != null } - suspend fun addBookmark( conference: String, uid: String?, diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionDetailsComponent.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionDetailsComponent.kt index aaef264de..92bd2705b 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionDetailsComponent.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionDetailsComponent.kt @@ -37,7 +37,7 @@ interface SessionDetailsComponent { sealed class SessionDetailsUiState { object Loading : SessionDetailsUiState() object Error : SessionDetailsUiState() - data class Success(val sessionDetails: SessionDetails) : SessionDetailsUiState() + data class Success(val conference: String, val sessionDetails: SessionDetails) : SessionDetailsUiState() } class DefaultSessionDetailsComponent( @@ -63,7 +63,7 @@ class DefaultSessionDetailsComponent( .map { val details = it.data?.session?.sessionDetails if (details != null) { - SessionDetailsUiState.Success(details) + SessionDetailsUiState.Success(conference, details) } else { SessionDetailsUiState.Error } diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionsComponent.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionsComponent.kt index e46fcc028..2a1f5114d 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionsComponent.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SessionsComponent.kt @@ -304,6 +304,7 @@ class SessionsSimpleComponent( } return SessionsUiState.Success( now = dateService.now(), + conference = conference, conferenceName = conferenceName, venueLat = venueLat, venueLon = venueLon, @@ -326,6 +327,7 @@ sealed interface SessionsUiState { data class Success( val now: LocalDateTime, + val conference: String, val conferenceName: String, val venueLat: Double?, val venueLon: Double?, diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SpeakerDetailsComponent.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SpeakerDetailsComponent.kt index 7509aa32a..1524b0782 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SpeakerDetailsComponent.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/decompose/SpeakerDetailsComponent.kt @@ -23,7 +23,7 @@ interface SpeakerDetailsComponent { sealed class SpeakerDetailsUiState { object Loading : SpeakerDetailsUiState() object Error : SpeakerDetailsUiState() - class Success(val details: SpeakerDetails) : SpeakerDetailsUiState() + class Success(val conference: String, val details: SpeakerDetails) : SpeakerDetailsUiState() } class DefaultSpeakerDetailsComponent( @@ -43,7 +43,7 @@ class DefaultSpeakerDetailsComponent( ?.firstOrNull { it.id == speakerId } if (details != null) { - emit(Success(details)) + emit(Success(conference, details)) } else { emit(Error) } diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/di/Koin.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/di/Koin.kt index 172184476..c1d505e13 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/di/Koin.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/di/Koin.kt @@ -2,6 +2,7 @@ package dev.johnoreilly.confetti.di +import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory import com.russhwolf.settings.ExperimentalSettingsApi import dev.johnoreilly.confetti.ApolloClientCache import dev.johnoreilly.confetti.AppSettings @@ -22,7 +23,7 @@ fun initKoin(appDeclaration: KoinAppDeclaration = {}) = } // called by iOS client -fun initKoin() = initKoin() {} +fun initKoin() = initKoin {} fun commonModule() = module { includes(platformModule()) @@ -34,4 +35,4 @@ fun commonModule() = module { singleOf(::GeminiApi) } -expect fun getDatabaseName(conference: String, uid: String?): String +expect fun getNormalizedCacheFactory(conference: String, uid: String?): NormalizedCacheFactory diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/ConferenceListView.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/ConferenceListView.kt index 214f9d514..104600169 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/ConferenceListView.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/ConferenceListView.kt @@ -94,10 +94,10 @@ fun ConferenceCard( Card( modifier = Modifier .clip(shape = RoundedCornerShape(8.dp)) + .padding(8.dp) .clickable(onClick = { navigateToConference(conference) }) - .padding(8.dp) .fillMaxWidth() ) { Column(Modifier.fillMaxWidth().padding(16.dp), diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewShared.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewShared.kt index b073ed0e5..543003d88 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewShared.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewShared.kt @@ -53,6 +53,7 @@ import sessionTimeFormat @OptIn(ExperimentalLayoutApi::class) @Composable internal fun SessionDetailViewShared( + conference: String, session: SessionDetails?, onSpeakerClick: (speakerId: String) -> Unit, onSocialLinkClicked: (String) -> Unit @@ -120,7 +121,7 @@ internal fun SessionDetailViewShared( Column(modifier = Modifier.padding(contentPadding)) { session.speakers.forEach { speaker -> - SessionSpeakerInfo(speaker.speakerDetails, onSpeakerClick, onSocialLinkClicked) + SessionSpeakerInfo(conference, speaker.speakerDetails, onSpeakerClick, onSocialLinkClicked) } } @@ -134,6 +135,7 @@ internal fun SessionDetailViewShared( @OptIn(ExperimentalResourceApi::class) @Composable internal fun SessionSpeakerInfo( + conference: String, speaker: SpeakerDetails, onSpeakerClick: (speakerId: String) -> Unit, onSocialLinkClick: (String) -> Unit @@ -144,8 +146,9 @@ internal fun SessionSpeakerInfo( ) { Row { speaker.photoUrl?.let { + val url = "https://confetti-app.dev/images/avatar/${conference}/${speaker.id}" AsyncImage( - model = speaker.photoUrl, + model = url, contentDescription = speaker.name, contentScale = ContentScale.Crop, modifier = Modifier.size(64.dp) diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListGridView.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListGridView.kt index f842041e6..cf95598fe 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListGridView.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListGridView.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowColumn import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -23,6 +22,11 @@ import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Bolt +import androidx.compose.material.icons.outlined.Bookmark +import androidx.compose.material.icons.outlined.BookmarkAdd +import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface @@ -38,7 +42,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -47,6 +50,7 @@ import dev.johnoreilly.confetti.decompose.SessionsUiState import dev.johnoreilly.confetti.fragment.RoomDetails import dev.johnoreilly.confetti.fragment.SessionDetails import dev.johnoreilly.confetti.isLightning +import dev.johnoreilly.confetti.isService @OptIn(ExperimentalFoundationApi::class) @Composable @@ -59,13 +63,13 @@ fun SessionListGridView( isLoggedIn: Boolean, onRefresh: () -> Unit, ) { - println(uiState) when (uiState) { SessionsUiState.Error -> ErrorView(onRefresh) SessionsUiState.Loading -> LoadingView() is SessionsUiState.Success -> { + println("SessionsUiState.Success, conference = ${uiState.conferenceName}") Column { val pagerState = rememberPagerState { uiState.formattedConfDates.size @@ -75,8 +79,7 @@ fun SessionListGridView( HorizontalPager(state = pagerState) { page -> - Row(Modifier.horizontalScroll(rememberScrollState())) { - val sessionsByStartTime = uiState.sessionsByStartTimeList[page] + Row(Modifier.horizontalScroll(rememberScrollState())) { val sessionsByStartTime = uiState.sessionsByStartTimeList[page] val rooms = uiState.rooms.filter { room -> sessionsByStartTime.values.any { session -> session.any { it.room?.name == room.name } } @@ -112,6 +115,7 @@ fun SessionListGridView( sessionsByStartTime.forEach { item { SessionGridRow( + conference = uiState.conference, sessionByTimeList = it, rooms = rooms, bookmarks = uiState.bookmarks, @@ -137,6 +141,7 @@ fun SessionListGridView( @Composable fun SessionGridRow( + conference: String, sessionByTimeList: Map.Entry>, bookmarks: Set, rooms: List, @@ -163,58 +168,73 @@ fun SessionGridRow( sessionByTimeList.value.find { it.room?.name == room.name } } - sessionList.forEach { session -> - Surface( - modifier = Modifier - .width(sessionInfoWidth) - .height(220.dp) - .padding(bottom = 16.dp) - .border(BorderStroke(1.dp, MaterialTheme.colorScheme.primary)), - color = MaterialTheme.colorScheme.surfaceContainerLow - ) { - Box(Modifier.fillMaxSize()) { - Column( - modifier = Modifier - .clickable(onClick = { - sessionSelected(session.id) - }) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - modifier = Modifier.align(Alignment.Start), - text = session.title, - fontSize = 16.sp, - textAlign = TextAlign.Start, - color = MaterialTheme.colorScheme.onSecondaryContainer - ) - Spacer(modifier = Modifier.weight(1f)) - Speakers(session = session) - if (session.isLightning()) { - Surface( - modifier = Modifier.fillMaxWidth().padding(top = 8.dp), - shape = MaterialTheme.shapes.small, - color = MaterialTheme.colorScheme.primaryContainer - ) { - Row(Modifier.padding(vertical = 4.dp, horizontal = 8.dp)) { - // TODO find alternative - //Icon(Icons.Default.Bolt, "lightning") - Spacer(Modifier.width(4.dp)) - Text("Lightning / ${session.startsAt.time}-${session.endsAt.time}") + val height = if (sessionList.size == 1 && sessionList[0].isService()) + 100.dp + else + 220.dp + + rooms.forEach { room -> + val session = sessionList.firstOrNull { it.room?.name == room.name } + + if (session != null) { + Surface( + modifier = Modifier + .width(sessionInfoWidth) + .height(height) + .padding(bottom = 16.dp) + .clickable(onClick = { + sessionSelected(session.id) + }) + .border(BorderStroke(1.dp, MaterialTheme.colorScheme.primary)), + color = MaterialTheme.colorScheme.surfaceContainerLow + ) { + Box(Modifier.fillMaxSize()) { + Column( + modifier = Modifier + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + modifier = Modifier.align(Alignment.Start), + text = session.title, + fontSize = 16.sp, + textAlign = TextAlign.Start, + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + //Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.height(8.dp)) + Speakers(conference, session) + if (session.isLightning()) { + Surface( + modifier = Modifier.fillMaxWidth().padding(top = 8.dp), + shape = MaterialTheme.shapes.small, + color = MaterialTheme.colorScheme.primaryContainer + ) { + Row(Modifier.padding(vertical = 4.dp, horizontal = 8.dp)) { + // TODO find alternative + Icon(Icons.Default.Bolt, "lightning") + Spacer(Modifier.width(4.dp)) + Text("Lightning / ${session.startsAt.time}-${session.endsAt.time}") + } } } } + Bookmark( + modifier = Modifier.align(Alignment.CenterEnd), + bookmarks = bookmarks, + session = session, + isLoggedIn = isLoggedIn, + removeBookmark = removeBookmark, + addBookmark = addBookmark, + onNavigateToSignIn = onNavigateToSignIn + ) } - Bookmark( - modifier = Modifier.align(Alignment.CenterEnd), - bookmarks = bookmarks, - session = session, - isLoggedIn = isLoggedIn, - removeBookmark = removeBookmark, - addBookmark = addBookmark, - onNavigateToSignIn = onNavigateToSignIn - ) } + } else { + Box(Modifier + .width(sessionInfoWidth) + .height(height) + ) } } } @@ -222,57 +242,33 @@ fun SessionGridRow( @Composable @OptIn(ExperimentalLayoutApi::class) -private fun Speakers(session: SessionDetails) { - if (session.speakers.count() < 4) { - session.speakers.forEach { speaker -> - Row( - Modifier - .fillMaxWidth() - .padding(2.dp), - verticalAlignment = Alignment.CenterVertically - ) { - if (speaker.speakerDetails.photoUrl?.isNotEmpty() == true) { - AsyncImage( - model = speaker.speakerDetails.photoUrl, - contentDescription = speaker.speakerDetails.name, - contentScale = ContentScale.Fit, - modifier = Modifier - .size(20.dp) - .clip(RoundedCornerShape(16.dp)) - ) - } - - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = speaker.speakerDetails.name, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.primary +private fun Speakers(conference: String, session: SessionDetails) { + session.speakers.forEach { speaker -> + Row( + Modifier + .fillMaxWidth() + .padding(2.dp), + verticalAlignment = Alignment.CenterVertically + ) { + if (speaker.speakerDetails.photoUrl?.isNotEmpty() == true) { + val url = "https://confetti-app.dev/images/avatar/${conference}/${speaker.id}" + AsyncImage( + model = url, + contentDescription = speaker.speakerDetails.name, + contentScale = ContentScale.Fit, + modifier = Modifier + .size(20.dp) + .clip(RoundedCornerShape(16.dp)) ) - - } - } - } else { - FlowColumn(modifier = Modifier.fillMaxWidth(), maxItemsInEachColumn = 2) { - session.speakers.forEach { speaker -> - Row { - AsyncImage( - model = speaker.speakerDetails.photoUrl, - contentDescription = speaker.speakerDetails.name, - contentScale = ContentScale.Fit, - modifier = Modifier - .size(20.dp) - .clip(RoundedCornerShape(16.dp)) - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = speaker.speakerDetails.name, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.primary, - overflow = TextOverflow.Ellipsis - ) - Spacer(modifier = Modifier.width(4.dp)) - } } + + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = speaker.speakerDetails.name, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.primary + ) + } } } @@ -301,15 +297,16 @@ private fun Bookmark( } } ) { - // TODO find alternative -// Icon( -// imageVector = Icons.Outlined.Bookmark, -// contentDescription = "remove bookmark", -// tint = MaterialTheme.colorScheme.primary, -// modifier = Modifier.padding(8.dp) -// ) + Icon( + imageVector = Icons.Outlined.Bookmark, + contentDescription = "remove bookmark", + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.padding(8.dp) + ) } } else { + // disable from this view for now +/* IconButton( modifier = modifier, onClick = { @@ -320,13 +317,14 @@ private fun Bookmark( } } ) { -// TODO find alternative -// Icon( -// imageVector = Icons.Outlined.BookmarkAdd, -// contentDescription = "add bookmark", -// modifier = Modifier.padding(8.dp) -// ) + Icon( + imageVector = Icons.Outlined.BookmarkAdd, + contentDescription = "add bookmark", + modifier = Modifier.padding(8.dp) + ) } + + */ } if (showDialog) { SignInDialog( diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListView.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListView.kt new file mode 100644 index 000000000..ba8caf99d --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SessionListView.kt @@ -0,0 +1,234 @@ +@file:OptIn(ExperimentalFoundationApi::class) + +package dev.johnoreilly.confetti.ui + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccessTime +import androidx.compose.material.icons.filled.Bolt +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.TabRow +import androidx.compose.material3.TabRowDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import dev.johnoreilly.confetti.decompose.SessionsUiState +import dev.johnoreilly.confetti.fragment.SessionDetails +import dev.johnoreilly.confetti.isBreak +import dev.johnoreilly.confetti.isLightning +import dev.johnoreilly.confetti.isService +import dev.johnoreilly.confetti.sessionSpeakers +import dev.johnoreilly.confetti.ui.ErrorView +import dev.johnoreilly.confetti.ui.LoadingView +import dev.johnoreilly.confetti.ui.SignInDialog +import dev.johnoreilly.confetti.ui.component.ConfettiHeader +import dev.johnoreilly.confetti.ui.component.ConfettiTab +import dev.johnoreilly.confetti.ui.component.pagerTabIndicatorOffset +import kotlinx.coroutines.launch +import kotlin.math.abs + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun SessionListView( + uiState: SessionsUiState, + sessionSelected: (sessionId: String) -> Unit, + addBookmark: (sessionId: String) -> Unit, + removeBookmark: (sessionId: String) -> Unit, + onRefresh: () -> Unit, + onNavigateToSignIn: () -> Unit, + isLoggedIn: Boolean, +) { + when (uiState) { + SessionsUiState.Error -> ErrorView(onRefresh) + SessionsUiState.Loading -> LoadingView() + is SessionsUiState.Success -> { + Column { + val initialPageIndex by remember { + derivedStateOf { uiState.confDates.indexOf(uiState.now.date) } + } + + val pagerState = rememberPagerState( + if (initialPageIndex == -1) 0 else initialPageIndex + ) { + uiState.formattedConfDates.size + } + + SessionListTabRow(pagerState, uiState) + + HorizontalPager(state = pagerState) { page -> + val sessions = uiState.sessionsByStartTimeList[page] + + val initialItemIndex by remember { + derivedStateOf { + // If initial page is null, we are in the wrong date and should not + // consider the current hour. + if (initialPageIndex != page) return@derivedStateOf 0 + + // Retrieves the initial item matching an hour block, including the + // aggregated index (ignores time grouping). + val initialItem = sessions + .values + .flatten() + .withIndex() + .minByOrNull { (_, session) -> + val timeOfNowInMillis = uiState + .now + .time + .toMillisecondOfDay() + val timeOfSessionStartInMillis = session + .startsAt + .time + .toMillisecondOfDay() + abs(timeOfNowInMillis - timeOfSessionStartInMillis) + } + + // Count the number of sticky headers until the initial item. + val stickyHeader = sessions + .entries + .withIndex() + .firstOrNull { + it.value.value.contains(initialItem?.value) + } + + val stickyHeaderIndex = stickyHeader?.index ?: 0 + val initialItemIndex = initialItem?.index ?: 0 + + // Sum the index of the initial item and the sticky headers. + stickyHeaderIndex + initialItemIndex + } + } + + val listState = rememberLazyListState(initialItemIndex) + + Box( + Modifier + .clipToBounds() + ) { + LazyColumn(state = listState) { + sessions.forEach { (startTime, sessions) -> + + stickyHeader { + ConfettiHeader(icon = Icons.Filled.AccessTime, text = startTime) + } + + val sortedSessions = + sessions.sortedBy { session -> uiState.rooms.indexOfFirst { it.name == session.room?.name } } + items(sortedSessions) { session -> + SessionItemView( + session = session, + sessionSelected = sessionSelected, + isBookmarked = uiState.bookmarks.contains(session.id), + addBookmark = addBookmark, + removeBookmark = removeBookmark, + onNavigateToSignIn = onNavigateToSignIn, + isLoggedIn = isLoggedIn, + ) + } + } + } + } + } + } + } + } +} + + +@Composable +fun SessionItemView( + session: SessionDetails, + sessionSelected: (sessionId: String) -> Unit, + isBookmarked: Boolean, + addBookmark: (String) -> Unit, + removeBookmark: (String) -> Unit, + onNavigateToSignIn: () -> Unit = {}, + isLoggedIn: Boolean, +) { + + var modifier = Modifier.fillMaxSize() + if (!session.isBreak()) { + modifier = modifier.clickable(onClick = { + sessionSelected(session.id) + }) + } + + if (session.isService()) { + modifier = modifier.background(Color.White) + } + + Row(modifier.padding(horizontal = 16.dp, vertical = 8.dp)) { + Column(modifier = Modifier.weight(1f)) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + text = session.title, + style = MaterialTheme.typography.bodyLarge.copy(fontWeight = FontWeight.Bold) + ) + } + + session.room?.let { room -> + Row( + modifier = Modifier.padding(top = 4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + session.sessionSpeakers() ?: "", + style = MaterialTheme.typography.bodyMedium + ) + } + + Row( + modifier = Modifier.padding(top = 4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + room.name, + style = MaterialTheme.typography.bodyMedium, + color = Color.Gray + ) + } + } + + if (session.isLightning()) { + Surface( + modifier = Modifier.padding(top = 8.dp), + shape = MaterialTheme.shapes.small, + color = MaterialTheme.colorScheme.primaryContainer, + ) { + Row(Modifier.padding(vertical = 4.dp, horizontal = 8.dp)) { + Icon(Icons.Default.Bolt, "lightning") + Spacer(Modifier.width(4.dp)) + Text("Lightning / ${session.startsAt.time}-${session.endsAt.time}") + } + } + } + } + } +} diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersDetailsView.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersDetailsView.kt index 640fba1a8..2931cbcca 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersDetailsView.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersDetailsView.kt @@ -45,6 +45,7 @@ import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterial3Api::class) @Composable fun SpeakerDetailsView( + conference: String, speaker: SpeakerDetails, navigateToSession: (id: String) -> Unit, popBack: () -> Unit @@ -98,9 +99,9 @@ fun SpeakerDetailsView( Spacer(modifier = Modifier.size(16.dp)) - + val url = "https://confetti-app.dev/images/avatar/${conference}/${speaker.id}" AsyncImage( - model = speaker.photoUrl, + model = url, contentDescription = speaker.name, contentScale = ContentScale.Fit, modifier = Modifier diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersGridView.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersGridView.kt index 3c11469ad..855ee42e4 100644 --- a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersGridView.kt +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/ui/SpeakersGridView.kt @@ -25,6 +25,7 @@ import dev.johnoreilly.confetti.fragment.SpeakerDetails @Composable fun SpeakerGridView( + conference: String, speakers: List, navigateToSpeaker: (id: String) -> Unit ) { @@ -39,8 +40,11 @@ fun SpeakerGridView( .padding(12.dp), horizontalAlignment = Alignment.CenterHorizontally ) { + + // proxy image requests through backend + val url = "https://confetti-app.dev/images/avatar/${conference}/${speaker.id}" AsyncImage( - model = speaker.photoUrl, + model = url, contentDescription = speaker.name, contentScale = ContentScale.Fit, modifier = Modifier @@ -58,4 +62,4 @@ fun SpeakerGridView( } } ) -} +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/utils/UIUtils.kt b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/utils/UIUtils.kt new file mode 100644 index 000000000..7284b09c3 --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/johnoreilly/confetti/utils/UIUtils.kt @@ -0,0 +1,7 @@ +package dev.johnoreilly.confetti.utils + +import androidx.compose.material3.windowsizeclass.WindowSizeClass +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass + +val WindowSizeClass.isExpanded: Boolean + get() = widthSizeClass == WindowWidthSizeClass.Expanded \ No newline at end of file diff --git a/shared/src/iosMain/kotlin/dev/johnoreilly/confetti/di/KoiniOS.kt b/shared/src/iosMain/kotlin/dev/johnoreilly/confetti/di/KoiniOS.kt index bc3ac9ee5..ad31af3c4 100644 --- a/shared/src/iosMain/kotlin/dev/johnoreilly/confetti/di/KoiniOS.kt +++ b/shared/src/iosMain/kotlin/dev/johnoreilly/confetti/di/KoiniOS.kt @@ -4,6 +4,7 @@ package dev.johnoreilly.confetti.di import com.apollographql.apollo3.ApolloClient import com.apollographql.apollo3.cache.normalized.FetchPolicy +import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory import com.russhwolf.settings.ExperimentalSettingsApi @@ -11,22 +12,19 @@ import com.russhwolf.settings.NSUserDefaultsSettings import com.russhwolf.settings.ObservableSettings import com.russhwolf.settings.coroutines.toFlowSettings import dev.johnoreilly.confetti.auth.Authentication -import dev.johnoreilly.confetti.auth.DefaultAuthentication import dev.johnoreilly.confetti.utils.DateService import dev.johnoreilly.confetti.utils.IosDateService -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import org.koin.core.module.dsl.bind import org.koin.core.module.dsl.singleOf import org.koin.dsl.module import platform.Foundation.NSUserDefaults -import platform.posix.bind + +@OptIn(ExperimentalSettingsApi::class) actual fun platformModule() = module { single { Authentication.Disabled } single { NSUserDefaultsSettings(NSUserDefaults.standardUserDefaults) } single { get().toFlowSettings() } - single { SqlNormalizedCacheFactory("confetti.db") } singleOf(::IosDateService) { bind() } single { FetchPolicy.CacheAndNetwork } factory { @@ -35,4 +33,8 @@ actual fun platformModule() = module { } } -actual fun getDatabaseName(conference: String, uid: String?) = "$conference$uid.db" +actual fun getNormalizedCacheFactory(conference: String, uid: String?): NormalizedCacheFactory { + val sqlNormalizedCacheFactory = SqlNormalizedCacheFactory("$conference$uid.db") + return MemoryCacheFactory(10 * 1024 * 1024) + .chain(sqlNormalizedCacheFactory) +} \ No newline at end of file diff --git a/shared/src/jvmMain/kotlin/dev/johnoreilly/confetti/di/KoinJVM.kt b/shared/src/jvmMain/kotlin/dev/johnoreilly/confetti/di/KoinJVM.kt index 8e64d3b15..e0048ebff 100644 --- a/shared/src/jvmMain/kotlin/dev/johnoreilly/confetti/di/KoinJVM.kt +++ b/shared/src/jvmMain/kotlin/dev/johnoreilly/confetti/di/KoinJVM.kt @@ -1,9 +1,11 @@ -@file:OptIn(ExperimentalSettingsApi::class, ApolloExperimental::class) +@file:OptIn(ExperimentalSettingsApi::class) package dev.johnoreilly.confetti.di -import com.apollographql.apollo3.annotations.ApolloExperimental import com.apollographql.apollo3.cache.normalized.FetchPolicy +import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory +import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory +import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory import com.russhwolf.settings.ExperimentalSettingsApi import com.russhwolf.settings.ObservableSettings import com.russhwolf.settings.PreferencesSettings @@ -32,4 +34,8 @@ actual fun platformModule() = module { } } -actual fun getDatabaseName(conference: String, uid: String?) = "jdbc:sqlite:$conference$uid.db" +actual fun getNormalizedCacheFactory(conference: String, uid: String?): NormalizedCacheFactory { + val sqlNormalizedCacheFactory = SqlNormalizedCacheFactory("jdbc:sqlite:$conference$uid.db") + return MemoryCacheFactory(10 * 1024 * 1024) + .chain(sqlNormalizedCacheFactory) +} \ No newline at end of file diff --git a/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/decompose/SettingsComponent.kt b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/decompose/SettingsComponent.kt new file mode 100644 index 000000000..7c9da56ea --- /dev/null +++ b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/decompose/SettingsComponent.kt @@ -0,0 +1,3 @@ +package dev.johnoreilly.confetti.decompose + +actual interface SettingsComponent \ No newline at end of file diff --git a/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/di/KoinWasmJs.kt b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/di/KoinWasmJs.kt new file mode 100644 index 000000000..199288022 --- /dev/null +++ b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/di/KoinWasmJs.kt @@ -0,0 +1,33 @@ +@file:OptIn(ExperimentalSettingsApi::class, ApolloExperimental::class) + +package dev.johnoreilly.confetti.di + +import com.apollographql.apollo3.annotations.ApolloExperimental +import com.apollographql.apollo3.cache.normalized.FetchPolicy +import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory +import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory +import com.russhwolf.settings.ExperimentalSettingsApi +import com.russhwolf.settings.StorageSettings +import com.russhwolf.settings.coroutines.FlowSettings +import com.russhwolf.settings.coroutines.toFlowSettings +import com.russhwolf.settings.serialization.toRuntimeObservable +import dev.johnoreilly.confetti.auth.Authentication +import dev.johnoreilly.confetti.utils.DateService +import dev.johnoreilly.confetti.utils.WasmDateService +import org.koin.core.module.dsl.bind +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.module + +@OptIn(ExperimentalSettingsApi::class) +actual fun platformModule() = module { + single { Authentication.Disabled } + single { StorageSettings().toRuntimeObservable().toFlowSettings() } + singleOf(::WasmDateService) { bind() } + single { + FetchPolicy.CacheAndNetwork + } +} + +actual fun getNormalizedCacheFactory(conference: String, uid: String?): NormalizedCacheFactory { + return MemoryCacheFactory(10 * 1024 * 1024) +} \ No newline at end of file diff --git a/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewSharedWrapper.kt b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewSharedWrapper.kt new file mode 100644 index 000000000..6313e2043 --- /dev/null +++ b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/ui/SessionDetailsViewSharedWrapper.kt @@ -0,0 +1,11 @@ +package dev.johnoreilly.confetti.dev.johnoreilly.confetti.ui + +import androidx.compose.runtime.Composable +import dev.johnoreilly.confetti.fragment.SessionDetails +import dev.johnoreilly.confetti.ui.SessionDetailViewShared + +@Composable +fun SessionDetailViewSharedWrapper(conference: String, session: SessionDetails?, onSpeakerClick: (speakerId: String) -> Unit, onSocialLinkClicked: (String) -> Unit) { + SessionDetailViewShared(conference, session, onSpeakerClick, onSocialLinkClicked) +} + diff --git a/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/utils/ApolloDebugServer.kt b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/utils/ApolloDebugServer.kt new file mode 100644 index 000000000..23bc91f38 --- /dev/null +++ b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/utils/ApolloDebugServer.kt @@ -0,0 +1,12 @@ +package dev.johnoreilly.confetti.utils + +import com.apollographql.apollo3.ApolloClient + +actual fun ApolloClient.registerApolloDebugServer(conference: String) { + // no-op +} + +actual fun ApolloClient.unregisterApolloDebugServer() { + // no-op +} + diff --git a/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/utils/WasmDateService.kt b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/utils/WasmDateService.kt new file mode 100644 index 000000000..2feac658c --- /dev/null +++ b/shared/src/wasmJsMain/kotlin/dev/johnoreilly/confetti/utils/WasmDateService.kt @@ -0,0 +1,10 @@ +package dev.johnoreilly.confetti.utils + +import kotlinx.datetime.Clock +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime + +class WasmDateService: DateService { + override fun now(): LocalDateTime = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) +} \ No newline at end of file diff --git a/wearApp/build.gradle.kts b/wearApp/build.gradle.kts index 73a76208b..7d6a278c5 100644 --- a/wearApp/build.gradle.kts +++ b/wearApp/build.gradle.kts @@ -10,6 +10,7 @@ plugins { id("com.google.firebase.crashlytics") id("kotlinx-serialization") id("io.github.takahirom.roborazzi") + id("org.jetbrains.compose") } configureCompilerOptions() diff --git a/webApp/src/commonMain/kotlin/App.kt b/webApp/src/commonMain/kotlin/App.kt index 19ca67f8a..42a945858 100644 --- a/webApp/src/commonMain/kotlin/App.kt +++ b/webApp/src/commonMain/kotlin/App.kt @@ -13,7 +13,6 @@ import androidx.compose.ui.unit.dp import com.apollographql.apollo3.ApolloClient import com.apollographql.apollo3.api.ApolloResponse import com.apollographql.apollo3.api.Operation -import com.apollographql.apollo3.exception.ApolloException import confetti.web.GetConferencesQuery import kotlinx.coroutines.flow.Flow