diff --git a/FCL/build.gradle b/FCL/build.gradle index ad9c3abb..9bee9651 100644 --- a/FCL/build.gradle +++ b/FCL/build.gradle @@ -1,5 +1,6 @@ plugins { id 'com.android.application' + id 'org.jetbrains.kotlin.android' version '1.9.20' id "org.hidetake.ssh" version "2.11.2" } @@ -102,6 +103,15 @@ android { } pickFirst '**/libbytehook.so' } + kotlinOptions { + jvmTarget = "1.8" + } + dataBinding { + enabled true + } + buildFeatures { + buildConfig true + } splits { def arch = System.getProperty("arch", "all") if (arch != 'all') { diff --git a/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.java b/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.java deleted file mode 100644 index 1e5a5ac0..00000000 --- a/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.java +++ /dev/null @@ -1,421 +0,0 @@ -package com.tungsten.fcl.activity; - -import static com.tungsten.fcl.setting.Accounts.getAccountFactory; -import static com.tungsten.fclcore.download.LibraryAnalyzer.LibraryType.MINECRAFT; -import static com.tungsten.fclcore.fakefx.beans.binding.Bindings.createStringBinding; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.Intent; -import android.graphics.drawable.BitmapDrawable; -import android.os.Bundle; -import android.view.View; -import android.view.ViewGroup; -import android.widget.RelativeLayout; -import android.widget.ScrollView; - -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.LinearLayoutCompat; -import androidx.constraintlayout.widget.ConstraintLayout; - -import com.tungsten.fcl.R; -import com.tungsten.fcl.game.JarExecutorHelper; -import com.tungsten.fcl.game.TexturesLoader; -import com.tungsten.fcl.setting.Accounts; -import com.tungsten.fcl.setting.ConfigHolder; -import com.tungsten.fcl.setting.Profile; -import com.tungsten.fcl.setting.Profiles; -import com.tungsten.fcl.ui.UIManager; -import com.tungsten.fcl.ui.version.Versions; -import com.tungsten.fcl.upgrade.UpdateChecker; -import com.tungsten.fcl.util.AndroidUtils; -import com.tungsten.fcl.util.FXUtils; -import com.tungsten.fcl.util.WeakListenerHolder; -import com.tungsten.fclcore.auth.Account; -import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorAccount; -import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorServer; -import com.tungsten.fclcore.auth.offline.Skin; -import com.tungsten.fclcore.auth.yggdrasil.TextureModel; -import com.tungsten.fclcore.download.LibraryAnalyzer; -import com.tungsten.fclcore.event.Event; -import com.tungsten.fclcore.fakefx.beans.property.ObjectProperty; -import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty; -import com.tungsten.fclcore.fakefx.beans.value.ObservableValue; -import com.tungsten.fclcore.mod.RemoteMod; -import com.tungsten.fclcore.mod.RemoteModRepository; -import com.tungsten.fclcore.task.Schedulers; -import com.tungsten.fclcore.util.Logging; -import com.tungsten.fclcore.util.fakefx.BindingMapping; -import com.tungsten.fcllibrary.component.FCLActivity; -import com.tungsten.fcllibrary.component.theme.ThemeEngine; -import com.tungsten.fcllibrary.component.view.FCLButton; -import com.tungsten.fcllibrary.component.view.FCLDynamicIsland; -import com.tungsten.fcllibrary.component.view.FCLEditText; -import com.tungsten.fcllibrary.component.view.FCLImageView; -import com.tungsten.fcllibrary.component.view.FCLMenuView; -import com.tungsten.fcllibrary.component.view.FCLTextView; -import com.tungsten.fcllibrary.component.view.FCLUILayout; -import com.tungsten.fcllibrary.util.ConvertUtils; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.logging.Level; -import java.util.stream.Stream; - -public class MainActivity extends FCLActivity implements FCLMenuView.OnSelectListener, View.OnClickListener { - - private static MainActivity instance; - - public ConstraintLayout background; - public FCLDynamicIsland titleView; - - private UIManager uiManager; - public FCLUILayout uiLayout; - - private ScrollView leftMenu; - public FCLMenuView home; - public FCLMenuView manage; - public FCLMenuView download; - public FCLMenuView controller; - public FCLMenuView multiplayer; - public FCLMenuView setting; - public FCLMenuView back; - - private LinearLayoutCompat account; - private FCLImageView avatar; - private FCLTextView accountName; - private FCLTextView accountHint; - private LinearLayoutCompat version; - private FCLImageView icon; - private FCLTextView versionName; - private FCLTextView versionHint; - private FCLButton executeJar; - private FCLButton launch; - - private ObjectProperty currentAccount; - private final WeakListenerHolder holder = new WeakListenerHolder(); - private Profile profile; - private Consumer onVersionIconChangedListener; - - public static MainActivity getInstance() { - return instance; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - instance = this; - - background = findViewById(R.id.background); - background.setBackground(ThemeEngine.getInstance().getTheme().getBackground(this)); - - titleView = findViewById(R.id.title); - - Skin.registerDefaultSkinLoader((type) -> { - switch (type) { - case ALEX: - return Skin.class.getResourceAsStream("/assets/img/alex.png"); - case ARI: - return Skin.class.getResourceAsStream("/assets/img/ari.png"); - case EFE: - return Skin.class.getResourceAsStream("/assets/img/efe.png"); - case KAI: - return Skin.class.getResourceAsStream("/assets/img/kai.png"); - case MAKENA: - return Skin.class.getResourceAsStream("/assets/img/makena.png"); - case NOOR: - return Skin.class.getResourceAsStream("/assets/img/noor.png"); - case STEVE: - return Skin.class.getResourceAsStream("/assets/img/steve.png"); - case SUNNY: - return Skin.class.getResourceAsStream("/assets/img/sunny.png"); - case ZURI: - return Skin.class.getResourceAsStream("/assets/img/zuri.png"); - default: - return null; - } - }); - - RemoteMod.registerEmptyRemoteMod(new RemoteMod("", "", getString(R.string.mods_broken_dependency_title), getString(R.string.mods_broken_dependency_desc), new ArrayList<>(), "", "", new RemoteMod.IMod() { - @Override - public List loadDependencies(RemoteModRepository modRepository) throws IOException { - throw new IOException(); - } - - @Override - public Stream loadVersions(RemoteModRepository modRepository) throws IOException { - throw new IOException(); - } - })); - - try { - ConfigHolder.init(); - } catch (IOException e) { - Logging.LOG.log(Level.WARNING, e.getMessage()); - } - - uiLayout = findViewById(R.id.ui_layout); - uiLayout.post(() -> { - leftMenu = findViewById(R.id.left_scroll); - ThemeEngine.getInstance().registerEvent(leftMenu, () -> leftMenu.setBackgroundColor(ThemeEngine.getInstance().getTheme().getColor())); - - account = findViewById(R.id.account); - avatar = findViewById(R.id.avatar); - accountName = findViewById(R.id.account_name); - accountHint = findViewById(R.id.account_hint); - version = findViewById(R.id.version); - icon = findViewById(R.id.icon); - versionName = findViewById(R.id.version_name); - versionHint = findViewById(R.id.version_hint); - executeJar = findViewById(R.id.execute_jar); - launch = findViewById(R.id.launch); - account.setOnClickListener(this); - version.setOnClickListener(this); - executeJar.setOnClickListener(this); - executeJar.setOnLongClickListener(V -> { - int padding = ConvertUtils.dip2px(MainActivity.this, 15); - FCLEditText editText = new FCLEditText(MainActivity.this); - RelativeLayout layout = new RelativeLayout(MainActivity.this); - editText.setHint("-jar xxx"); - editText.setLines(1); - editText.setMaxLines(1); - layout.setPadding(padding, padding, padding, padding); - layout.addView(editText); - AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) - .setTitle(R.string.jar_execute_custom_args) - .setView(layout) - .setPositiveButton(com.tungsten.fcllibrary.R.string.dialog_positive, (dialog1, which) -> JarExecutorHelper.exec(MainActivity.this, null, 8, editText.getText().toString())) - .setNegativeButton(com.tungsten.fcllibrary.R.string.dialog_negative, null) - .create(); - layout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - editText.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - ThemeEngine.getInstance().applyFullscreen(dialog.getWindow(), ThemeEngine.getInstance().getTheme().isFullscreen()); - dialog.show(); - return true; - }); - launch.setOnClickListener(this); - launch.setOnLongClickListener(view -> { - startActivity(new Intent(MainActivity.this, ShellActivity.class)); - return true; - }); - - uiManager = new UIManager(this, uiLayout); - uiManager.registerDefaultBackEvent(backToMainUI); - uiManager.init(() -> { - home = findViewById(R.id.home); - manage = findViewById(R.id.manage); - download = findViewById(R.id.download); - controller = findViewById(R.id.controller); - multiplayer = findViewById(R.id.multiplayer); - setting = findViewById(R.id.setting); - back = findViewById(R.id.back); - home.setOnSelectListener(this); - manage.setOnSelectListener(this); - download.setOnSelectListener(this); - controller.setOnSelectListener(this); - multiplayer.setOnSelectListener(this); - setting.setOnSelectListener(this); - back.setOnClickListener(this); - home.setSelected(true); - - setupAccountDisplay(); - setupVersionDisplay(); - - UpdateChecker.getInstance().checkAuto(this).start(); - }); - }); - } - - public Runnable backToMainUI = () -> { - if (uiManager.getCurrentUI() == uiManager.getMainUI()) { - Intent i = new Intent(Intent.ACTION_MAIN); - i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - i.addCategory(Intent.CATEGORY_HOME); - startActivity(i); - } else { - home.setSelected(true); - } - }; - - @Override - public void onBackPressed() { - if (uiManager != null) { - uiManager.onBackPressed(); - } - } - - @Override - protected void onPause() { - super.onPause(); - if (uiManager != null) { - uiManager.onPause(); - } - } - - @Override - protected void onResume() { - super.onResume(); - if (uiManager != null) { - uiManager.onResume(); - } - } - - @Override - public void onSelect(FCLMenuView view) { - refreshMenuView(view); - if (view == home) { - titleView.setTextWithAnim(getString(R.string.app_name)); - uiManager.switchUI(uiManager.getMainUI()); - } - if (view == manage) { - String version = Profiles.getSelectedVersion(); - if (version == null) { - refreshMenuView(null); - titleView.setTextWithAnim(getString(R.string.version)); - uiManager.switchUI(uiManager.getVersionUI()); - } else { - titleView.setTextWithAnim(getString(R.string.manage)); - uiManager.getManageUI().setVersion(version, Profiles.getSelectedProfile()); - uiManager.switchUI(uiManager.getManageUI()); - } - } - if (view == download) { - titleView.setTextWithAnim(getString(R.string.download)); - uiManager.switchUI(uiManager.getDownloadUI()); - } - if (view == controller) { - titleView.setTextWithAnim(getString(R.string.controller)); - uiManager.switchUI(uiManager.getControllerUI()); - } - if (view == multiplayer) { - titleView.setTextWithAnim(getString(R.string.multiplayer)); - uiManager.switchUI(uiManager.getMultiplayerUI()); - } - if (view == setting) { - titleView.setTextWithAnim(getString(R.string.setting)); - uiManager.switchUI(uiManager.getSettingUI()); - } - } - - public void refreshMenuView(FCLMenuView view) { - FCLMenuView[] views = { - home, - manage, - download, - controller, - multiplayer, - setting - }; - for (FCLMenuView v : views) { - if (v != view) { - v.setSelected(false); - } - } - } - - @Override - public void onClick(View view) { - if (view == account && uiManager.getCurrentUI() != uiManager.getAccountUI()) { - refreshMenuView(null); - titleView.setTextWithAnim(getString(R.string.account)); - uiManager.switchUI(uiManager.getAccountUI()); - } - if (view == version && uiManager.getCurrentUI() != uiManager.getVersionUI()) { - refreshMenuView(null); - titleView.setTextWithAnim(getString(R.string.version)); - uiManager.switchUI(uiManager.getVersionUI()); - } - if (view == back) { - if (uiManager != null) { - uiManager.onBackPressed(); - } - } - if (view == executeJar) { - JarExecutorHelper.start(this, this); - } - if (view == launch) { - Versions.launch(this, Profiles.getSelectedProfile()); - } - } - - private static ObservableValue accountSubtitle(Context context, Account account) { - if (account instanceof AuthlibInjectorAccount) { - return BindingMapping.of(((AuthlibInjectorAccount) account).getServer(), AuthlibInjectorServer::getName); - } else { - return createStringBinding(() -> Accounts.getLocalizedLoginTypeName(context, getAccountFactory(account))); - } - } - - private void setupAccountDisplay() { - currentAccount = new SimpleObjectProperty() { - - @Override - protected void invalidated() { - Account account = get(); - if (account == null) { - accountName.stringProperty().unbind(); - accountHint.stringProperty().unbind(); - avatar.imageProperty().unbind(); - accountName.setText(getString(R.string.account_state_no_account)); - accountHint.setText(getString(R.string.account_state_add)); - avatar.setBackgroundDrawable(new BitmapDrawable(TexturesLoader.toAvatar(TexturesLoader.getDefaultSkin(TextureModel.ALEX).getImage(), ConvertUtils.dip2px(MainActivity.this, 30)))); - } else { - accountName.stringProperty().bind(BindingMapping.of(account, Account::getCharacter)); - accountHint.stringProperty().bind(accountSubtitle(MainActivity.this, account)); - avatar.imageProperty().unbind(); - avatar.imageProperty().bind(TexturesLoader.avatarBinding(account, ConvertUtils.dip2px(MainActivity.this, 30))); - } - } - }; - currentAccount.bind(Accounts.selectedAccountProperty()); - } - - public void refreshAvatar(Account account) { - Schedulers.androidUIThread().execute(() -> { - if (currentAccount.get() == account) { - avatar.imageProperty().unbind(); - avatar.imageProperty().bind(TexturesLoader.avatarBinding(currentAccount.get(), ConvertUtils.dip2px(MainActivity.this, 30))); - } - }); - } - - @SuppressLint("UseCompatLoadingForDrawables") - private void loadVersion(String version) { - if (Profiles.getSelectedProfile() != profile) { - profile = Profiles.getSelectedProfile(); - if (profile != null) { - onVersionIconChangedListener = profile.getRepository().onVersionIconChanged.registerWeak(event -> this.loadVersion(Profiles.getSelectedVersion())); - } - } - if (version != null && Profiles.getSelectedProfile() != null && Profiles.getSelectedProfile().getRepository().hasVersion(version)) { - String game = Profiles.getSelectedProfile().getRepository().getGameVersion(version).orElse(getString(R.string.message_unknown)); - StringBuilder libraries = new StringBuilder(game); - LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(Profiles.getSelectedProfile().getRepository().getResolvedPreservingPatchesVersion(version)); - for (LibraryAnalyzer.LibraryMark mark : analyzer) { - String libraryId = mark.getLibraryId(); - String libraryVersion = mark.getLibraryVersion(); - if (libraryId.equals(MINECRAFT.getPatchId())) continue; - if (AndroidUtils.hasStringId(this, "install_installer_" + libraryId.replace("-", "_"))) { - libraries.append(", ").append(AndroidUtils.getLocalizedText(this, "install_installer_" + libraryId.replace("-", "_"))); - if (libraryVersion != null) - libraries.append(": ").append(libraryVersion.replaceAll("(?i)" + libraryId, "")); - } - } - versionName.setText(version); - versionHint.setText(libraries.toString()); - icon.setBackgroundDrawable(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version)); - } else { - versionName.setText(getString(R.string.version_no_version)); - versionHint.setText(getString(R.string.version_manage)); - icon.setBackgroundDrawable(getDrawable(R.drawable.img_grass)); - } - } - - private void setupVersionDisplay() { - holder.add(FXUtils.onWeakChangeAndOperate(Profiles.selectedVersionProperty(), s -> Schedulers.androidUIThread().execute(() -> loadVersion(s)))); - } -} \ No newline at end of file diff --git a/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt b/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt new file mode 100644 index 00000000..9186df7d --- /dev/null +++ b/FCL/src/main/java/com/tungsten/fcl/activity/MainActivity.kt @@ -0,0 +1,459 @@ +package com.tungsten.fcl.activity + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.graphics.drawable.BitmapDrawable +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.widget.RelativeLayout +import androidx.appcompat.app.AlertDialog +import androidx.databinding.DataBindingUtil +import com.tungsten.fcl.R +import com.tungsten.fcl.databinding.ActivityMainBinding +import com.tungsten.fcl.game.JarExecutorHelper +import com.tungsten.fcl.game.TexturesLoader +import com.tungsten.fcl.setting.Accounts +import com.tungsten.fcl.setting.ConfigHolder +import com.tungsten.fcl.setting.Profile +import com.tungsten.fcl.setting.Profiles +import com.tungsten.fcl.ui.UIManager +import com.tungsten.fcl.ui.version.Versions +import com.tungsten.fcl.upgrade.UpdateChecker +import com.tungsten.fcl.util.AndroidUtils +import com.tungsten.fcl.util.FXUtils +import com.tungsten.fcl.util.WeakListenerHolder +import com.tungsten.fclcore.auth.Account +import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorAccount +import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorServer +import com.tungsten.fclcore.auth.offline.Skin +import com.tungsten.fclcore.auth.yggdrasil.TextureModel +import com.tungsten.fclcore.download.LibraryAnalyzer +import com.tungsten.fclcore.download.LibraryAnalyzer.LibraryType +import com.tungsten.fclcore.event.Event +import com.tungsten.fclcore.fakefx.beans.binding.Bindings +import com.tungsten.fclcore.fakefx.beans.property.ObjectProperty +import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty +import com.tungsten.fclcore.fakefx.beans.value.ObservableValue +import com.tungsten.fclcore.mod.RemoteMod +import com.tungsten.fclcore.mod.RemoteMod.IMod +import com.tungsten.fclcore.mod.RemoteModRepository +import com.tungsten.fclcore.task.Schedulers +import com.tungsten.fclcore.util.Logging +import com.tungsten.fclcore.util.fakefx.BindingMapping +import com.tungsten.fcllibrary.component.FCLActivity +import com.tungsten.fcllibrary.component.theme.ThemeEngine +import com.tungsten.fcllibrary.component.view.FCLEditText +import com.tungsten.fcllibrary.component.view.FCLMenuView +import com.tungsten.fcllibrary.component.view.FCLMenuView.OnSelectListener +import com.tungsten.fcllibrary.util.ConvertUtils +import java.io.IOException +import java.util.function.Consumer +import java.util.logging.Level +import java.util.stream.Stream + +class MainActivity : FCLActivity(), OnSelectListener, View.OnClickListener { + companion object { + @SuppressLint("StaticFieldLeak") + @JvmStatic + lateinit var instance: MainActivity + } + lateinit var bind: ActivityMainBinding + private var _uiManager: UIManager? = null + private lateinit var uiManager: UIManager + private lateinit var currentAccount: ObjectProperty + private val holder = WeakListenerHolder() + private var profile: Profile? = null + private var onVersionIconChangedListener: Consumer? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + instance = this + bind = DataBindingUtil.setContentView(this, R.layout.activity_main) + + bind.background.background = ThemeEngine.getInstance().getTheme().getBackground(this) + + Skin.registerDefaultSkinLoader { type: Skin.Type? -> + when (type) { + Skin.Type.ALEX -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/alex.png" + ) + + Skin.Type.ARI -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/ari.png" + ) + + Skin.Type.EFE -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/efe.png" + ) + + Skin.Type.KAI -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/kai.png" + ) + + Skin.Type.MAKENA -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/makena.png" + ) + + Skin.Type.NOOR -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/noor.png" + ) + + Skin.Type.STEVE -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/steve.png" + ) + + Skin.Type.SUNNY -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/sunny.png" + ) + + Skin.Type.ZURI -> return@registerDefaultSkinLoader Skin::class.java.getResourceAsStream( + "/assets/img/zuri.png" + ) + + else -> return@registerDefaultSkinLoader null + } + } + + RemoteMod.registerEmptyRemoteMod( + RemoteMod( + "", + "", + getString(R.string.mods_broken_dependency_title), + getString(R.string.mods_broken_dependency_desc), + ArrayList(), + "", + "", + object : IMod { + @Throws(IOException::class) + override fun loadDependencies(modRepository: RemoteModRepository): List { + throw IOException() + } + + @Throws(IOException::class) + override fun loadVersions(modRepository: RemoteModRepository): Stream { + throw IOException() + } + }) + ) + + try { + ConfigHolder.init() + } catch (e: IOException) { + Logging.LOG.log(Level.WARNING, e.message) + } + + bind.apply { + uiLayout.post { + ThemeEngine.getInstance().registerEvent(leftMenu) { + leftMenu.setBackgroundColor( + ThemeEngine.getInstance().getTheme().color + ) + } + + account.setOnClickListener(this@MainActivity) + version.setOnClickListener(this@MainActivity) + executeJar.setOnClickListener(this@MainActivity) + executeJar.setOnLongClickListener { + val padding = ConvertUtils.dip2px(this@MainActivity, 15f) + val editText = FCLEditText(this@MainActivity) + val layout = RelativeLayout(this@MainActivity) + editText.hint = "-jar xxx" + editText.setLines(1) + editText.maxLines = 1 + layout.setPadding(padding, padding, padding, padding) + layout.addView(editText) + val dialog = AlertDialog.Builder(this@MainActivity) + .setTitle(R.string.jar_execute_custom_args) + .setView(layout) + .setPositiveButton(com.tungsten.fcllibrary.R.string.dialog_positive) { _: DialogInterface?, _: Int -> + JarExecutorHelper.exec( + this@MainActivity, null, 8, editText.text.toString() + ) + } + .setNegativeButton(com.tungsten.fcllibrary.R.string.dialog_negative, null) + .create() + layout.layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + editText.layoutParams = RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + ThemeEngine.getInstance().applyFullscreen( + dialog.window, + ThemeEngine.getInstance().getTheme().isFullscreen + ) + dialog.show() + true + } + launch.setOnClickListener(this@MainActivity) + launch.setOnLongClickListener { + startActivity(Intent(this@MainActivity, ShellActivity::class.java)) + true + } + + uiManager = UIManager(this@MainActivity, uiLayout) + _uiManager = uiManager + uiManager.registerDefaultBackEvent(backToMainUI) + uiManager.init { + home.setOnSelectListener(this@MainActivity) + manage.setOnSelectListener(this@MainActivity) + download.setOnSelectListener(this@MainActivity) + controller.setOnSelectListener(this@MainActivity) + multiplayer.setOnSelectListener(this@MainActivity) + setting.setOnSelectListener(this@MainActivity) + back.setOnClickListener(this@MainActivity) + home.setSelected(true) + + setupAccountDisplay() + setupVersionDisplay() + UpdateChecker.getInstance().checkAuto(this@MainActivity).start() + } + } + } + } + + var backToMainUI: Runnable = Runnable { + if (uiManager.currentUI === uiManager.mainUI) { + val i = Intent(Intent.ACTION_MAIN) + i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + i.addCategory(Intent.CATEGORY_HOME) + startActivity(i) + } else { + bind.home.isSelected = true + } + } + + override fun onBackPressed() { + _uiManager?.onBackPressed() + super.onBackPressed() + } + + override fun onPause() { + super.onPause() + _uiManager?.onPause() + } + + override fun onResume() { + super.onResume() + _uiManager?.onResume() + } + + override fun onSelect(view: FCLMenuView) { + refreshMenuView(view) + bind.apply { + when(view) { + home -> { + title.setTextWithAnim(getString(R.string.app_name)) + uiManager.switchUI(uiManager.mainUI) + } + manage -> { + val version = Profiles.getSelectedVersion() + if (version == null) { + refreshMenuView(null) + title.setTextWithAnim(getString(R.string.version)) + uiManager.switchUI(uiManager.versionUI) + } else { + title.setTextWithAnim(getString(R.string.manage)) + uiManager.manageUI.setVersion(version, Profiles.getSelectedProfile()) + uiManager.switchUI(uiManager.manageUI) + } + } + download -> { + title.setTextWithAnim(getString(R.string.download)) + uiManager.switchUI(uiManager.downloadUI) + } + controller -> { + title.setTextWithAnim(getString(R.string.controller)) + uiManager.switchUI(uiManager.controllerUI) + } + multiplayer -> { + title.setTextWithAnim(getString(R.string.multiplayer)) + uiManager.switchUI(uiManager.multiplayerUI) + } + setting -> { + title.setTextWithAnim(getString(R.string.setting)) + uiManager.switchUI(uiManager.settingUI) + } + } + } + } + + fun refreshMenuView(view: FCLMenuView?) { + bind.apply { + val views = arrayOf( + home, + manage, + download, + controller, + multiplayer, + setting + ) + + for (v in views) { + if (v !== view) { + v.isSelected = false + } + } + } + } + + override fun onClick(view: View) { + bind.apply { + if (view === account && uiManager.currentUI !== uiManager.accountUI) { + refreshMenuView(null) + title.setTextWithAnim(getString(R.string.account)) + uiManager.switchUI(uiManager.accountUI) + } + if (view === version && uiManager.currentUI !== uiManager.versionUI) { + refreshMenuView(null) + title.setTextWithAnim(getString(R.string.version)) + uiManager.switchUI(uiManager.versionUI) + } + if (view === back) { + uiManager.onBackPressed() + } + if (view === executeJar) { + JarExecutorHelper.start(this@MainActivity, this@MainActivity) + } + if (view === launch) { + Versions.launch(this@MainActivity, Profiles.getSelectedProfile()) + } + } + } + + private fun setupAccountDisplay() { + bind.apply { + currentAccount = object : SimpleObjectProperty() { + override fun invalidated() { + val account = get() + if (account == null) { + accountName.stringProperty().unbind() + accountHint.stringProperty().unbind() + avatar.imageProperty().unbind() + accountName.text = getString(R.string.account_state_no_account) + accountHint.text = getString(R.string.account_state_add) + avatar.setBackgroundDrawable( + BitmapDrawable( + TexturesLoader.toAvatar( + TexturesLoader.getDefaultSkin(TextureModel.ALEX).image, + ConvertUtils.dip2px( + this@MainActivity, 30f + ) + ) + ) + ) + } else { + accountName.stringProperty() + .bind(BindingMapping.of(account) { obj: Account -> obj.character }) + accountHint.stringProperty().bind(accountSubtitle(this@MainActivity, account)) + avatar.imageProperty().unbind() + avatar.imageProperty().bind( + TexturesLoader.avatarBinding( + account, ConvertUtils.dip2px( + this@MainActivity, 30f + ) + ) + ) + } + } + } + (currentAccount as SimpleObjectProperty).bind(Accounts.selectedAccountProperty()) + } + } + + fun refreshAvatar(account: Account) { + Schedulers.androidUIThread().execute { + if (currentAccount.get() === account) { + bind.avatar.imageProperty().unbind() + bind.avatar.imageProperty().bind( + TexturesLoader.avatarBinding( + currentAccount.get(), ConvertUtils.dip2px( + this@MainActivity, 30f + ) + ) + ) + } + } + } + + @SuppressLint("UseCompatLoadingForDrawables") + private fun loadVersion(version: String?) { + if (Profiles.getSelectedProfile() != profile) { + profile = Profiles.getSelectedProfile() + if (profile != null) { + onVersionIconChangedListener = + profile!!.repository.onVersionIconChanged.registerWeak { + this.loadVersion(Profiles.getSelectedVersion()) + } + } + } + if (version != null && Profiles.getSelectedProfile() != null && Profiles.getSelectedProfile().repository.hasVersion( + 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( + this, + "install_installer_" + libraryId.replace("-", "_") + ) + ) + if (libraryVersion != null) libraries.append(": ").append( + libraryVersion.replace( + "(?i)$libraryId".toRegex(), "" + ) + ) + } + } + bind.versionName.text = version + bind.versionHint.text = libraries.toString() + bind.icon.setBackgroundDrawable( + Profiles.getSelectedProfile().repository.getVersionIconImage( + version + ) + ) + } else { + 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)) + } + } + + private fun setupVersionDisplay() { + holder.add(FXUtils.onWeakChangeAndOperate(Profiles.selectedVersionProperty()) { s: String? -> + Schedulers.androidUIThread().execute { loadVersion(s) } + }) + } + + private fun accountSubtitle(context: Context, account: Account): ObservableValue { + return if (account is AuthlibInjectorAccount) { + BindingMapping.of(account.server) { obj: AuthlibInjectorServer -> obj.name } + } else { + Bindings.createStringBinding({ + Accounts.getLocalizedLoginTypeName( + context, + Accounts.getAccountFactory(account) + ) + }) + } + } +} \ 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 f88e38c1..94f7b20f 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 @@ -62,7 +62,7 @@ public class ManageUI extends FCLMultiPageUI implements TabLayout.OnTabSelectedL Schedulers.androidUIThread().execute(() -> { if (isShowing()) { MainActivity.getInstance().refreshMenuView(null); - MainActivity.getInstance().home.setSelected(true); + MainActivity.getInstance().bind.home.setSelected(true); } }); return; @@ -158,7 +158,7 @@ public class ManageUI extends FCLMultiPageUI implements TabLayout.OnTabSelectedL loadVersion(preferredVersionName, this.version.get().getProfile()); } else if (isShowing()) { MainActivity.getInstance().refreshMenuView(null); - MainActivity.getInstance().home.setSelected(true); + MainActivity.getInstance().bind.home.setSelected(true); } } }); @@ -176,7 +176,7 @@ public class ManageUI extends FCLMultiPageUI implements TabLayout.OnTabSelectedL Schedulers.androidUIThread().execute(() -> { if (isShowing()) { MainActivity.getInstance().refreshMenuView(null); - MainActivity.getInstance().home.setSelected(true); + MainActivity.getInstance().bind.home.setSelected(true); } }); return; diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java index 23a7444a..fd544dae 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java @@ -406,7 +406,7 @@ public class ModListPage extends FCLCommonPage implements ManageUI.VersionLoadab public void download() { MainActivity.getInstance().refreshMenuView(null); - MainActivity.getInstance().download.setSelected(true); + MainActivity.getInstance().bind.download.setSelected(true); DownloadPageManager.getInstance().switchPage(DownloadPageManager.PAGE_ID_DOWNLOAD_MOD); } diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/setting/LauncherSettingPage.java b/FCL/src/main/java/com/tungsten/fcl/ui/setting/LauncherSettingPage.java index 50db9757..78e7446c 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/setting/LauncherSettingPage.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/setting/LauncherSettingPage.java @@ -289,7 +289,7 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi if (AndroidUtils.isDocUri(uri)) { path = AndroidUtils.copyFileToDir(getActivity(), uri, new File(FCLPath.CACHE_DIR)); } - ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).background, path, null); + ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).bind.background, path, null); } })); } @@ -307,7 +307,7 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi if (AndroidUtils.isDocUri(uri)) { path = AndroidUtils.copyFileToDir(getActivity(), uri, new File(FCLPath.CACHE_DIR)); } - ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).background, null, path); + ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).bind.background, null, path); } })); } @@ -319,7 +319,7 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi if (!new File(FCLPath.LT_BACKGROUND_PATH).delete() && new File(FCLPath.LT_BACKGROUND_PATH).exists()) Schedulers.androidUIThread().execute(() -> Toast.makeText(getContext(), getContext().getString(R.string.message_failed), Toast.LENGTH_SHORT).show()); - Schedulers.androidUIThread().execute(() -> ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).background, null, null)); + Schedulers.androidUIThread().execute(() -> ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).bind.background, null, null)); }).start(); } if (v == resetDkBackground) { @@ -327,7 +327,7 @@ public class LauncherSettingPage extends FCLCommonPage implements View.OnClickLi if (!new File(FCLPath.DK_BACKGROUND_PATH).delete() && new File(FCLPath.DK_BACKGROUND_PATH).exists()) Schedulers.androidUIThread().execute(() -> Toast.makeText(getContext(), getContext().getString(R.string.message_failed), Toast.LENGTH_SHORT).show()); - Schedulers.androidUIThread().execute(() -> ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).background, null, null)); + Schedulers.androidUIThread().execute(() -> ThemeEngine.getInstance().applyAndSave(getContext(), ((MainActivity) getActivity()).bind.background, null, null)); }).start(); } } diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/version/Versions.java b/FCL/src/main/java/com/tungsten/fcl/ui/version/Versions.java index 56e054af..aefc808a 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/version/Versions.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/version/Versions.java @@ -219,7 +219,7 @@ public class Versions { builder.setMessage(context.getString(R.string.version_empty_launch)); builder.setNegativeButton(context.getString(com.tungsten.fcllibrary.R.string.dialog_positive), () -> { MainActivity.getInstance().refreshMenuView(null); - MainActivity.getInstance().download.setSelected(true); + MainActivity.getInstance().bind.download.setSelected(true); }); builder.create().show(); return false; diff --git a/FCL/src/main/res/layout/activity_main.xml b/FCL/src/main/res/layout/activity_main.xml index 9b44251d..aab9fe8a 100644 --- a/FCL/src/main/res/layout/activity_main.xml +++ b/FCL/src/main/res/layout/activity_main.xml @@ -1,292 +1,294 @@ - - - + + android:id="@+id/background" + tools:context=".activity.MainActivity"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + android:text="@string/account" + android:textSize="11sp" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent"/> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - \ No newline at end of file + \ No newline at end of file