diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index ec47304f..095b9ec6 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.jetbrains.kotlin.compose) } android { @@ -33,6 +34,9 @@ android { kotlinOptions { jvmTarget = "1.8" } + buildFeatures { + compose = true + } } dependencies { @@ -46,6 +50,15 @@ dependencies { implementation(libs.androidx.recyclerview) implementation(libs.wordpress.rs.android) implementation(project(":Gutenberg")) + + // Compose + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.material.icons.extended) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.activity.compose) + testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/android/app/src/main/java/com/example/gutenbergkit/EditorActivity.kt b/android/app/src/main/java/com/example/gutenbergkit/EditorActivity.kt index bd44e3a0..8d8ad857 100644 --- a/android/app/src/main/java/com/example/gutenbergkit/EditorActivity.kt +++ b/android/app/src/main/java/com/example/gutenbergkit/EditorActivity.kt @@ -3,26 +3,42 @@ package com.example.gutenbergkit import android.os.Bundle import android.webkit.WebView import android.content.pm.ApplicationInfo +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.Redo +import androidx.compose.material.icons.automirrored.filled.Undo +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.viewinterop.AndroidView import org.wordpress.gutenberg.EditorConfiguration import org.wordpress.gutenberg.GutenbergView -class EditorActivity : AppCompatActivity() { +class EditorActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - setContentView(R.layout.activity_editor) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.editor)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - if (0 != (applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE)) { + if (0 != (applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE)) { WebView.setWebContentsDebuggingEnabled(true) } @@ -38,7 +54,105 @@ class EditorActivity : AppCompatActivity() { intent.getParcelableExtra(MainActivity.EXTRA_CONFIGURATION) } ?: EditorConfiguration.builder().build() - val gbView = findViewById(R.id.gutenbergView) - gbView.start(configuration) + setContent { + EditorScreen( + configuration = configuration, + onClose = { finish() } + ) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EditorScreen( + configuration: EditorConfiguration, + onClose: () -> Unit +) { + var showMenu by remember { mutableStateOf(false) } + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar( + title = { }, + navigationIcon = { + IconButton(onClick = onClose) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = "Close" + ) + } + }, + actions = { + IconButton(onClick = { }, enabled = false) { + Icon( + imageVector = Icons.AutoMirrored.Filled.Undo, + contentDescription = "Undo" + ) + } + IconButton(onClick = { }, enabled = false) { + Icon( + imageVector = Icons.AutoMirrored.Filled.Redo, + contentDescription = "Redo" + ) + } + TextButton(onClick = { }, enabled = false) { + Text("PUBLISH") + } + + // Overflow menu button and dropdown in Box for proper anchoring + Box { + IconButton(onClick = { showMenu = true }) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = "More options" + ) + } + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { + DropdownMenuItem( + text = { Text("Save") }, + onClick = { }, + enabled = false + ) + DropdownMenuItem( + text = { Text("Preview") }, + onClick = { }, + enabled = false + ) + DropdownMenuItem( + text = { Text("Code editor") }, + onClick = { }, + enabled = false + ) + DropdownMenuItem( + text = { Text("Post settings") }, + onClick = { }, + enabled = false + ) + DropdownMenuItem( + text = { Text("Help") }, + onClick = { }, + enabled = false + ) + } + } + } + ) + } + ) { innerPadding -> + AndroidView( + factory = { context -> + GutenbergView(context).apply { + start(configuration) + } + }, + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + ) } } \ No newline at end of file diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 3165d57f..2b2978f2 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -16,6 +16,8 @@ robolectric = "4.14.1" kotlinx-coroutines = '1.10.2' androidx-recyclerview = '1.3.2' wordpress-rs = 'trunk-503f1da9e067677d1517d09f926b1d038dfa58a1' +composeBom = "2024.12.01" +activityCompose = "1.9.3" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -34,8 +36,15 @@ robolectric = { group = "org.robolectric", name = "robolectric", version.ref = " kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "androidx-recyclerview" } wordpress-rs-android = { group = "rs.wordpress.api", name = "android", version.ref = "wordpress-rs" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" } +androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +jetbrains-kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } android-library = { id = "com.android.library", version.ref = "agp" }