diff --git a/FCL/build.gradle b/FCL/build.gradle index f522b534..b3fb48ef 100644 --- a/FCL/build.gradle +++ b/FCL/build.gradle @@ -44,8 +44,8 @@ android { applicationId "com.tungsten.fcl" minSdk 26 targetSdk 34 - versionCode 1177 - versionName "1.1.7.7" + versionCode 1178 + versionName "1.1.7.8" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/FCL/src/main/java/com/mio/util/AnimUtil.kt b/FCL/src/main/java/com/mio/util/AnimUtil.kt index 776467d9..e2f67183 100644 --- a/FCL/src/main/java/com/mio/util/AnimUtil.kt +++ b/FCL/src/main/java/com/mio/util/AnimUtil.kt @@ -95,5 +95,11 @@ class AnimUtil { this.interpolator = interpolator return this } + + @JvmStatic + fun ObjectAnimator.startAfter(delayTime: Long) { + this.startDelay = delayTime + this.start() + } } } \ No newline at end of file diff --git a/FCL/src/main/java/com/mio/util/PerfUtil.kt b/FCL/src/main/java/com/mio/util/PerfUtil.kt new file mode 100644 index 00000000..f52b3db9 --- /dev/null +++ b/FCL/src/main/java/com/mio/util/PerfUtil.kt @@ -0,0 +1,61 @@ +package com.mio.util + +import android.os.Handler +import android.os.HandlerThread +import android.os.Looper +import android.util.Log +import android.util.Printer + +class PerfUtil : Printer { + companion object { + @JvmStatic + fun install() { + Looper.getMainLooper().setMessageLogging(PerfUtil()) + } + } + + private val sampler = StackSampler(300) + private var isStarted = false + private var startTime = 0L + + override fun println(x: String?) { + if (!isStarted) { + isStarted = true + startTime = System.currentTimeMillis() + sampler.startDump() + } else { + isStarted = false + val endTime = System.currentTimeMillis() + if (endTime - startTime > 300) { + Log.e("FCL PerfUtil", "block time = ${endTime - startTime}") + } + sampler.stopDump() + } + } + + inner class StackSampler(val interval: Long) { + private val handler: Handler + private val runnable = Runnable { + val sb = StringBuilder() + Looper.getMainLooper().thread.stackTrace.forEach { + sb.append(it.toString()) + sb.append("\n") + } + Log.e("FCL PerfUtil", sb.toString()) + } + + init { + val handlerThread = HandlerThread("") + handlerThread.start() + handler = Handler(handlerThread.looper) + } + + fun startDump() { + handler.postDelayed(runnable, interval) + } + + fun stopDump() { + handler.removeCallbacks(runnable) + } + } +} \ No newline at end of file diff --git a/FCL/src/main/java/com/tungsten/fcl/FCLApplication.java b/FCL/src/main/java/com/tungsten/fcl/FCLApplication.java index 46cf9758..77c14253 100644 --- a/FCL/src/main/java/com/tungsten/fcl/FCLApplication.java +++ b/FCL/src/main/java/com/tungsten/fcl/FCLApplication.java @@ -8,6 +8,8 @@ import android.os.StrictMode; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.mio.util.PerfUtil; + import java.lang.ref.WeakReference; public class FCLApplication extends Application implements Application.ActivityLifecycleCallbacks { @@ -18,6 +20,7 @@ public class FCLApplication extends Application implements Application.ActivityL // enabledStrictMode(); super.onCreate(); this.registerActivityLifecycleCallbacks(this); + PerfUtil.install(); } public static Activity getCurrentActivity() { @@ -28,9 +31,9 @@ public class FCLApplication extends Application implements Application.ActivityL StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectNetwork() .detectCustomSlowCalls() .detectDiskReads() - .detectDiskWrites() + .detectDiskWrites() .detectAll() - .penaltyLog() + .penaltyLog() .build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects() @@ -73,7 +76,7 @@ public class FCLApplication extends Application implements Application.ActivityL @Override public void onActivityDestroyed(@NonNull Activity activity) { - if (currentActivity.get() == activity) { + if (currentActivity != null && currentActivity.get() == activity) { currentActivity = null; } } diff --git a/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt b/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt index 6a5e5fed..63babfd4 100644 --- a/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt +++ b/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt @@ -9,10 +9,13 @@ import android.os.Bundle import android.view.KeyEvent import android.view.View import android.view.ViewGroup +import android.view.animation.BounceInterpolator import android.widget.RelativeLayout import androidx.appcompat.app.AlertDialog import androidx.core.view.forEach import androidx.databinding.DataBindingUtil +import com.mio.util.AnimUtil +import com.mio.util.AnimUtil.Companion.interpolator import com.tungsten.fcl.R import com.tungsten.fcl.databinding.ActivityMainBinding import com.tungsten.fcl.game.JarExecutorHelper @@ -225,6 +228,7 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener { setupVersionDisplay() UpdateChecker.getInstance().checkAuto(this@MainActivity).start() } + playAnim() } } } @@ -256,7 +260,7 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener { } manage -> { - val version = Profiles.getSelectedVersion() + val version = Profiles.getSelectedProfile().selectedVersion if (version == null) { refreshMenuView(null) title.setTextWithAnim(getString(R.string.version)) @@ -381,6 +385,7 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener { @SuppressLint("UseCompatLoadingForDrawables") private fun loadVersion(version: String?) { + bind.versionProgress.visibility = View.VISIBLE if (Profiles.getSelectedProfile() != profile) { profile = Profiles.getSelectedProfile() if (profile != null) { @@ -394,42 +399,45 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener { version ) ) { - val game = Profiles.getSelectedProfile().repository.getGameVersion(version) - .orElse(getString(R.string.message_unknown)) - val libraries = StringBuilder(game) - val analyzer = LibraryAnalyzer.analyze( - Profiles.getSelectedProfile().repository.getResolvedPreservingPatchesVersion(version) - ) - for (mark in analyzer) { - val libraryId = mark.libraryId - val libraryVersion = mark.libraryVersion - if (libraryId == LibraryType.MINECRAFT.patchId) continue - if (AndroidUtils.hasStringId( - this, - "install_installer_" + libraryId.replace("-", "_") - ) - ) { - libraries.append(", ").append( - AndroidUtils.getLocalizedText( + Schedulers.defaultScheduler().execute { + val game = Profiles.getSelectedProfile().repository.getGameVersion(version) + .orElse(getString(R.string.message_unknown)) + val libraries = StringBuilder(game) + val analyzer = LibraryAnalyzer.analyze( + Profiles.getSelectedProfile().repository.getResolvedPreservingPatchesVersion(version) + ) + for (mark in analyzer) { + val libraryId = mark.libraryId + val libraryVersion = mark.libraryVersion + if (libraryId == LibraryType.MINECRAFT.patchId) continue + if (AndroidUtils.hasStringId( this, "install_installer_" + libraryId.replace("-", "_") ) - ) - if (libraryVersion != null) libraries.append(": ").append( - libraryVersion.replace( - "(?i)$libraryId".toRegex(), "" + ) { + libraries.append(", ").append( + AndroidUtils.getLocalizedText( + this, + "install_installer_" + libraryId.replace("-", "_") + ) ) - ) + if (libraryVersion != null) libraries.append(": ").append( + libraryVersion.replace( + "(?i)$libraryId".toRegex(), "" + ) + ) + } + } + val drawable = Profiles.getSelectedProfile().repository.getVersionIconImage(version) + Schedulers.androidUIThread().execute { + bind.versionProgress.visibility = View.GONE + bind.versionName.text = version + bind.versionHint.text = libraries.toString() + bind.icon.setBackgroundDrawable(drawable) } } - bind.versionName.text = version - bind.versionHint.text = libraries.toString() - bind.icon.setBackgroundDrawable( - Profiles.getSelectedProfile().repository.getVersionIconImage( - version - ) - ) } else { + bind.versionProgress.visibility = View.GONE bind.versionName.text = getString(R.string.version_no_version) bind.versionHint.text = getString(R.string.version_manage) bind.icon.setBackgroundDrawable(getDrawable(R.drawable.img_grass)) @@ -454,4 +462,21 @@ class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener { }) } } + + private fun playAnim() { + bind.apply { + AnimUtil.playTranslationX( + leftMenu, + ThemeEngine.getInstance().getTheme().animationSpeed * 100L, + -100f, + 0f + ).interpolator(BounceInterpolator()).start() + AnimUtil.playTranslationX( + rightMenu, + ThemeEngine.getInstance().getTheme().animationSpeed * 100L, + 100f, + 0f + ).interpolator(BounceInterpolator()).start() + } + } } \ No newline at end of file diff --git a/FCL/src/main/java/com/tungsten/fcl/activity/SplashActivity.java b/FCL/src/main/java/com/tungsten/fcl/activity/SplashActivity.java index 1769d524..f060be31 100644 --- a/FCL/src/main/java/com/tungsten/fcl/activity/SplashActivity.java +++ b/FCL/src/main/java/com/tungsten/fcl/activity/SplashActivity.java @@ -41,9 +41,6 @@ public class SplashActivity extends FCLActivity { public ConstraintLayout background; - private EulaFragment eulaFragment; - private RuntimeFragment runtimeFragment; - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -103,21 +100,15 @@ public class SplashActivity extends FCLActivity { FCLPath.loadPaths(this); transFile(); Logging.start(Paths.get(FCLPath.LOG_DIR)); - initFragments(); start(); } - private void initFragments() { - eulaFragment = new EulaFragment(); - runtimeFragment = new RuntimeFragment(); - } - public void start() { SharedPreferences sharedPreferences = getSharedPreferences("launcher", MODE_PRIVATE); if (sharedPreferences.getBoolean("isFirstLaunch", true)) { - getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, eulaFragment).commit(); + getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, EulaFragment.class, null).commit(); } else { - getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, runtimeFragment).commit(); + getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.frag_start_anim, R.anim.frag_stop_anim).replace(R.id.fragment, RuntimeFragment.class, null).commit(); } } diff --git a/FCL/src/main/java/com/tungsten/fcl/fragment/RuntimeFragment.kt b/FCL/src/main/java/com/tungsten/fcl/fragment/RuntimeFragment.kt index 672931b8..f64f4a5c 100644 --- a/FCL/src/main/java/com/tungsten/fcl/fragment/RuntimeFragment.kt +++ b/FCL/src/main/java/com/tungsten/fcl/fragment/RuntimeFragment.kt @@ -1,6 +1,5 @@ package com.tungsten.fcl.fragment -import android.annotation.SuppressLint import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater @@ -12,11 +11,9 @@ import com.tungsten.fcl.activity.SplashActivity import com.tungsten.fcl.databinding.FragmentRuntimeBinding import com.tungsten.fcl.util.RuntimeUtils import com.tungsten.fclauncher.utils.FCLPath +import com.tungsten.fclcore.task.Schedulers import com.tungsten.fclcore.util.io.FileUtils import com.tungsten.fcllibrary.component.FCLFragment -import com.tungsten.fcllibrary.component.view.FCLButton -import com.tungsten.fcllibrary.component.view.FCLImageView -import com.tungsten.fcllibrary.component.view.FCLProgressBar import com.tungsten.fcllibrary.util.LocaleUtils import java.io.File import java.io.IOException @@ -41,10 +38,12 @@ class RuntimeFragment : FCLFragment(), View.OnClickListener { ): View? { val view = inflater.inflate(R.layout.fragment_runtime, container, false) bind = FragmentRuntimeBinding.bind(view) - initState() - refreshDrawables() - check() bind.install.setOnClickListener(this) + Schedulers.defaultScheduler().execute { + initState() + refreshDrawables() + check() + } return view } diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Accounts.java b/FCL/src/main/java/com/tungsten/fcl/setting/Accounts.java index 7c43b176..92f74e26 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/Accounts.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Accounts.java @@ -243,7 +243,7 @@ public final class Accounts { */ static void init() { if (initialized) - throw new IllegalStateException("Already initialized"); + return; loadGlobalAccountStorages(); diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/ConfigHolder.java b/FCL/src/main/java/com/tungsten/fcl/setting/ConfigHolder.java index 18c91c78..7512f124 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/ConfigHolder.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/ConfigHolder.java @@ -62,7 +62,7 @@ public final class ConfigHolder { public synchronized static void init() throws IOException { if (configInstance != null) { - throw new IllegalStateException("Configuration is already loaded"); + return; } configInstance = loadConfig(); diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java b/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java index ca958b3e..221826b8 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java @@ -10,6 +10,7 @@ import com.tungsten.fclcore.fakefx.beans.Observable; import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyListProperty; import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyListWrapper; import com.tungsten.fclcore.fakefx.collections.ObservableList; +import com.tungsten.fclcore.task.Schedulers; import com.tungsten.fclcore.util.Logging; import com.tungsten.fclcore.util.gson.fakefx.factories.JavaFxPropertyTypeAdapterFactory; import com.tungsten.fclcore.util.io.FileUtils; @@ -27,10 +28,12 @@ public class Controllers { private Controllers() { } - private static final ObservableList controllers = observableArrayList(controller -> new Observable[] { controller }); + private static final ObservableList controllers = observableArrayList(controller -> new Observable[]{controller}); private static final ReadOnlyListWrapper controllersWrapper = new ReadOnlyListWrapper<>(controllers); public static Controller DEFAULT_CONTROLLER; + private static final List CALLBACKS = new ArrayList<>(); + public static void checkControllers() { if (controllers.contains(null)) { controllers.remove(null); @@ -92,12 +95,16 @@ public class Controllers { public static void init() { if (initialized) - throw new IllegalStateException("Already initialized"); + return; controllers.addAll(getControllersFromDisk()); checkControllers(); initialized = true; + CALLBACKS.forEach(callback -> { + Schedulers.androidUIThread().execute(callback); + }); + CALLBACKS.clear(); } private static ArrayList getControllersFromDisk() { @@ -150,4 +157,12 @@ public class Controllers { return controllers.stream().filter(it -> it.getName().equals(name)).findFirst().orElse(controllers.get(0)); } + public static void addCallback(Runnable callback) { + if (initialized) { + callback.run(); + return; + } + CALLBACKS.add(callback); + } + } diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Profiles.java b/FCL/src/main/java/com/tungsten/fcl/setting/Profiles.java index 7dee9a2e..b85b2f1e 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/Profiles.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Profiles.java @@ -135,7 +135,7 @@ public final class Profiles { static void init() { if (initialized) - throw new IllegalStateException("Already initialized"); + return; HashSet names = new HashSet<>(); config().getConfigurations().forEach((name, profile) -> { diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java b/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java index c65f60f3..3f24944e 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java @@ -19,6 +19,7 @@ package com.tungsten.fcl.setting; import com.tungsten.fcl.game.FCLCacheRepository; import com.tungsten.fclauncher.utils.FCLPath; +import com.tungsten.fclcore.task.Schedulers; import com.tungsten.fclcore.util.CacheRepository; public final class Settings { @@ -43,7 +44,7 @@ public final class Settings { DownloadProviders.init(); Accounts.init(); Profiles.init(); - Controllers.init(); + Schedulers.defaultScheduler().execute(Controllers::init); AuthlibInjectorServers.init(); CacheRepository.setInstance(FCLCacheRepository.REPOSITORY); diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java b/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java index 77f442bf..68614800 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java @@ -359,14 +359,15 @@ public final class VersionSetting implements Cloneable { } public void checkController() { - Controllers.checkControllers(); + Controllers.addCallback(() -> { + Controllers.checkControllers(); + Controller controller = Controllers.getControllers().stream() + .filter(it -> it.getName().equals(getController())) + .findFirst() + .orElse(Controllers.getControllers().get(0)); - Controller controller = Controllers.getControllers().stream() - .filter(it -> it.getName().equals(getController())) - .findFirst() - .orElse(Controllers.getControllers().get(0)); - - setController(controller.getName()); + setController(controller.getName()); + }); } public void addPropertyChangedListener(InvalidationListener listener) { diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/PageManager.java b/FCL/src/main/java/com/tungsten/fcl/ui/PageManager.java index fa33943a..1f08c9d5 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/PageManager.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/PageManager.java @@ -18,7 +18,7 @@ public abstract class PageManager { private final FCLUILayout parent; private final int defaultPageId; - private final ArrayList allPages; + public final ArrayList allPages; private FCLCommonPage currentPage; public PageManager (Context context, FCLUILayout parent, int defaultPageId, UIListener listener) { @@ -53,6 +53,10 @@ public abstract class PageManager { public abstract ArrayList getAllPages(); + public FCLCommonPage createPageById(int id){ + return null; + } + public FCLCommonPage getPageById(int id) { for (FCLCommonPage page : allPages) { if (page.getId() == id) { @@ -66,7 +70,10 @@ public abstract class PageManager { if (allPages.size() > 0) { FCLCommonPage targetPage = getPageById(id); if (targetPage == null) { - throw new IllegalStateException("Wrong page id, this should not happen!"); + targetPage = createPageById(id); + if (targetPage == null){ + throw new IllegalStateException("Wrong page id, this should not happen!"); + } } if (currentPage != null && currentPage != targetPage) { if (currentPage.isShowing()) { diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/UIManager.java b/FCL/src/main/java/com/tungsten/fcl/ui/UIManager.java deleted file mode 100644 index f4947eb9..00000000 --- a/FCL/src/main/java/com/tungsten/fcl/ui/UIManager.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.tungsten.fcl.ui; - -import android.content.Context; - -import com.tungsten.fcl.R; -import com.tungsten.fcl.ui.account.AccountUI; -import com.tungsten.fcl.ui.controller.ControllerUI; -import com.tungsten.fcl.ui.download.DownloadUI; -import com.tungsten.fcl.ui.manage.ManageUI; -import com.tungsten.fcl.ui.main.MainUI; -import com.tungsten.fcl.ui.multiplayer.MultiplayerUI; -import com.tungsten.fcl.ui.setting.SettingUI; -import com.tungsten.fcl.ui.version.VersionUI; -import com.tungsten.fclcore.util.Logging; -import com.tungsten.fcllibrary.component.ui.FCLBaseUI; -import com.tungsten.fcllibrary.component.ui.FCLCommonUI; -import com.tungsten.fcllibrary.component.view.FCLUILayout; - -import java.util.logging.Level; - -public class UIManager { - - private static UIManager instance; - - public static UIManager getInstance() { - if (instance == null) { - throw new IllegalStateException("UIManager not initialized!"); - } - return instance; - } - - private final Context context; - private final FCLUILayout parent; - - private MainUI mainUI; - private AccountUI accountUI; - private VersionUI versionUI; - private ManageUI manageUI; - private DownloadUI downloadUI; - private ControllerUI controllerUI; - private MultiplayerUI multiplayerUI; - private SettingUI settingUI; - - private FCLBaseUI[] allUIs; - private FCLBaseUI currentUI; - - private int loadedUI = 0; - - public UIManager(Context context, FCLUILayout parent) { - this.context = context; - this.parent = parent; - } - - public void init(UIListener listener) { - if (instance != null) { - Logging.LOG.log(Level.WARNING, "UIManager already initialized!"); - return; - } - instance = this; - - mainUI = new MainUI(context, parent, R.layout.ui_main); - accountUI = new AccountUI(context, parent, R.layout.ui_account); - versionUI = new VersionUI(context, parent, R.layout.ui_version); - manageUI = new ManageUI(context, parent, R.layout.ui_manage); - downloadUI = new DownloadUI(context, parent, R.layout.ui_download); - controllerUI = new ControllerUI(context, parent, R.layout.ui_controller); - multiplayerUI = new MultiplayerUI(context, parent, R.layout.ui_multiplayer); - settingUI = new SettingUI(context, parent, R.layout.ui_setting); - - allUIs = new FCLBaseUI[] { - mainUI, - accountUI, - versionUI, - manageUI, - downloadUI, - controllerUI, - multiplayerUI, - settingUI - }; - - for (FCLBaseUI ui : allUIs) { - ((FCLCommonUI) ui).addLoadingCallback(() -> { - loadedUI++; - if (loadedUI == allUIs.length) { - listener.onLoad(); - } - }); - } - } - - public Context getContext() { - return context; - } - - public FCLUILayout getParent() { - return parent; - } - - public MainUI getMainUI() { - return mainUI; - } - - public AccountUI getAccountUI() { - return accountUI; - } - - public VersionUI getVersionUI() { - return versionUI; - } - - public ManageUI getManageUI() { - return manageUI; - } - - public DownloadUI getDownloadUI() { - return downloadUI; - } - - public ControllerUI getControllerUI() { - return controllerUI; - } - - public MultiplayerUI getMultiplayerUI() { - return multiplayerUI; - } - - public SettingUI getSettingUI() { - return settingUI; - } - - public FCLBaseUI getCurrentUI() { - return currentUI; - } - - public void switchUI(FCLBaseUI ui) { - for (FCLBaseUI baseUI : allUIs) { - if (ui == baseUI) { - if (currentUI != null) { - currentUI.onStop(); - } - ui.onStart(); - currentUI = ui; - break; - } - } - } - - public void registerDefaultBackEvent(Runnable runnable) { - FCLBaseUI.setDefaultBackEvent(runnable); - } - - public void onBackPressed() { - if (currentUI != null) { - currentUI.onBackPressed(); - } - } - - public void onPause() { - for (FCLBaseUI baseUI : allUIs) { - baseUI.onPause(); - } - } - - public void onResume() { - for (FCLBaseUI baseUI : allUIs) { - baseUI.onResume(); - } - } -} diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/UIManager.kt b/FCL/src/main/java/com/tungsten/fcl/ui/UIManager.kt new file mode 100644 index 00000000..2c554918 --- /dev/null +++ b/FCL/src/main/java/com/tungsten/fcl/ui/UIManager.kt @@ -0,0 +1,98 @@ +package com.tungsten.fcl.ui + +import android.content.Context +import com.tungsten.fcl.R +import com.tungsten.fcl.ui.account.AccountUI +import com.tungsten.fcl.ui.controller.ControllerUI +import com.tungsten.fcl.ui.download.DownloadUI +import com.tungsten.fcl.ui.main.MainUI +import com.tungsten.fcl.ui.manage.ManageUI +import com.tungsten.fcl.ui.multiplayer.MultiplayerUI +import com.tungsten.fcl.ui.setting.SettingUI +import com.tungsten.fcl.ui.version.VersionUI +import com.tungsten.fclcore.util.Logging +import com.tungsten.fcllibrary.component.ui.FCLBaseUI +import com.tungsten.fcllibrary.component.ui.FCLCommonUI +import com.tungsten.fcllibrary.component.view.FCLUILayout +import java.util.logging.Level + +class UIManager(val context: Context, val parent: FCLUILayout) { + companion object { + @JvmStatic + lateinit var instance: UIManager + } + + private var initialized = false + lateinit var mainUI: MainUI + val accountUI: AccountUI by lazy { AccountUI(context, parent, R.layout.ui_account) } + val versionUI: VersionUI by lazy { VersionUI(context, parent, R.layout.ui_version) } + val manageUI: ManageUI by lazy { ManageUI(context, parent, R.layout.ui_manage) } + val downloadUI: DownloadUI by lazy { DownloadUI(context, parent, R.layout.ui_download) } + val controllerUI: ControllerUI by lazy { ControllerUI(context, parent, R.layout.ui_controller) } + val multiplayerUI: MultiplayerUI by lazy { + MultiplayerUI( + context, + parent, + R.layout.ui_multiplayer + ) + } + val settingUI: SettingUI by lazy { SettingUI(context, parent, R.layout.ui_setting) } + + private val allUIList = mutableListOf() + var currentUI: FCLBaseUI? = null + + fun init(listener: UIListener) { + if (initialized) { + Logging.LOG.log(Level.WARNING, "UIManager already initialized!") + return + } + instance = this + mainUI = MainUI(context, parent, R.layout.ui_main) + allUIList.add(mainUI) + mainUI.addLoadingCallback { + listener.onLoad() + } + } + + fun switchUI(ui: FCLCommonUI) { + var isFirstAdd = false + if (!allUIList.contains(ui)) { + isFirstAdd = true + allUIList.add(ui) + } + for (baseUI in allUIList) { + if (ui === baseUI) { + currentUI?.onStop() + if (isFirstAdd) { + ui.addLoadingCallback { + ui.onStart() + } + } else { + ui.onStart() + } + currentUI = ui + break + } + } + } + + fun registerDefaultBackEvent(runnable: Runnable?) { + FCLBaseUI.setDefaultBackEvent(runnable) + } + + fun onBackPressed() { + currentUI?.onBackPressed() + } + + fun onPause() { + for (baseUI in allUIList) { + baseUI.onPause() + } + } + + fun onResume() { + for (baseUI in allUIList) { + baseUI.onResume() + } + } +} \ No newline at end of file diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java b/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java index 39330003..fd33cb30 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java @@ -42,33 +42,14 @@ import com.tungsten.fcllibrary.component.view.FCLUILayout; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.function.Consumer; import java.util.logging.Level; public class ControllerUI extends FCLCommonUI implements View.OnClickListener { private final BooleanProperty refreshProperty = new SimpleBooleanProperty(false); - private final ObjectProperty selectedController = new SimpleObjectProperty() { - { - Controllers.getControllers().addListener(onInvalidating(this::invalidated)); - } - - @Override - protected void invalidated() { - if (!Controllers.isInitialized()) return; - - Controller controller = get(); - if (Controllers.getControllers().isEmpty()) { - if (controller != null) { - set(null); - } - } else { - if (!Controllers.getControllers().contains(controller)) { - set(Controllers.getControllers().get(0)); - } - } - } - }; + private ObjectProperty selectedController; public Controller getSelectedController() { return selectedController.get(); @@ -94,8 +75,32 @@ public class ControllerUI extends FCLCommonUI implements View.OnClickListener { @Override public void onCreate() { super.onCreate(); + Controllers.addCallback(this::init); + } - if (Controllers.controllersProperty().size() != 0) { + private void init() { + selectedController = new SimpleObjectProperty() { + { + Controllers.getControllers().addListener(onInvalidating(this::invalidated)); + } + + @Override + protected void invalidated() { + if (!Controllers.isInitialized()) return; + + Controller controller = get(); + if (Controllers.getControllers().isEmpty()) { + if (controller != null) { + set(null); + } + } else { + if (!Controllers.getControllers().contains(controller)) { + set(Controllers.getControllers().get(0)); + } + } + } + }; + if (!Controllers.controllersProperty().isEmpty()) { selectedController.set(Controllers.controllersProperty().get(0)); } else { selectedController.set(Controllers.DEFAULT_CONTROLLER); diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManagePageManager.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManagePageManager.java deleted file mode 100644 index b7b009b8..00000000 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManagePageManager.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.tungsten.fcl.ui.manage; - -import android.content.Context; - -import com.tungsten.fcl.R; -import com.tungsten.fcl.setting.Profile; -import com.tungsten.fcl.ui.PageManager; -import com.tungsten.fcl.ui.UIListener; -import com.tungsten.fcl.ui.download.DownloadPage; -import com.tungsten.fcl.ui.download.InstallVersionPage; -import com.tungsten.fcllibrary.component.ui.FCLCommonPage; -import com.tungsten.fcllibrary.component.view.FCLUILayout; - -import java.util.ArrayList; - -public class ManagePageManager extends PageManager { - - public static final int PAGE_ID_MANAGE_MANAGE = 15000; - public static final int PAGE_ID_MANAGE_SETTING = 15001; - public static final int PAGE_ID_MANAGE_INSTALL = 15002; - public static final int PAGE_ID_MANAGE_MOD = 15003; - public static final int PAGE_ID_MANAGE_WORLD = 15004; - - private static ManagePageManager instance; - - private ManagePage managePage; - private VersionSettingPage versionSettingPage; - private InstallerListPage installerListPage; - private ModListPage modListPage; - private WorldListPage worldListPage; - - public static ManagePageManager getInstance() { - if (instance == null) { - throw new IllegalStateException("ManagePageManager not initialized!"); - } - return instance; - } - - public ManagePageManager(Context context, FCLUILayout parent, int defaultPageId, UIListener listener) { - super(context, parent, defaultPageId, listener); - instance = this; - } - - @Override - public void init(UIListener listener) { - managePage = new ManagePage(getContext(), PAGE_ID_MANAGE_MANAGE, getParent(), R.layout.page_manage); - versionSettingPage = new VersionSettingPage(getContext(), PAGE_ID_MANAGE_SETTING, getParent(), R.layout.page_version_setting, false); - installerListPage = new InstallerListPage(getContext(), PAGE_ID_MANAGE_INSTALL, getParent(), R.layout.page_installer_list); - modListPage = new ModListPage(getContext(), PAGE_ID_MANAGE_MOD, getParent(), R.layout.page_mod_list); - worldListPage = new WorldListPage(getContext(), PAGE_ID_MANAGE_WORLD, getParent(), R.layout.page_world_list); - - if (listener != null) { - listener.onLoad(); - } - } - - @Override - public ArrayList getAllPages() { - ArrayList pages = new ArrayList<>(); - pages.add(managePage); - pages.add(versionSettingPage); - pages.add(installerListPage); - pages.add(modListPage); - pages.add(worldListPage); - return pages; - } - - public void loadVersion(Profile profile, String version) { - managePage.loadVersion(profile, version); - versionSettingPage.loadVersion(profile, version); - installerListPage.loadVersion(profile, version); - modListPage.loadVersion(profile, version); - worldListPage.loadVersion(profile, version); - } - - public void onRunDirectoryChange(Profile profile, String version) { - modListPage.loadVersion(profile, version); - worldListPage.loadVersion(profile, version); - } -} diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManagePageManager.kt b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManagePageManager.kt new file mode 100644 index 00000000..10611fc0 --- /dev/null +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManagePageManager.kt @@ -0,0 +1,109 @@ +package com.tungsten.fcl.ui.manage + +import android.content.Context +import com.tungsten.fcl.R +import com.tungsten.fcl.setting.Profile +import com.tungsten.fcl.ui.PageManager +import com.tungsten.fcl.ui.UIListener +import com.tungsten.fcl.ui.manage.ManageUI.VersionLoadable +import com.tungsten.fcllibrary.component.ui.FCLCommonPage +import com.tungsten.fcllibrary.component.view.FCLUILayout + +class ManagePageManager( + context: Context, + parent: FCLUILayout, + defaultPageId: Int, + val listener: UIListener? +) : PageManager(context, parent, defaultPageId, listener) { + companion object { + @JvmStatic + var instance: ManagePageManager? = null + const val PAGE_ID_MANAGE_MANAGE: Int = 15000 + const val PAGE_ID_MANAGE_SETTING: Int = 15001 + const val PAGE_ID_MANAGE_INSTALL: Int = 15002 + const val PAGE_ID_MANAGE_MOD: Int = 15003 + const val PAGE_ID_MANAGE_WORLD: Int = 15004 + } + + var profile: Profile? = null + var version: String? = null + + lateinit var managePage: ManagePage + val versionSettingPage: VersionSettingPage by lazy { + VersionSettingPage( + context, + PAGE_ID_MANAGE_SETTING, + parent, + R.layout.page_version_setting, + false + ) + } + val installerListPage: InstallerListPage by lazy { + InstallerListPage( + context, + PAGE_ID_MANAGE_INSTALL, + parent, + R.layout.page_installer_list + ) + } + val modListPage: ModListPage by lazy { + ModListPage( + context, + PAGE_ID_MANAGE_MOD, + parent, + R.layout.page_mod_list + ) + } + val worldListPage: WorldListPage by lazy { + WorldListPage( + context, + PAGE_ID_MANAGE_WORLD, + parent, + R.layout.page_world_list + ) + } + + init { + instance = this + } + + override fun init(listener: UIListener?) { + managePage = + ManagePage(context, PAGE_ID_MANAGE_MANAGE, parent, R.layout.page_manage) + listener?.onLoad() + } + + override fun getAllPages(): ArrayList { + return ArrayList().apply { + add(managePage) + } + } + + override fun createPageById(id: Int): FCLCommonPage? { + val page: FCLCommonPage? = when (id) { + PAGE_ID_MANAGE_SETTING -> versionSettingPage + PAGE_ID_MANAGE_INSTALL -> installerListPage + PAGE_ID_MANAGE_MOD -> modListPage + PAGE_ID_MANAGE_WORLD -> worldListPage + else -> null + } + if (page != null) { + allPages.add(page) + (page as VersionLoadable).loadVersion(profile, version) + } + return page + } + + fun loadVersion(profile: Profile?, version: String?) { + this.profile = profile + this.version = version + allPages.forEach { + (it as VersionLoadable).loadVersion(profile, version) + } + } + + fun onRunDirectoryChange(profile: Profile?, version: String?) { + modListPage.loadVersion(profile, version) + worldListPage.loadVersion(profile, version) + } +} \ No newline at end of file diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManageUI.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManageUI.java index 94f7b20f..729ecbaf 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManageUI.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ManageUI.java @@ -47,28 +47,28 @@ public class ManageUI extends FCLMultiPageUI implements TabLayout.OnTabSelectedL container = findViewById(R.id.container); tabLayout.addOnTabSelectedListener(this); - container.post(this::initPages); - + initPages(); listenerHolder.add(EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerWeak(event -> checkSelectedVersion(), EventPriority.HIGHEST)); } @Override public void onStart() { super.onStart(); - // If we jumped to game list page and deleted this version - // and back to this page, we should return to main page. - if (!getProfile().getRepository().isLoaded() || - !getProfile().getRepository().hasVersion(getVersion())) { - Schedulers.androidUIThread().execute(() -> { - if (isShowing()) { - MainActivity.getInstance().refreshMenuView(null); - MainActivity.getInstance().bind.home.setSelected(true); - } - }); - return; - } - - loadVersion(getVersion(), getProfile()); + addLoadingCallback(()->{ + // If we jumped to game list page and deleted this version + // and back to this page, we should return to main page. + if (!getProfile().getRepository().isLoaded() || + !getProfile().getRepository().hasVersion(getVersion())) { + Schedulers.androidUIThread().execute(() -> { + if (isShowing()) { + MainActivity.getInstance().refreshMenuView(null); + MainActivity.getInstance().bind.home.setSelected(true); + } + }); + return; + } + loadVersion(getVersion(), getProfile()); + }); } @Override diff --git a/FCL/src/main/res/drawable/ic_launcher_background.xml b/FCL/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 424ccb10..00000000 --- a/FCL/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/FCL/src/main/res/layout/activity_main.xml b/FCL/src/main/res/layout/activity_main.xml index 565e270c..d2656979 100644 --- a/FCL/src/main/res/layout/activity_main.xml +++ b/FCL/src/main/res/layout/activity_main.xml @@ -261,6 +261,16 @@ + + = 5 && Integer.parseInt(version[1]) >= 13) { newLibraries.add(library); diff --git a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/ui/FCLCommonUI.java b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/ui/FCLCommonUI.java index 40b5a5c6..d1ddb026 100644 --- a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/ui/FCLCommonUI.java +++ b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/ui/FCLCommonUI.java @@ -17,11 +17,14 @@ public abstract class FCLCommonUI extends FCLBaseUI { private UILoadingCallback callback; + private boolean init = false; + public FCLCommonUI(Context context, FCLUILayout parent, @LayoutRes int id) { super(context); this.parent = parent; setContentView(id, () -> { onCreate(); + init = true; if (callback != null) { callback.onLoad(); } @@ -78,5 +81,8 @@ public abstract class FCLCommonUI extends FCLBaseUI { public void addLoadingCallback(UILoadingCallback callback) { this.callback = callback; + if (init) { + callback.onLoad(); + } } } diff --git a/version_map.json b/version_map.json index 8c17a334..b7361fcd 100644 --- a/version_map.json +++ b/version_map.json @@ -1,20 +1,20 @@ [ { "type": "release", - "versionCode": 1177, - "versionName": "1.1.7.7", - "date": "2024.08.27", + "versionCode": 1178, + "versionName": "1.1.7.8", + "date": "2024.09.04", "description": [ { "lang": "en", - "text": "1.Fix oshi core.\n2.Fix windows scale.\n3.Add custom cursor.\n4.Fix some bug.\nSee github for more details." + "text": "1. Fix bug that triggers error return when deleting text\n2. Fix bug that Microsoft login cannot be used when the language is not Chinese or English\n3. Update HolyGL4ES\n4. Add the function of adjusting cursor offset in the game" }, { "lang": "zh_CN", - "text": "FCL 1.1.7.7更新内容(若启动器内下载缓慢请使用网盘下载,64位的请下载arm64,不知道该下哪个的请下载all)\n1.修复oshi core\n2.修复窗口缩放\n3.添加自定义光标\n4.添加更多动画效果" + "text": "FCL 1.1.7.8更新内容(若启动器内下载缓慢请使用网盘下载,64位的请下载arm64,不知道该下哪个的请下载all)\n1.修复删除文本时错误触发返回的bug\n2.修复语言为非中文或英文时无法使用微软登录的bug\n3.更新HolyGL4ES\n4.增加游戏内光标偏移调节的功能" } ], - "netdiskUrl": "https://pan.quark.cn/s/5fac965e464b", - "url": "https://github.com/FCL-Team/FoldCraftLauncher/releases/download/1.1.7.7/FCL-release-1.1.7.7-all.apk" + "netdiskUrl": "https://pan.quark.cn/s/5fa82d8bb512", + "url": "https://github.com/FCL-Team/FoldCraftLauncher/releases/download/1.1.7.8/FCL-release-1.1.7.8-all.apk" } ]