Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
83f27a5
feat: 查看项目
xiaowuzt Jun 19, 2026
9d43c38
feat: 查看项目
xiaowuzt Jun 19, 2026
ded4009
feat: 查看项目
xiaowuzt Jun 19, 2026
c76b497
feat: 查看项目
xiaowuzt Jun 19, 2026
64a78fa
feat: 查看项目
xiaowuzt Jun 19, 2026
a9ed761
feat: 查看项目
xiaowuzt Jun 19, 2026
a817308
feat: 查看项目
xiaowuzt Jun 19, 2026
96f262f
feat: 查看项目
xiaowuzt Jun 19, 2026
ece9814
feat: 查看项目
xiaowuzt Jun 19, 2026
3f5dde4
feat: 查看项目
xiaowuzt Jun 19, 2026
ab03780
feat(glass): add shared glass theme constants
xiaowuzt Jun 19, 2026
5107f44
feat(glass): add reusable GlassCard component
xiaowuzt Jun 19, 2026
75100e2
feat(glass): add reusable GlassButton variants
xiaowuzt Jun 19, 2026
1f92ee5
feat(glass): add page-level shared glass components
xiaowuzt Jun 19, 2026
e39b4d3
feat(glass): propagate theme preset state through nav host
xiaowuzt Jun 19, 2026
c5bffb9
feat(glass): rewrite HomePage with announcement and quick launch
xiaowuzt Jun 19, 2026
da3f832
feat(glass): rewrite VersionsPage with profile, search and filters
xiaowuzt Jun 19, 2026
5b15380
feat(glass): rewrite SettingsPage with theme preview and preset selector
xiaowuzt Jun 19, 2026
9808aeb
chore(manifest): set GlassMainActivity as launcher entry
xiaowuzt Jun 19, 2026
fd28b32
fix(glass): clean unused imports and fix VersionsPage listener leak
xiaowuzt Jun 19, 2026
854b4ca
feat: 查看项目
xiaowuzt Jun 19, 2026
ce39eb6
feat(glass-download): add download routes and glass input/checkbox co…
xiaowuzt Jun 19, 2026
a0a6239
feat(glass-download): rewrite DownloadPage as category home
xiaowuzt Jun 19, 2026
7f0dc6f
feat(glass-download): add version install list page
xiaowuzt Jun 19, 2026
4aa0b57
feat(glass-download): add installer version selection page
xiaowuzt Jun 19, 2026
599faf6
feat: 查看项目
xiaowuzt Jun 19, 2026
092949d
feat(glass-download): add version install info page
xiaowuzt Jun 19, 2026
5938149
feat(glass-download): wire nested download navigation
xiaowuzt Jun 19, 2026
cfa6f06
feat(glass-download): share selected loader versions across install flow
xiaowuzt Jun 19, 2026
56cb409
feat: 查看项目
xiaowuzt Jun 19, 2026
34e8eab
feat(glass-mod): add remote content routes and type definitions
xiaowuzt Jun 19, 2026
9302789
feat(glass-mod): add shared mod download components
xiaowuzt Jun 19, 2026
6ed135a
feat(glass-mod): add generic remote mod list page and cache
xiaowuzt Jun 19, 2026
0762952
feat(glass-mod): add generic remote mod info page
xiaowuzt Jun 19, 2026
1db7a64
feat(glass-mod): add generic remote mod version page
xiaowuzt Jun 19, 2026
75b7a42
feat(glass-mod): wire mod download routes from home and nav host
xiaowuzt Jun 19, 2026
917b9ac
feat: 查看项目
xiaowuzt Jun 19, 2026
bef8020
fix(glass-mod): pass FCLUILayout parent to modpack install
xiaowuzt Jun 19, 2026
776eae1
feat(glass): embed Compose content in FCLUILayout for legacy page com…
xiaowuzt Jun 19, 2026
dda14fe
feat(glass-mod): add error toasts for mod download flow
xiaowuzt Jun 19, 2026
f9342ec
feat(glass-mod): show TaskDialog during mod download
xiaowuzt Jun 19, 2026
f2cfe2c
feat(glass-mod): show dependency list before download
xiaowuzt Jun 19, 2026
704e446
chore(glass): clean unused imports
xiaowuzt Jun 19, 2026
d1ef78a
fix(glass-mod): run installation on UI thread, use TaskDialog only fo…
xiaowuzt Jun 19, 2026
33f4427
feat: 查看项目
xiaowuzt Jun 19, 2026
56664bd
feat(glass-account): add account state holder and list item
xiaowuzt Jun 19, 2026
97e4860
feat(glass-account): add account page
xiaowuzt Jun 19, 2026
62ab2b0
feat(glass-nav): replace Manage tab with Account
xiaowuzt Jun 19, 2026
6cf1cdd
feat(glass-versions): add version actions menu
xiaowuzt Jun 19, 2026
ae3e6cc
feat: 查看项目
xiaowuzt Jun 19, 2026
ce33c9f
feat: 查看项目
xiaowuzt Jun 19, 2026
18abe8c
feat: 查看项目
xiaowuzt Jun 19, 2026
309cee9
feat: 查看项目
xiaowuzt Jun 19, 2026
8804f74
feat: 查看项目
xiaowuzt Jun 19, 2026
37f3248
chore: ignore .worktrees directory
xiaowuzt Jun 19, 2026
fbef0d6
feat: 查看项目
xiaowuzt Jun 19, 2026
4306dc7
feat: 查看项目
xiaowuzt Jun 19, 2026
f5664da
feat: 查看项目
xiaowuzt Jun 20, 2026
87e752a
feat(glass): add settings and java routes
xiaowuzt Jun 20, 2026
ae47331
feat: 查看项目
xiaowuzt Jun 20, 2026
740a5fd
feat(glass): add phase 2 version management routes
xiaowuzt Jun 20, 2026
5089191
feat(glass): add VersionSettingsPage
xiaowuzt Jun 20, 2026
0d2a879
feat(glass): add VersionInstallPage
xiaowuzt Jun 20, 2026
34ee73d
Phase 2 Task 4: implement glass Mod list and Mod info pages
xiaowuzt Jun 20, 2026
8d8eed1
Phase 2 Task 5: implement glass World list page with export dialog
xiaowuzt Jun 20, 2026
e46e10b
feat: 查看项目
xiaowuzt Jun 20, 2026
59764b6
feat: 查看项目
xiaowuzt Jun 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ FCL/src/main/java/com/mio/Main.kt
.DS_Store
/LWJGL-Pojav/bin
LWJGL-Pojav/compileOnly/jspecify-1.0.0.jar

# Isolated worktrees
.worktrees/
14 changes: 13 additions & 1 deletion FCL/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import java.util.Properties
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose") version "2.3.20"
id("org.jetbrains.kotlin.plugin.serialization") version "2.3.20"
}

Expand Down Expand Up @@ -43,7 +44,8 @@ android {

defaultConfig {
applicationId = "com.tungsten.fcl"
minSdk = libs.versions.minSdk.get().toInt()
// 液态玻璃 UI 依赖 Backdrop 效果,需要 Android 12+ (API 31)
minSdk = 31
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1313
versionName = "1.3.1.3"
Expand Down Expand Up @@ -84,8 +86,10 @@ android {
viewBinding = true
buildConfig = true
resValues = true
compose = true
}


splits {
val arch = System.getProperty("arch", "all")
if (arch != "all") {
Expand Down Expand Up @@ -166,6 +170,14 @@ dependencies {
implementation(libs.segmented.button)
implementation(libs.datastore)
implementation(libs.kotlinx.serialization.json)
implementation(platform(libs.compose.bom))
implementation(libs.compose.ui)
implementation(libs.compose.material3)
implementation(libs.compose.activity)
implementation(libs.compose.navigation)
implementation(libs.compose.ui.tooling)
implementation(libs.compose.ui.tooling.preview)
implementation(libs.backdrop)
}

tasks.register("updateMap") {
Expand Down
13 changes: 10 additions & 3 deletions FCL/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
tools:ignore="DiscouragedApi"
tools:targetApi="33">
<activity
android:name=".activity.SplashActivity"
android:name=".activity.GlassMainActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation"
android:exported="true"
android:screenOrientation="sensorLandscape"
android:theme="@style/Theme.Splash">
android:theme="@style/Theme.FoldCraftLauncher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down Expand Up @@ -91,9 +91,16 @@
<data android:pathPattern=".*\\.7z" />
</intent-filter>
</activity-alias>
<activity
android:name=".activity.SplashActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:theme="@style/Theme.Splash" />
<activity
android:name=".activity.MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation"
android:exported="false"
android:screenOrientation="sensorLandscape" />
<activity
android:name=".activity.WebActivity"
Expand Down Expand Up @@ -172,4 +179,4 @@
<action android:name="android.intent.action.MAIN" />
</intent>
</queries>
</manifest>
</manifest>
41 changes: 41 additions & 0 deletions FCL/src/main/java/com/tungsten/fcl/activity/GlassMainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.tungsten.fcl.activity

import android.os.Bundle
import androidx.compose.ui.platform.ComposeView
import androidx.core.view.WindowCompat
import com.tungsten.fcl.ui.glass.FCLGlassApp
import com.tungsten.fcllibrary.component.FCLActivity
import com.tungsten.fcllibrary.component.view.FCLUILayout

/**
* FCL 液态玻璃 UI 主入口。
*
* 作为 SplashActivity 之后的主 Activity,负责展示 Compose + Backdrop 构建的液态玻璃界面。
* 以 FCLUILayout 为根容器,方便旧版页面在 Compose UI 上层添加视图。
*/
class GlassMainActivity : FCLActivity() {

lateinit var layout: FCLUILayout
private set

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

WindowCompat.setDecorFitsSystemWindows(window, false)

layout = FCLUILayout(this)
val composeView = ComposeView(this).apply {
setContent {
FCLGlassApp()
}
}
layout.addView(
composeView,
android.widget.RelativeLayout.LayoutParams(
android.widget.RelativeLayout.LayoutParams.MATCH_PARENT,
android.widget.RelativeLayout.LayoutParams.MATCH_PARENT
)
)
setContentView(layout)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class SplashActivity : FCLActivity() {
}
}
startActivity(
handleModpack(Intent(this@SplashActivity, MainActivity::class.java)),
handleModpack(Intent(this@SplashActivity, GlassMainActivity::class.java)),
ActivityOptionsCompat.makeCustomAnimation(this@SplashActivity, 0, 0).toBundle()
)
finish()
Expand Down
5 changes: 5 additions & 0 deletions FCL/src/main/java/com/tungsten/fcl/setting/Profiles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ object Profiles {
versionsListeners.add(listener)
}

@JvmStatic
fun unregisterVersionsListener(listener: Consumer<Profile>) {
versionsListeners.remove(listener)
}

fun getSelectedGameVersion(): String {
val gameVersion: Optional<String> =
getSelectedProfile().repository.getGameVersion(getSelectedVersion())
Expand Down
105 changes: 105 additions & 0 deletions FCL/src/main/java/com/tungsten/fcl/ui/glass/FCLGlassApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.tungsten.fcl.ui.glass

import android.content.Context
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.hasRoute
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
import com.tungsten.fcl.activity.GlassMainActivity
import com.tungsten.fcl.ui.glass.component.GlassBottomBar
import com.tungsten.fcl.ui.glass.component.GlassNavHost
import com.tungsten.fcl.ui.glass.component.dialog.GlassDialogHost
import com.tungsten.fcl.ui.glass.theme.GlassTheme
import com.tungsten.fcllibrary.component.theme.ThemePreset

@Composable
fun FCLGlassApp(
initialPreset: ThemePreset = ThemePreset.DEFAULT
) {
val context = LocalContext.current
val sharedPreferences = remember { context.getSharedPreferences("launcher", Context.MODE_PRIVATE) }
val presetOrdinal = remember { sharedPreferences.getInt("themePreset", initialPreset.ordinal) }
var currentPreset by remember { mutableStateOf(ThemePreset.values()[presetOrdinal]) }

val isDark = isSystemInDarkTheme()
val backgroundColor = GlassTheme.backgroundColor()

val onPresetChange: (ThemePreset) -> Unit = { preset ->
currentPreset = preset
sharedPreferences.edit().putInt("themePreset", preset.ordinal).apply()
}

val layout = remember(context) {
(context as? GlassMainActivity)?.layout
}

CompositionLocalProvider(LocalFCLUILayout provides layout) {
MaterialTheme(
colorScheme = if (isDark) darkColorScheme() else lightColorScheme()
) {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val currentRoute = when {
currentDestination?.hasRoute<FCLGlassRoute.Home>() == true -> FCLGlassRoute.Home
currentDestination?.hasRoute<FCLGlassRoute.Versions>() == true -> FCLGlassRoute.Versions
currentDestination?.hasRoute<FCLGlassRoute.Download>() == true -> FCLGlassRoute.Download
currentDestination?.hasRoute<FCLGlassRoute.Account>() == true -> FCLGlassRoute.Account
currentDestination?.hasRoute<FCLGlassRoute.Settings>() == true -> FCLGlassRoute.Settings
else -> FCLGlassRoute.Home
}

val backdrop = rememberLayerBackdrop {
drawRect(backgroundColor)
drawContent()
}

Box(modifier = Modifier.fillMaxSize()) {
GlassNavHost(
navController = navController,
backdrop = backdrop,
currentPreset = currentPreset,
onPresetChange = onPresetChange,
modifier = Modifier
.fillMaxSize()
.padding(bottom = 80.dp)
)

GlassBottomBar(
backdrop = backdrop,
preset = currentPreset,
currentRoute = currentRoute,
onRouteSelected = { route ->
navController.navigate(route) {
popUpTo(navController.graph.startDestinationId) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
modifier = Modifier.align(Alignment.BottomCenter)
)

GlassDialogHost(backdrop = backdrop)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.tungsten.fcl.ui.glass

import kotlinx.serialization.Serializable

sealed class FCLGlassDownloadRoute {
@Serializable
data object Home : FCLGlassDownloadRoute()

@Serializable
data object VersionInstallList : FCLGlassDownloadRoute()

@Serializable
data class VersionInstallInfo(val gameVersion: String) : FCLGlassDownloadRoute()

@Serializable
data class InstallerVersionSelect(
val gameVersion: String,
val libraryId: String
) : FCLGlassDownloadRoute()

@Serializable
data class ModDownload(val gameVersion: String = "") : FCLGlassDownloadRoute()

@Serializable
data class ModpackDownload(val gameVersion: String = "") : FCLGlassDownloadRoute()

@Serializable
data class ResourcePackDownload(val gameVersion: String = "") : FCLGlassDownloadRoute()

@Serializable
data class ShaderPackDownload(val gameVersion: String = "") : FCLGlassDownloadRoute()

@Serializable
data class RemoteModInfo(
val typeName: String,
val modSlug: String,
val modTitle: String,
val gameVersion: String,
val cacheKey: String
) : FCLGlassDownloadRoute()

@Serializable
data class RemoteModVersions(
val typeName: String,
val modSlug: String,
val targetGameVersion: String,
val cacheKey: String
) : FCLGlassDownloadRoute()
}
79 changes: 79 additions & 0 deletions FCL/src/main/java/com/tungsten/fcl/ui/glass/FCLGlassRoute.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.tungsten.fcl.ui.glass

import kotlinx.serialization.Serializable

sealed class FCLGlassRoute {
@Serializable
data object Home : FCLGlassRoute()

@Serializable
data object Versions : FCLGlassRoute()

@Serializable
data object Download : FCLGlassRoute()

@Serializable
data object Account : FCLGlassRoute()

@Serializable
data object Settings : FCLGlassRoute()

@Serializable
data object LauncherSettings : FCLGlassRoute()

@Serializable
data object JavaRuntime : FCLGlassRoute()

@Serializable
data object JvmArgs : FCLGlassRoute()

@Serializable
data class QuickInput(
val title: String,
val initialValue: String,
val hint: String
) : FCLGlassRoute()

@Serializable
data class VersionSettings(
val profileName: String,
val version: String
) : FCLGlassRoute()

@Serializable
data class VersionInstall(
val profileName: String,
val version: String? = null
) : FCLGlassRoute()

@Serializable
data class VersionMods(
val profileName: String,
val version: String
) : FCLGlassRoute()

@Serializable
data class VersionWorlds(
val profileName: String,
val version: String
) : FCLGlassRoute()

@Serializable
data class VersionResourcePacks(
val profileName: String,
val version: String
) : FCLGlassRoute()

@Serializable
data class VersionShaderPacks(
val profileName: String,
val version: String
) : FCLGlassRoute()

@Serializable
data class ModInfo(
val modFileName: String,
val profileName: String,
val version: String
) : FCLGlassRoute()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.tungsten.fcl.ui.glass

import androidx.compose.runtime.staticCompositionLocalOf
import com.tungsten.fcllibrary.component.view.FCLUILayout

val LocalFCLUILayout = staticCompositionLocalOf<FCLUILayout?> { null }
Loading