authlib injector account

This commit is contained in:
Tungstend 2023-07-04 18:01:04 +08:00
parent 6187eb529c
commit 9ff0670847
14 changed files with 487 additions and 46 deletions

View File

@ -18,7 +18,7 @@ public class AccountUI extends FCLCommonUI implements View.OnClickListener {
private LinearLayoutCompat addOfflineAccount;
private LinearLayoutCompat addMicrosoftAccount;
private LinearLayoutCompat addExternalAccount;
private LinearLayoutCompat addLoginServer;
private ListView listView;
private AccountListAdapter accountListAdapter;
@ -33,12 +33,15 @@ public class AccountUI extends FCLCommonUI implements View.OnClickListener {
addOfflineAccount = findViewById(R.id.offline);
addMicrosoftAccount = findViewById(R.id.microsoft);
addExternalAccount = findViewById(R.id.add_login_server);
addLoginServer = findViewById(R.id.add_login_server);
addOfflineAccount.setOnClickListener(this);
addMicrosoftAccount.setOnClickListener(this);
addExternalAccount.setOnClickListener(this);
addLoginServer.setOnClickListener(this);
listView = findViewById(R.id.list);
ListView serverListView = findViewById(R.id.server_list);
serverListView.setAdapter(new ServerListAdapter(getContext()));
}
@Override
@ -81,8 +84,8 @@ public class AccountUI extends FCLCommonUI implements View.OnClickListener {
CreateAccountDialog dialog = new CreateAccountDialog(getContext(), Accounts.FACTORY_MICROSOFT);
dialog.show();
}
if (view == addExternalAccount) {
CreateAccountDialog dialog = new CreateAccountDialog(getContext(), Accounts.FACTORY_AUTHLIB_INJECTOR);
if (view == addLoginServer) {
AddAuthlibInjectorServerDialog dialog = new AddAuthlibInjectorServerDialog(getContext());
dialog.show();
}
}

View File

@ -1,14 +1,125 @@
package com.tungsten.fcl.ui.account;
import static com.tungsten.fcl.setting.ConfigHolder.config;
import static com.tungsten.fclcore.util.Logging.LOG;
import android.content.Context;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.tungsten.fcl.R;
import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorServer;
import com.tungsten.fclcore.task.Schedulers;
import com.tungsten.fclcore.task.Task;
import com.tungsten.fcllibrary.component.dialog.FCLDialog;
import com.tungsten.fcllibrary.component.view.FCLButton;
import com.tungsten.fcllibrary.component.view.FCLConstraintLayout;
import com.tungsten.fcllibrary.component.view.FCLEditText;
import com.tungsten.fcllibrary.component.view.FCLTextView;
public class AddAuthlibInjectorServerDialog extends FCLDialog {
import java.io.IOException;
import java.util.Objects;
import java.util.logging.Level;
import javax.net.ssl.SSLException;
public class AddAuthlibInjectorServerDialog extends FCLDialog implements View.OnClickListener {
private FCLConstraintLayout firstLayout;
private FCLConstraintLayout secondLayout;
private FCLEditText editText;
private FCLTextView url;
private FCLTextView name;
private FCLButton next;
private FCLButton back;
private FCLButton positive;
private FCLButton negativePri;
private FCLButton negativeSec;
private AuthlibInjectorServer serverBeingAdded;
public AddAuthlibInjectorServerDialog(@NonNull Context context) {
super(context);
setCancelable(false);
setContentView(R.layout.dialog_add_authlib_injector_server);
firstLayout = findViewById(R.id.first_layout);
secondLayout = findViewById(R.id.second_layout);
editText = findViewById(R.id.url);
url = findViewById(R.id.address);
name = findViewById(R.id.name);
next = findViewById(R.id.next);
back = findViewById(R.id.prev);
positive = findViewById(R.id.positive);
negativePri = findViewById(R.id.negative_pri);
negativeSec = findViewById(R.id.negative_sec);
next.setOnClickListener(this);
back.setOnClickListener(this);
positive.setOnClickListener(this);
negativePri.setOnClickListener(this);
negativeSec.setOnClickListener(this);
firstLayout.setVisibility(View.VISIBLE);
secondLayout.setVisibility(View.GONE);
}
private void next() {
next.setEnabled(false);
negativePri.setEnabled(false);
String url = Objects.requireNonNull(editText.getText()).toString();
Task.runAsync(() -> {
serverBeingAdded = AuthlibInjectorServer.locateServer(url);
}).whenComplete(Schedulers.androidUIThread(), exception -> {
next.setEnabled(true);
negativePri.setEnabled(true);
if (exception == null) {
this.name.setText(serverBeingAdded.getName());
this.url.setText(serverBeingAdded.getUrl());
firstLayout.setVisibility(View.GONE);
secondLayout.setVisibility(View.VISIBLE);
} else {
LOG.log(Level.WARNING, "Failed to resolve auth server: " + url, exception);
Toast.makeText(getContext(), resolveFetchExceptionMessage(exception), Toast.LENGTH_SHORT).show();
}
}).start();
}
private String resolveFetchExceptionMessage(Throwable exception) {
if (exception instanceof SSLException) {
return getContext().getString(R.string.account_failed_ssl);
} else if (exception instanceof IOException) {
return getContext().getString(R.string.account_failed_connect_injector_server);
} else {
return exception.getClass().getName() + ": " + exception.getLocalizedMessage();
}
}
@Override
public void onClick(View v) {
if (v == next) {
next();
}
if (v == back) {
firstLayout.setVisibility(View.VISIBLE);
secondLayout.setVisibility(View.GONE);
}
if (v == positive) {
if (!config().getAuthlibInjectorServers().contains(serverBeingAdded)) {
config().getAuthlibInjectorServers().add(serverBeingAdded);
}
dismiss();
}
if (v == negativePri || v == negativeSec) {
dismiss();
}
}
}

View File

@ -17,7 +17,7 @@ import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.google.android.material.tabs.TabLayout;
@ -34,6 +34,7 @@ import com.tungsten.fclcore.auth.CharacterSelector;
import com.tungsten.fclcore.auth.NoSelectedCharacterException;
import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorAccountFactory;
import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorServer;
import com.tungsten.fclcore.auth.authlibinjector.BoundAuthlibInjectorAccountFactory;
import com.tungsten.fclcore.auth.microsoft.MicrosoftAccountFactory;
import com.tungsten.fclcore.auth.offline.OfflineAccountFactory;
import com.tungsten.fclcore.auth.yggdrasil.GameProfile;
@ -50,6 +51,7 @@ import com.tungsten.fcllibrary.component.dialog.FCLDialog;
import com.tungsten.fcllibrary.component.view.FCLButton;
import com.tungsten.fcllibrary.component.view.FCLEditText;
import com.tungsten.fcllibrary.component.view.FCLImageButton;
import com.tungsten.fcllibrary.component.view.FCLImageView;
import com.tungsten.fcllibrary.component.view.FCLTabLayout;
import com.tungsten.fcllibrary.component.view.FCLTextView;
@ -92,6 +94,10 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
init(factory);
}
public CreateAccountDialog(@NonNull Context context, AuthlibInjectorServer authServer) {
this(context, Accounts.getAccountFactoryByAuthlibInjectorServer(authServer));
}
private void init(AccountFactory<?> factory) {
if (factory == null) {
showMethodSwitcher = true;
@ -114,8 +120,7 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
titleId = R.string.account_create_offline;
} else if (factory instanceof MicrosoftAccountFactory) {
titleId = R.string.account_create_microsoft;
}
else {
} else {
titleId = R.string.account_create_external;
}
}
@ -136,6 +141,9 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
if (factory instanceof AuthlibInjectorAccountFactory) {
details = new ExternalDetails(getContext());
}
if (factory instanceof BoundAuthlibInjectorAccountFactory) {
details = new ExternalDetails(getContext(), ((BoundAuthlibInjectorAccountFactory) factory).getServer());
}
detailsContainer.removeAllViews();
detailsContainer.addView(details.getView(), ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
@ -323,7 +331,7 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
}
}
private static class ExternalDetails implements Details, View.OnClickListener {
private static class ExternalDetails implements Details {
private static final String[] ALLOWED_LINKS = { "homepage", "register" };
@ -333,27 +341,31 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
private FCLTextView serverName;
private FCLImageButton home;
private FCLImageButton register;
private FCLImageButton setting;
private final FCLEditText username;
private final FCLEditText password;
@Nullable
private final AuthlibInjectorServer server;
public ExternalDetails(Context context) {
this(context, config().getAuthlibInjectorServers().size() == 0 ? null : config().getAuthlibInjectorServers().get(0));
}
public ExternalDetails(Context context, @Nullable AuthlibInjectorServer server) {
this.context = context;
this.view = LayoutInflater.from(context).inflate(R.layout.view_create_account_external, null);
serverName = view.findViewById(R.id.server_name);
home = view.findViewById(R.id.home);
register = view.findViewById(R.id.register);
setting = view.findViewById(R.id.setting);
username = view.findViewById(R.id.username);
password = view.findViewById(R.id.password);
setting.setOnClickListener(this);
refreshAuthenticateServer(config().getAuthlibInjectorServers().size() == 0 ? null : config().getAuthlibInjectorServers().get(0));
this.server = server;
refreshAuthenticateServer(server);
}
private void refreshAuthenticateServer(AuthlibInjectorServer authlibInjectorServer) {
public void refreshAuthenticateServer(AuthlibInjectorServer authlibInjectorServer) {
if (authlibInjectorServer == null) {
serverName.setText(context.getString(R.string.account_create_server_not_select));
home.setVisibility(View.GONE);
@ -403,20 +415,16 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
@Override
public Object getAdditionalData() throws IllegalStateException {
return null;
if (server == null) {
throw new IllegalStateException(context.getString(R.string.account_create_server_not_select));
}
return server;
}
@Override
public View getView() throws IllegalStateException {
return view;
}
@Override
public void onClick(View view) {
if (view == setting) {
}
}
}
// character selector
@ -492,7 +500,7 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
static class ViewHolder {
ConstraintLayout parent;
AppCompatImageView avatar;
FCLImageView avatar;
FCLTextView name;
}
@ -500,6 +508,16 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
void onSelect(GameProfile profile);
}
@Override
public int getCount() {
return profiles.size();
}
@Override
public Object getItem(int i) {
return profiles.get(i);
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder viewHolder;
@ -515,10 +533,8 @@ public class CreateAccountDialog extends FCLDialog implements View.OnClickListen
}
GameProfile gameProfile = profiles.get(i);
viewHolder.name.setText(gameProfile.getName());
viewHolder.avatar.setBackground(TexturesLoader.avatarBinding(service, gameProfile.getId(), 32).get());
viewHolder.parent.setOnClickListener(view1 -> {
listener.onSelect(gameProfile);
});
viewHolder.avatar.imageProperty().bind(TexturesLoader.avatarBinding(service, gameProfile.getId(), 32));
viewHolder.parent.setOnClickListener(view1 -> listener.onSelect(gameProfile));
return view;
}
}

View File

@ -0,0 +1,75 @@
package com.tungsten.fcl.ui.account;
import static com.tungsten.fcl.setting.ConfigHolder.config;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.tungsten.fcl.R;
import com.tungsten.fcl.setting.Accounts;
import com.tungsten.fclcore.auth.authlibinjector.AuthlibInjectorServer;
import com.tungsten.fclcore.fakefx.beans.InvalidationListener;
import com.tungsten.fclcore.fakefx.collections.ObservableList;
import com.tungsten.fcllibrary.component.FCLAdapter;
import com.tungsten.fcllibrary.component.view.FCLImageButton;
import com.tungsten.fcllibrary.component.view.FCLTextView;
public class ServerListAdapter extends FCLAdapter {
private final ObservableList<AuthlibInjectorServer> list;
public ServerListAdapter(Context context) {
super(context);
list = config().getAuthlibInjectorServers();
list.addListener((InvalidationListener) i -> notifyDataSetChanged());
}
static class ViewHolder {
ConstraintLayout parent;
FCLTextView name;
FCLTextView url;
FCLImageButton delete;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@SuppressLint("UseCompatLoadingForDrawables")
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(getContext()).inflate(R.layout.item_authlib_injector_server, null);
viewHolder.parent = view.findViewById(R.id.parent);
viewHolder.name = view.findViewById(R.id.name);
viewHolder.url = view.findViewById(R.id.url);
viewHolder.delete = view.findViewById(R.id.delete);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
AuthlibInjectorServer server = list.get(i);
viewHolder.name.setText(server.getName());
viewHolder.url.setText(server.getUrl());
viewHolder.parent.setOnClickListener(v -> {
CreateAccountDialog dialog = new CreateAccountDialog(getContext(), server);
dialog.show();
});
viewHolder.delete.setOnClickListener(v -> config().getAuthlibInjectorServers().remove(server));
return view;
}
}

View File

@ -13,6 +13,7 @@ import com.tungsten.fcl.ui.account.CreateAccountDialog;
import com.tungsten.fcl.util.RequestCodes;
import com.tungsten.fcl.util.TaskCancellationAction;
import com.tungsten.fclcore.auth.Account;
import com.tungsten.fclcore.auth.AccountFactory;
import com.tungsten.fclcore.download.game.GameAssetDownloadTask;
import com.tungsten.fclcore.game.GameDirectoryType;
import com.tungsten.fclcore.task.Schedulers;
@ -197,7 +198,7 @@ public class Versions {
private static void ensureSelectedAccount(Context context, Consumer<Account> action) {
Account account = Accounts.getSelectedAccount();
if (account == null) {
CreateAccountDialog dialog = new CreateAccountDialog(context, null);
CreateAccountDialog dialog = new CreateAccountDialog(context, (AccountFactory<?>) null);
dialog.setOnDismissListener(dialogInterface -> {
Account newAccount = Accounts.getSelectedAccount();
if (newAccount == null) {

View File

@ -0,0 +1,10 @@
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@android:color/white"
android:pathData="M13,19H14A1,1 0 0,1 15,20H22V22H15A1,1 0 0,1 14,23H10A1,1 0 0,1 9,22H2V20H9A1,1 0 0,1 10,19H11V17H4A1,1 0 0,1 3,16V12A1,1 0 0,1 4,11H20A1,1 0 0,1 21,12V16A1,1 0 0,1 20,17H13V19M4,3H20A1,1 0 0,1 21,4V8A1,1 0 0,1 20,9H4A1,1 0 0,1 3,8V4A1,1 0 0,1 4,3M9,7H10V5H9V7M9,15H10V13H9V15M5,5V7H7V5H5M5,13V15H7V13H5Z"/>
</vector>

View File

@ -1,6 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="400dp"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="10dp">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:id="@+id/title"
android:text="@string/account_add_server"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.5"/>
<com.tungsten.fcllibrary.component.view.FCLConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/first_layout"
app:layout_constraintTop_toBottomOf="@+id/title"
android:layout_marginTop="10dp">
<com.tungsten.fcllibrary.component.view.FCLLinearLayout
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/url_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:singleLine="true"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="@string/account_add_server_url"
android:layout_gravity="center"/>
<com.tungsten.fcllibrary.component.view.FCLEditText
android:singleLine="true"
android:id="@+id/url"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</com.tungsten.fcllibrary.component.view.FCLLinearLayout>
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginTop="10dp"
android:id="@+id/next"
android:text="@string/event_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/url_layout"/>
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginTop="10dp"
android:id="@+id/negative_pri"
android:text="@string/dialog_negative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/url_layout"/>
</com.tungsten.fcllibrary.component.view.FCLConstraintLayout>
<com.tungsten.fcllibrary.component.view.FCLConstraintLayout
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/second_layout"
app:layout_constraintTop_toBottomOf="@+id/title"
android:layout_marginTop="10dp">
<com.tungsten.fcllibrary.component.view.FCLLinearLayout
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/address_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:singleLine="true"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="@string/account_add_server_url"
android:layout_gravity="center"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:singleLine="true"
android:id="@+id/address"
android:layout_width="230dp"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</com.tungsten.fcllibrary.component.view.FCLLinearLayout>
<androidx.appcompat.widget.LinearLayoutCompat
app:layout_constraintTop_toBottomOf="@+id/address_layout"
android:id="@+id/name_layout"
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:singleLine="true"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="@string/account_add_server_name"
android:layout_gravity="center"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:singleLine="true"
android:id="@+id/name"
android:layout_width="230dp"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginTop="15dp"
android:id="@+id/prev"
android:text="@string/event_prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/name_layout"/>
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginTop="15dp"
android:layout_marginEnd="15dp"
android:id="@+id/positive"
android:text="@string/dialog_positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="@+id/negative_sec"
app:layout_constraintTop_toBottomOf="@id/name_layout"/>
<com.tungsten.fcllibrary.component.view.FCLButton
android:layout_marginTop="15dp"
android:id="@+id/negative_sec"
android:text="@string/dialog_negative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/name_layout"/>
</com.tungsten.fcllibrary.component.view.FCLConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_width="300dp"
android:layout_height="match_parent"
android:padding="10dp"
xmlns:app="http://schemas.android.com/apk/res-auto">

View File

@ -39,7 +39,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="130dp"
android:layout_marginEnd="170dp"
app:layout_constraintStart_toEndOf="@+id/avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="@drawable/bg_container_transparent_clickable"
android:padding="10dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_gravity="center"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/ic_baseline_server_24"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.5"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintEnd_toStartOf="@+id/delete"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.5">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="@+id/name"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:textSize="11sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="@+id/url"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.tungsten.fcllibrary.component.view.FCLImageButton
android:id="@+id/delete"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_baseline_close_24"
app:auto_tint="true"
app:no_padding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.5"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -6,14 +6,15 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_marginTop="5dp"
android:background="@drawable/bg_item_clickable"
android:clickable="true"
android:background="@drawable/bg_container_transparent_clickable"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
<com.tungsten.fcllibrary.component.view.FCLImageView
android:id="@+id/avatar"
android:layout_width="30dp"
android:layout_height="30dp"
@ -29,7 +30,7 @@
android:singleLine="true"
android:layout_marginStart="8dp"
app:layout_constraintVertical_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/avatar"
app:layout_constraintStart_toEndOf="@+id/avatar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

View File

@ -50,15 +50,6 @@
app:auto_tint="true"
android:id="@+id/register"/>
<com.tungsten.fcllibrary.component.view.FCLImageButton
android:layout_marginStart="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_baseline_settings_24"
app:auto_tint="true"
android:id="@+id/setting"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat

View File

@ -18,6 +18,9 @@
<string name="about">关于</string>
<string name="account_add_server">添加认证服务器</string>
<string name="account_add_server_url">服务器地址</string>
<string name="account_add_server_name">服务器名称</string>
<string name="account_cape">披风</string>
<string name="account_create">创建账户</string>
<string name="account_create_offline">创建离线账户</string>
@ -39,6 +42,7 @@
<string name="account_failed">账户刷新失败</string>
<string name="account_failed_no_character">该账户中无角色。</string>
<string name="account_failed_connect_authentication_server">无法连接认证服务器,请检查网络。</string>
<string name="account_failed_connect_injector_server">无法连接认证服务器。 请检查网络并确认你输入了正确的地址。</string>
<string name="account_failed_server_disconnected">无法连接认证服务器。你可以暂时离线游戏或尝试重新登录。</string>
<string name="account_failed_server_response_malformed">无效的返回码,该认证服务器可能失效。</string>
<string name="account_failed_invalid_credentials">不正确的密码或被限速,请稍后再试。</string>
@ -47,6 +51,7 @@
<string name="account_failed_migration">你的账户需要迁移至微软账户,如果已经迁移,请尝试重新登录。</string>
<string name="account_failed_injector_download_failure">无法下载 authlib-injector。 请检查网络,或修改下载源。</string>
<string name="account_failed_character_deleted">该角色已被删除。</string>
<string name="account_failed_ssl">连接服务器时发生了 SSL 错误。</string>
<string name="account_failed_wrong_account">登录了错误的账户。</string>
<string name="account_skin_invalid_skin">无效的皮肤文件</string>
<string name="account_methods_microsoft_error_add_family">你尚未满 18 岁,需要一位成年将你加入至家庭中。</string>
@ -146,6 +151,9 @@
<string name="edit_direction_event_sneak">双击中心潜行</string>
<string name="edit_direction_event_sneak_code">潜行键值</string>
<string name="event_next">下一步</string>
<string name="event_prev">上一步</string>
<string name="exception_access_denied">无法获取文件 %s。</string>
<string name="exception_artifact_malformed">无法校验文件。</string>
<string name="exception_ssl_handshake">缺少 SSL 证书。</string>

View File

@ -26,6 +26,9 @@
<string name="about">About</string>
<string name="account_add_server">Add Authentication Server</string>
<string name="account_add_server_url">Server URL</string>
<string name="account_add_server_name">Server Name</string>
<string name="account_cape">Cape</string>
<string name="account_create">Create Account</string>
<string name="account_create_offline">Create Offline Account</string>
@ -47,6 +50,7 @@
<string name="account_failed">Account refresh failed</string>
<string name="account_failed_no_character">There are no characters linked to this account.</string>
<string name="account_failed_connect_authentication_server">Unable to contact authentication servers, your Internet connection may be down.</string>
<string name="account_failed_connect_injector_server">Unable to connect to the authentication server. Please check your network and make sure you entered the correct URL.</string>
<string name="account_failed_server_disconnected">Cannot access authentication server. You can log in offline or try to re-login.</string>
<string name="account_failed_server_response_malformed">Invalid server response, the authentication server may not be working.</string>
<string name="account_failed_invalid_credentials">Incorrect password or rate limited, please try again later.</string>
@ -55,6 +59,7 @@
<string name="account_failed_migration">Your account needs to be migrated to a Microsoft account. If you already did, you should re-login to your migrated Microsoft account instead.</string>
<string name="account_failed_injector_download_failure">Unable to download authlib-injector. Please check your network, or try switching to a different download mirror.</string>
<string name="account_failed_character_deleted">The character has already been deleted.</string>
<string name="account_failed_ssl">An SSL error occurred while connecting to the server.</string>
<string name="account_failed_wrong_account">You have logged in to the wrong account.</string>
<string name="account_skin_invalid_skin">Invalid skin file</string>
<string name="account_methods_microsoft_error_add_family">Since you are not yet 18 years old, an adult must add you to a family in order for you to play Minecraft.</string>
@ -157,6 +162,9 @@
<string name="edit_direction_event_sneak">Double Click Center to Sneak</string>
<string name="edit_direction_event_sneak_code">Sneak Keycode</string>
<string name="event_next">Next</string>
<string name="event_prev">Prev</string>
<string name="exception_access_denied">Unable to access the file %s.</string>
<string name="exception_artifact_malformed">Cannot verify the integrity of the downloaded files.</string>
<string name="exception_ssl_handshake">Unable to establish SSL connection due to missing SSL certificates in current Java installation.</string>