diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c4c50ed..c87b10d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -86,6 +86,9 @@ dependencies { ksp(libs.androidx.room.compiler) implementation(libs.androidx.room.ktx) + implementation(platform(libs.bom)) + implementation(libs.editor) + testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/java/com/paulcoding/hviewer/network/Github.kt b/app/src/main/java/com/paulcoding/hviewer/network/Github.kt index ae8c626..f3a59ec 100644 --- a/app/src/main/java/com/paulcoding/hviewer/network/Github.kt +++ b/app/src/main/java/com/paulcoding/hviewer/network/Github.kt @@ -67,7 +67,7 @@ object Github { downloadAndGetConfig() } else { log("Already latest version", "check update") - _stateFlow.update { it.copy(siteConfigs = siteConfigs) } + _stateFlow.update { it.copy(siteConfigs = currentConfigs) } } } } catch (e: Exception) { diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/component/H7Tap.kt b/app/src/main/java/com/paulcoding/hviewer/ui/component/H7Tap.kt new file mode 100644 index 0000000..0adb2dd --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/component/H7Tap.kt @@ -0,0 +1,41 @@ +package com.paulcoding.hviewer.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.paulcoding.hviewer.BuildConfig +import com.paulcoding.hviewer.helper.makeToast + +@Composable +fun H7Tap(modifier: Modifier = Modifier, onDevModeChange: (Boolean) -> Unit) { + var tapCount by remember { mutableIntStateOf(0) } + var lastTapTime by remember { mutableLongStateOf(0L) } + Box(modifier = modifier + .padding(16.dp) + .clickable { + val current = System.currentTimeMillis() + if (current - lastTapTime > 2000) { + tapCount = 1 + } else { + tapCount++ + if (tapCount >= 7) { + makeToast("Dev Mode Enabled") + onDevModeChange(true) + tapCount = 0 + } + } + lastTapTime = current + + }) { + Text("Version ${BuildConfig.VERSION_NAME}") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/component/HIcon.kt b/app/src/main/java/com/paulcoding/hviewer/ui/component/HIcon.kt index c8f3902..5255e0f 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/component/HIcon.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/component/HIcon.kt @@ -29,8 +29,8 @@ fun HFavoriteIcon(modifier: Modifier = Modifier, isFavorite: Boolean, onClick: ( @Composable fun HIcon( - modifier: Modifier = Modifier, imageVector: ImageVector = SettingsIcon, + modifier: Modifier = Modifier, description: String = "", tint: Color = LocalContentColor.current, onClick: () -> Unit diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/icon/JS.kt b/app/src/main/java/com/paulcoding/hviewer/ui/icon/JS.kt new file mode 100644 index 0000000..536a308 --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/icon/JS.kt @@ -0,0 +1,82 @@ +package com.paulcoding.hviewer.ui.icon + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.StrokeJoin +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +public val Javascript: ImageVector + get() { + if (_Javascript != null) { + return _Javascript!! + } + _Javascript = ImageVector.Builder( + name = "Javascript", + defaultWidth = 24.dp, + defaultHeight = 24.dp, + viewportWidth = 960f, + viewportHeight = 960f + ).apply { + path( + fill = SolidColor(Color.Black), + fillAlpha = 1.0f, + stroke = null, + strokeAlpha = 1.0f, + strokeLineWidth = 1.0f, + strokeLineCap = StrokeCap.Butt, + strokeLineJoin = StrokeJoin.Miter, + strokeLineMiter = 1.0f, + pathFillType = PathFillType.NonZero + ) { + moveTo(300f, 600f) + quadToRelative(-25f, 0f, -42.5f, -17.5f) + reflectiveQuadTo(240f, 540f) + verticalLineToRelative(-40f) + horizontalLineToRelative(60f) + verticalLineToRelative(40f) + horizontalLineToRelative(60f) + verticalLineToRelative(-180f) + horizontalLineToRelative(60f) + verticalLineToRelative(180f) + quadToRelative(0f, 25f, -17.5f, 42.5f) + reflectiveQuadTo(360f, 600f) + close() + moveToRelative(220f, 0f) + quadToRelative(-17f, 0f, -28.5f, -11.5f) + reflectiveQuadTo(480f, 560f) + verticalLineToRelative(-40f) + horizontalLineToRelative(60f) + verticalLineToRelative(20f) + horizontalLineToRelative(80f) + verticalLineToRelative(-40f) + horizontalLineTo(520f) + quadToRelative(-17f, 0f, -28.5f, -11.5f) + reflectiveQuadTo(480f, 460f) + verticalLineToRelative(-60f) + quadToRelative(0f, -17f, 11.5f, -28.5f) + reflectiveQuadTo(520f, 360f) + horizontalLineToRelative(120f) + quadToRelative(17f, 0f, 28.5f, 11.5f) + reflectiveQuadTo(680f, 400f) + verticalLineToRelative(40f) + horizontalLineToRelative(-60f) + verticalLineToRelative(-20f) + horizontalLineToRelative(-80f) + verticalLineToRelative(40f) + horizontalLineToRelative(100f) + quadToRelative(17f, 0f, 28.5f, 11.5f) + reflectiveQuadTo(680f, 500f) + verticalLineToRelative(60f) + quadToRelative(0f, 17f, -11.5f, 28.5f) + reflectiveQuadTo(640f, 600f) + close() + } + }.build() + return _Javascript!! + } + +private var _Javascript: ImageVector? = null diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/icon/Save.kt b/app/src/main/java/com/paulcoding/hviewer/ui/icon/Save.kt new file mode 100644 index 0000000..06d132a --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/icon/Save.kt @@ -0,0 +1,76 @@ +package com.paulcoding.hviewer.ui.icon + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.StrokeJoin +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +public val Save: ImageVector + get() { + if (_Save != null) { + return _Save!! + } + _Save = ImageVector.Builder( + name = "Save", + defaultWidth = 24.dp, + defaultHeight = 24.dp, + viewportWidth = 960f, + viewportHeight = 960f + ).apply { + path( + fill = SolidColor(Color.Black), + fillAlpha = 1.0f, + stroke = null, + strokeAlpha = 1.0f, + strokeLineWidth = 1.0f, + strokeLineCap = StrokeCap.Butt, + strokeLineJoin = StrokeJoin.Miter, + strokeLineMiter = 1.0f, + pathFillType = PathFillType.NonZero + ) { + moveTo(840f, 280f) + verticalLineToRelative(480f) + quadToRelative(0f, 33f, -23.5f, 56.5f) + reflectiveQuadTo(760f, 840f) + horizontalLineTo(200f) + quadToRelative(-33f, 0f, -56.5f, -23.5f) + reflectiveQuadTo(120f, 760f) + verticalLineToRelative(-560f) + quadToRelative(0f, -33f, 23.5f, -56.5f) + reflectiveQuadTo(200f, 120f) + horizontalLineToRelative(480f) + close() + moveToRelative(-80f, 34f) + lineTo(646f, 200f) + horizontalLineTo(200f) + verticalLineToRelative(560f) + horizontalLineToRelative(560f) + close() + moveTo(480f, 720f) + quadToRelative(50f, 0f, 85f, -35f) + reflectiveQuadToRelative(35f, -85f) + reflectiveQuadToRelative(-35f, -85f) + reflectiveQuadToRelative(-85f, -35f) + reflectiveQuadToRelative(-85f, 35f) + reflectiveQuadToRelative(-35f, 85f) + reflectiveQuadToRelative(35f, 85f) + reflectiveQuadToRelative(85f, 35f) + moveTo(240f, 400f) + horizontalLineToRelative(360f) + verticalLineToRelative(-160f) + horizontalLineTo(240f) + close() + moveToRelative(-40f, -86f) + verticalLineToRelative(446f) + verticalLineToRelative(-560f) + close() + } + }.build() + return _Save!! + } + +private var _Save: ImageVector? = null diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt index eb50989..9d6bde6 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt @@ -21,6 +21,8 @@ import com.paulcoding.hviewer.model.PostItem import com.paulcoding.hviewer.model.SiteConfigs import com.paulcoding.hviewer.network.Github import com.paulcoding.hviewer.ui.favorite.FavoritePage +import com.paulcoding.hviewer.ui.page.editor.EditorPage +import com.paulcoding.hviewer.ui.page.editor.ListScriptPage import com.paulcoding.hviewer.ui.page.post.PostPage import com.paulcoding.hviewer.ui.page.posts.PostsPage import com.paulcoding.hviewer.ui.page.search.SearchPage @@ -34,6 +36,7 @@ fun AppEntry() { val githubState by Github.stateFlow.collectAsState() val siteConfigs = githubState.siteConfigs ?: SiteConfigs() val appViewModel: AppViewModel = viewModel() + val appState by appViewModel.stateFlow.collectAsState() fun navToImages(post: PostItem) { appViewModel.setCurrentPost(post) @@ -42,7 +45,9 @@ fun AppEntry() { NavHost(navController, Route.SITES) { animatedComposable(Route.SITES) { - SitesPage(siteConfigs = siteConfigs, + SitesPage( + isDevMode = appState.isDevMode, + siteConfigs = siteConfigs, refresh = { Github.refreshLocalConfigs() }, navToTopics = { site -> appViewModel.setSiteConfig(site, siteConfigs.sites[site]!!) @@ -53,10 +58,13 @@ fun AppEntry() { navToFavorite = { navController.navigate(Route.FAVORITE) }, + navToListScript = { + navController.navigate(Route.LIST_SCRIPT) + }, goBack = { navController.popBackStack() }) } animatedComposable(Route.SETTINGS) { - SettingsPage(goBack = { navController.popBackStack() }) + SettingsPage(appViewModel = appViewModel, goBack = { navController.popBackStack() }) } animatedComposable(Route.POSTS) { PostsPage( @@ -94,6 +102,21 @@ fun AppEntry() { goBack = { navController.popBackStack() } ) } + animatedComposable(Route.LIST_SCRIPT) { + ListScriptPage( + appViewModel = appViewModel, + goBack = { navController.popBackStack() }, + navToEditor = { + navController.navigate(Route.EDITOR + "/$it") + }) + } + animatedComposable(Route.EDITOR + "/{scriptFile}") { backStackEntry -> + val scriptFile = backStackEntry.arguments?.getString("scriptFile")!! + EditorPage( + appViewModel = appViewModel, + scriptFile = scriptFile, + goBack = { navController.popBackStack() }) + } } } diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt index 030e83e..2610eb6 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt @@ -2,15 +2,22 @@ package com.paulcoding.hviewer.ui.page import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.paulcoding.hviewer.MainApp.Companion.appContext import com.paulcoding.hviewer.database.DatabaseProvider +import com.paulcoding.hviewer.helper.scriptsDir import com.paulcoding.hviewer.model.PostItem import com.paulcoding.hviewer.model.SiteConfig import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import java.io.File class AppViewModel : ViewModel() { + private val scriptsDir = appContext.scriptsDir + val listScriptFiles: List + get() = scriptsDir.listFiles()?.toList() ?: listOf() + private var _stateFlow = MutableStateFlow(UiState()) val stateFlow = _stateFlow.asStateFlow() @@ -27,8 +34,13 @@ class AppViewModel : ViewModel() { data class UiState( val post: PostItem = PostItem(), val site: Pair = "" to SiteConfig(), + val isDevMode: Boolean = false, ) + fun setDevMode(isDevMode: Boolean) { + _stateFlow.update { it.copy(isDevMode = isDevMode) } + } + fun addFavorite(postItem: PostItem, reAdded: Boolean = false) { viewModelScope.launch { val item = if (reAdded) postItem else postItem.copy( diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt index 6862616..ee2a544 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/Route.kt @@ -9,4 +9,6 @@ object Route { const val SEARCH = "search" const val SETTINGS = "settings" const val FAVORITE = "favorite" + const val EDITOR = "editor" + const val LIST_SCRIPT = "list_script" } \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/CodeEditor.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/CodeEditor.kt new file mode 100644 index 0000000..7ee1ab9 --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/CodeEditor.kt @@ -0,0 +1,62 @@ +package com.paulcoding.hviewer.ui.page.editor + +import android.content.Context +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.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView +import io.github.rosemoe.sora.text.Content +import io.github.rosemoe.sora.widget.CodeEditor + +data class CodeEditorState( + var editor: CodeEditor? = null, + val initialContent: Content = Content() +) { + var content by mutableStateOf(initialContent) +} + +private fun setCodeEditorFactory( + context: Context, + state: CodeEditorState +): CodeEditor { + val editor = CodeEditor(context) + editor.apply { + setText(state.content) + } + state.editor = editor + return editor +} + +@Composable +fun CodeEditor( + modifier: Modifier = Modifier, + state: CodeEditorState +) { + val context = LocalContext.current + val editor = remember { + setCodeEditorFactory( + context = context, + state = state + ) + } + AndroidView( + factory = { editor }, + modifier = modifier, + onRelease = { + it.release() + } + ) +} + +@Composable +fun rememberCodeEditorState( + initialContent: Content = Content() +) = remember { + CodeEditorState( + initialContent = initialContent + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/EditorPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/EditorPage.kt new file mode 100644 index 0000000..cf1ad8c --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/EditorPage.kt @@ -0,0 +1,52 @@ +package com.paulcoding.hviewer.ui.page.editor + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.paulcoding.hviewer.helper.makeToast +import com.paulcoding.hviewer.helper.readFile +import com.paulcoding.hviewer.helper.writeFile +import com.paulcoding.hviewer.network.Github +import com.paulcoding.hviewer.ui.component.HBackIcon +import com.paulcoding.hviewer.ui.component.HIcon +import com.paulcoding.hviewer.ui.icon.Save +import com.paulcoding.hviewer.ui.page.AppViewModel +import io.github.rosemoe.sora.text.Content + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EditorPage(appViewModel: AppViewModel, goBack: () -> Boolean, scriptFile: String) { + val context = LocalContext.current + val script = context.readFile(scriptFile) + val state = rememberCodeEditorState(initialContent = Content(script)) + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar(title = { Text(text = "Editor") }, navigationIcon = { + HBackIcon { + goBack() + } + }, actions = { + HIcon(imageVector = Save) { + context.writeFile(state.content.toString(), scriptFile) + Github.refreshLocalConfigs() + makeToast("Saved!") + } + }) + }, + ) { paddings -> + CodeEditor( + modifier = Modifier + .padding(paddings) + .fillMaxSize(), + state = state + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/ListScriptPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/ListScriptPage.kt new file mode 100644 index 0000000..ff90099 --- /dev/null +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/editor/ListScriptPage.kt @@ -0,0 +1,68 @@ +package com.paulcoding.hviewer.ui.page.editor + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.paulcoding.hviewer.ui.component.HBackIcon +import com.paulcoding.hviewer.ui.icon.Javascript +import com.paulcoding.hviewer.ui.page.AppViewModel + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ListScriptPage( + appViewModel: AppViewModel, + goBack: () -> Unit, + navToEditor: (String) -> Unit +) { + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar(title = { Text(text = "List Script") }, + navigationIcon = { + HBackIcon { + goBack() + } + }) + }) { paddings -> + + LazyColumn( + modifier = Modifier + .padding(paddings) + .fillMaxSize() + ) { + items(appViewModel.listScriptFiles, key = { it.name }) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp) + .clickable { + navToEditor(it.name) + }, + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + Javascript, + contentDescription = "Javascript", + modifier = Modifier.size(32.dp), + ) + Text(text = it.name) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/settings/SettingsPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/settings/SettingsPage.kt index 2490ca2..8f70841 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/settings/SettingsPage.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/settings/SettingsPage.kt @@ -47,12 +47,14 @@ import com.paulcoding.hviewer.MainActivity import com.paulcoding.hviewer.extensions.setSecureScreen import com.paulcoding.hviewer.network.Github import com.paulcoding.hviewer.preference.Preferences +import com.paulcoding.hviewer.ui.component.H7Tap import com.paulcoding.hviewer.ui.component.HBackIcon import com.paulcoding.hviewer.ui.icon.EditIcon +import com.paulcoding.hviewer.ui.page.AppViewModel @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SettingsPage(goBack: () -> Boolean) { +fun SettingsPage(appViewModel: AppViewModel, goBack: () -> Boolean) { val githubState by Github.stateFlow.collectAsState() val prevSiteConfigs = remember { githubState.siteConfigs } var modalVisible by remember { mutableStateOf(false) } @@ -73,6 +75,7 @@ fun SettingsPage(goBack: () -> Boolean) { Box(modifier = Modifier.padding(paddings)) { Column( modifier = Modifier + .fillMaxSize() .padding(horizontal = 16.dp) .verticalScroll( rememberScrollState() @@ -104,6 +107,14 @@ fun SettingsPage(goBack: () -> Boolean) { window.setSecureScreen(it) }) } + Box(modifier = Modifier + .weight(1f) + .fillMaxSize() + ) { + H7Tap(modifier = Modifier.align(Alignment.BottomCenter)) { + appViewModel.setDevMode(it) + } + } } } diff --git a/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt b/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt index c195b8f..994414d 100644 --- a/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt +++ b/app/src/main/java/com/paulcoding/hviewer/ui/page/sites/SitesPage.kt @@ -31,6 +31,8 @@ import com.paulcoding.hviewer.model.SiteConfig import com.paulcoding.hviewer.model.SiteConfigs import com.paulcoding.hviewer.ui.component.HEmpty import com.paulcoding.hviewer.ui.component.HFavoriteIcon +import com.paulcoding.hviewer.ui.component.HIcon +import com.paulcoding.hviewer.ui.icon.EditIcon import com.paulcoding.hviewer.ui.icon.SettingsIcon import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -38,10 +40,12 @@ import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable fun SitesPage( + isDevMode: Boolean, navToTopics: (site: String) -> Unit, goBack: () -> Unit, siteConfigs: SiteConfigs, navToSettings: () -> Unit, + navToListScript: () -> Unit, refresh: () -> Unit, navToFavorite: () -> Unit, ) { @@ -55,6 +59,10 @@ fun SitesPage( Scaffold(topBar = { TopAppBar(title = { Text("Sites") }, actions = { + if (isDevMode) + HIcon(EditIcon) { + navToListScript() + } HFavoriteIcon(isFavorite = false) { navToFavorite() } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2bf1b1e..f56fb78 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,7 @@ [versions] accompanistPermissions = "0.36.0" agp = "8.7.2" +bom = "0.23.4" coilNetworkOkhttp = "3.0.0" commonsCompress = "1.27.1" concurrentFuturesKtx = "1.2.0" @@ -39,11 +40,13 @@ androidx-navigation-compose = { module = "androidx.navigation:navigation-compose androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" } androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" } androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" } +bom = { module = "io.github.Rosemoe.sora-editor:bom", version.ref = "bom" } coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coilNetworkOkhttp" } coil-gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coilNetworkOkhttp" } coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coilNetworkOkhttp" } coil-video = { module = "io.coil-kt.coil3:coil-video", version.ref = "coilNetworkOkhttp" } commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commonsCompress" } +editor = { module = "io.github.Rosemoe.sora-editor:editor" } gson = { module = "com.google.code.gson:gson", version.ref = "gson" } jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } junit = { group = "junit", name = "junit", version.ref = "junit" }