Commit 8336ab66 authored by fallenstardust's avatar fallenstardust Committed by GitHub

Merge pull request #190 from zhuhongbozhuhongbo/master

卡组广场并入主项目
parents 3f43b00a 3c2f770b
上传新卡组调用api:
首先获得卡组id:
【get] http://rarnu.xyz:38383/api/mdpro3/deck/deckId
将获得的卡组id作为json body的一部分,上传到服务器:
http://rarnu.xyz:38383/api/mdpro3/sync/single
json body格式如下:
{
"deckContributor": "zhb_con",
"userId": 795610,
"deck": {
"deckId": "0007b1ad19",
"deckName": "zhb_test_deck2",
"deckCoverCard1": 0,
"deckCoverCard2": 0,
"deckCoverCard3": 0,
"deckCase": 0,
"deckProtector": 0,
"deckYdk": "#created by
mdpro3\r\n#main\r\n89943723\r\n89943724\r\n89943724\r\n79856792\r\n58153103\r\n83965310\r\n14124483\r\n13256226\r\n13256226\r\n9411399\r\n9411399\r\n18094166\r\n18094166\r\n40044918\r\n40044918\r\n59392529\r\n63060238\r\n50720316\r\n50720316\r\n27780618\r\n27780618\r\n16605586\r\n16605586\r\n43237273\r\n80344569\r\n22865492\r\n22865492\r\n17955766\r\n14558127\r\n14558127\r\n14558127\r\n23434538\r\n23434538\r\n23434538\r\n40740224\r\n6186304\r\n18144506\r\n213326\r\n213326\r\n8949584\r\n8949584\r\n10186633\r\n32807848\r\n21143940\r\n21143940\r\n80170678\r\n52947044\r\n45906428\r\n45906428\r\n24094653\r\n24094653\r\n14088859\r\n14088859\r\n24224830\r\n24224830\r\n65681983\r\n24299458\r\n75047173\r\n10045474\r\n75047173\r\n#extra\r\n90050480\r\n86346643\r\n31817415\r\n32828466\r\n40080312\r\n56733747\r\n29095552\r\n40854197\r\n46759931\r\n60461804\r\n93347961\r\n64655485\r\n22908820\r\n58481572\r\n58004362\r\n!
side\r\n27204311\r\n27204311\r\n83965311\r\n59438930\r\n59438930\r\n24508238\r\n24508238\r\n94145021\r\n94145021\r\n26964762\r\n90846359\r\n83326048\r\n83326048\r\n83326048\r\n#pickup\r\n#case\r\n1081008#\r\n#protector\r\n1070008#\r\n#field\r\n1090009#\r\n#grave\r\n1100009#\r\n#stand\r\n1110001#\r\n#mate\r\n1000007#\r\n##\r\n###",
"isDelete": false
}
}
注意:deckId字段为[get]方法获得的id,deckName字段对应于卡组名称,服务端会检查该字段,不允许同一卡组名称上传多次(如果第二次上传某个卡组名,会返回false,上传失败)
上传成功后,服务器响应为:
{
"code": 0,
"message": "",
"data": true
}
上传失败后,服务器响应为:
更新已在云上存在的卡组:
仍然用上述body,但是其中deckId、deckName必须与云上的记录严格对应。
示例:
[1]云上存在卡组deckId=111,deckName=双打水产。
上传json中,deckId=111,deckName=双打水产,代表更新云上的该卡组的内容。
[2]云上存在卡组deckId=111,deckName=双打水产,
上传json中,deckId=110,deckName=双打水产,服务端会返回错误,本次上传失败。
即,如果服务器上已存在卡组名称XXX,则再上传“卡组名为XXX,卡组id不同”的卡组,会返回错误
[3]云上存在卡组deckId=111,deckName=双打水产,
上传json中,deckId=111,deckName=双打水产B,代表更新卡组名称,本次上传成功。
总结:
将对应于deckId、deckName的卡组内容json推送到服务器。
如果在服务器上不存在deckId、deckName对应的记录,则创建新卡组
如果在服务器存在deckId相同的记录,则更新卡组,deckName会覆盖服务器上的卡组名
如果在服务器存在deckName相同、deckId不同的记录,则更新失败
\ No newline at end of file
...@@ -19,8 +19,8 @@ android { ...@@ -19,8 +19,8 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_11
} }
productFlavors { productFlavors {
cn { cn {
...@@ -68,6 +68,9 @@ android { ...@@ -68,6 +68,9 @@ android {
noCompress 'dll', 'config' noCompress 'dll', 'config'
} }
namespace 'cn.garymb.ygomobile.lite' namespace 'cn.garymb.ygomobile.lite'
buildFeatures {
viewBinding true
}
// buildToolsVersion '28.0.3' // buildToolsVersion '28.0.3'
} }
...@@ -89,6 +92,7 @@ dependencies { ...@@ -89,6 +92,7 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation 'androidx.navigation:navigation-fragment:2.8.1' implementation 'androidx.navigation:navigation-fragment:2.8.1'
implementation 'androidx.navigation:navigation-ui:2.8.1' implementation 'androidx.navigation:navigation-ui:2.8.1'
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation('com.github.chrisbanes.photoview:library:1.2.4') { implementation('com.github.chrisbanes.photoview:library:1.2.4') {
implementation 'com.github.chrisbanes.photoview:library:1.2.4' implementation 'com.github.chrisbanes.photoview:library:1.2.4'
......
...@@ -21,11 +21,12 @@ ...@@ -21,11 +21,12 @@
android:name="cn.garymb.ygomobile.ui.activities.LogoActivity" android:name="cn.garymb.ygomobile.ui.activities.LogoActivity"
android:excludeFromRecents="false" android:excludeFromRecents="false"
android:theme="@style/TranslucentTheme"> android:theme="@style/TranslucentTheme">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<!--meta-data <!--meta-data
android:name="android.app.shortcuts" android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" /--> android:resource="@xml/shortcuts" /-->
...@@ -158,14 +159,14 @@ ...@@ -158,14 +159,14 @@
<!-- android:screenOrientation="landscape"--> <!-- android:screenOrientation="landscape"-->
<activity <activity
android:name="cn.garymb.ygomobile.ex_card.ExCardActivity" android:name="cn.garymb.ygomobile.ex_card.ExCardActivity"
android:theme="@style/AppTheme.Mycard"
android:launchMode="singleTop" android:launchMode="singleTop"
/> android:theme="@style/AppTheme.Mycard" />
<service <service
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService" android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt" android:label="dexopt"
android:process=":dexopt" > android:process=":dexopt"></service>
</service>
<!-- 如果已经安装过原版YGOMobile,请注释掉或修改成其他,否则会导致无法安装 --> <!-- 如果已经安装过原版YGOMobile,请注释掉或修改成其他,否则会导致无法安装 -->
<provider <provider
android:name="cn.garymb.ygomobile.ui.settings.YGOPreferencesProvider" android:name="cn.garymb.ygomobile.ui.settings.YGOPreferencesProvider"
......
package androidx.appcompat.widget; package androidx.recyclerview.widget;
import android.view.GestureDetector; import android.view.GestureDetector;
...@@ -6,7 +6,6 @@ import android.view.MotionEvent; ...@@ -6,7 +6,6 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import androidx.core.view.GestureDetectorCompat; import androidx.core.view.GestureDetectorCompat;
import androidx.recyclerview.widget.RecyclerView;
public class RecyclerViewItemListener extends RecyclerView.SimpleOnItemTouchListener { public class RecyclerViewItemListener extends RecyclerView.SimpleOnItemTouchListener {
private final GestureDetectorCompat gestureDetector; private final GestureDetectorCompat gestureDetector;
......
...@@ -19,9 +19,9 @@ import static cn.garymb.ygomobile.Constants.DEF_PREF_KEEP_SCALE; ...@@ -19,9 +19,9 @@ import static cn.garymb.ygomobile.Constants.DEF_PREF_KEEP_SCALE;
import static cn.garymb.ygomobile.Constants.DEF_PREF_NOTCH_HEIGHT; import static cn.garymb.ygomobile.Constants.DEF_PREF_NOTCH_HEIGHT;
import static cn.garymb.ygomobile.Constants.DEF_PREF_ONLY_GAME; import static cn.garymb.ygomobile.Constants.DEF_PREF_ONLY_GAME;
import static cn.garymb.ygomobile.Constants.DEF_PREF_READ_EX; import static cn.garymb.ygomobile.Constants.DEF_PREF_READ_EX;
import static cn.garymb.ygomobile.Constants.PREF_DEF_KEY_WORDS_SPLIT;
import static cn.garymb.ygomobile.Constants.PREF_DEF_DATA_LANGUAGE; import static cn.garymb.ygomobile.Constants.PREF_DEF_DATA_LANGUAGE;
import static cn.garymb.ygomobile.Constants.PREF_DEF_IMMERSIVE_MODE; import static cn.garymb.ygomobile.Constants.PREF_DEF_IMMERSIVE_MODE;
import static cn.garymb.ygomobile.Constants.PREF_DEF_KEY_WORDS_SPLIT;
import static cn.garymb.ygomobile.Constants.PREF_DEF_SENSOR_REFRESH; import static cn.garymb.ygomobile.Constants.PREF_DEF_SENSOR_REFRESH;
import static cn.garymb.ygomobile.Constants.PREF_FONT_SIZE; import static cn.garymb.ygomobile.Constants.PREF_FONT_SIZE;
import static cn.garymb.ygomobile.Constants.PREF_IMMERSIVE_MODE; import static cn.garymb.ygomobile.Constants.PREF_IMMERSIVE_MODE;
...@@ -499,6 +499,7 @@ public class AppsSettings { ...@@ -499,6 +499,7 @@ public class AppsSettings {
public String getCoreSkinPath() { public String getCoreSkinPath() {
return new File(getResourcePath(), Constants.CORE_SKIN_PATH).getAbsolutePath(); return new File(getResourcePath(), Constants.CORE_SKIN_PATH).getAbsolutePath();
} }
public String getAvatarPath() { public String getAvatarPath() {
return new File(getResourcePath(), Constants.CORE_AVATAR_PATH).getAbsolutePath(); return new File(getResourcePath(), Constants.CORE_AVATAR_PATH).getAbsolutePath();
} }
...@@ -510,6 +511,7 @@ public class AppsSettings { ...@@ -510,6 +511,7 @@ public class AppsSettings {
public String getBgPath() { public String getBgPath() {
return new File(getResourcePath(), Constants.CORE_BG_PATH).getAbsolutePath(); return new File(getResourcePath(), Constants.CORE_BG_PATH).getAbsolutePath();
} }
/*** /***
* 字体路径 * 字体路径
*/ */
...@@ -613,7 +615,12 @@ public class AppsSettings { ...@@ -613,7 +615,12 @@ public class AppsSettings {
return mSharedPreferences.getString(Constants.PREF_DEF_LAST_YDK, null); return mSharedPreferences.getString(Constants.PREF_DEF_LAST_YDK, null);
} }
//获得最后卡组绝对路径 /**
* 获得(最后)上次打开的卡组的绝对路径
* setCurDeck()方法负责设置上次打开的卡组的路径
*
* @return
*/
public @Nullable public @Nullable
String getLastDeckPath() { String getLastDeckPath() {
String path; String path;
...@@ -804,7 +811,7 @@ public class AppsSettings { ...@@ -804,7 +811,7 @@ public class AppsSettings {
Korean(1, "ko"), Korean(1, "ko"),
English(2, "en"), English(2, "en"),
Spanish(3, "es"), Spanish(3, "es"),
Japanese(4,"jp"), Japanese(4, "jp"),
Portuguese(5, "pt"); Portuguese(5, "pt");
public Integer code; public Integer code;
...@@ -913,7 +920,7 @@ public class AppsSettings { ...@@ -913,7 +920,7 @@ public class AppsSettings {
setDataLanguage(languageEnum.Portuguese.code); setDataLanguage(languageEnum.Portuguese.code);
} }
private void replaceLineFeed(){ private void replaceLineFeed() {
//替换换行符 //替换换行符
String stringConfPath = new File(getResourcePath(), CORE_STRING_PATH).getAbsolutePath(); String stringConfPath = new File(getResourcePath(), CORE_STRING_PATH).getAbsolutePath();
String botConfPath = new File(getResourcePath(), BOT_CONF).getAbsolutePath(); String botConfPath = new File(getResourcePath(), BOT_CONF).getAbsolutePath();
......
...@@ -25,7 +25,7 @@ public class DeckInfo { ...@@ -25,7 +25,7 @@ public class DeckInfo {
private final List<Card> sideCards; private final List<Card> sideCards;
private final List<Card> allCards; private final List<Card> allCards;
public File source; public File source;//当前打开的ydk文件的file
private int mainCount, extraCount, sideCount; private int mainCount, extraCount, sideCount;
......
package cn.garymb.ygomobile.bean; package cn.garymb.ygomobile.bean;
public class DeckType extends TextSelect { public class DeckType extends TextSelect {
public enum ServerType {
LOCAL,//本地卡组
SQUARE_DECK,//卡组广场上的卡组
MY_SQUARE,//本用户在云上的卡组
}
private String name; private String name;
private String path; private String path;
private ServerType onServer;//true代表云端卡组,false代表本地卡组
public DeckType(String name, String path) { public DeckType(String name, String path) {
this.name = name; this.name = name;
this.path = path; this.path = path;
onServer = ServerType.LOCAL;
super.setName(name); super.setName(name);
setObject(this); setObject(this);
} }
public DeckType(String name, String path, ServerType onServer) {
this.name = name;
this.path = path;
this.onServer = onServer;
setObject(this);
}
public String getName() { public String getName() {
return name; return name;
} }
...@@ -27,4 +42,16 @@ public class DeckType extends TextSelect { ...@@ -27,4 +42,16 @@ public class DeckType extends TextSelect {
this.path = path; this.path = path;
} }
public ServerType getOnServer() {
return onServer;
}
public void setOnServer(ServerType onServer) {
this.onServer = onServer;
}
//true代表卡组位于本地
public boolean isLocal() {
return (this.onServer == ServerType.LOCAL);
}
} }
...@@ -2,27 +2,54 @@ package cn.garymb.ygomobile.bean.events; ...@@ -2,27 +2,54 @@ package cn.garymb.ygomobile.bean.events;
import java.io.File; import java.io.File;
import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.TextSelect; import cn.garymb.ygomobile.bean.TextSelect;
import cn.garymb.ygomobile.utils.DeckUtil; import cn.garymb.ygomobile.utils.DeckUtil;
public class DeckFile extends TextSelect { public class DeckFile extends TextSelect {
private File path;
private final File path; private String fileFullName;//本地文件对应的名称,仅在onServer为false时有效
private final String fullName; // private final File path;
// private final String fullName;
//分类 //分类
private String typeName; private String typeName;//可取值包括cacheDeck,Pack
private int firstCode; private int firstCode;
private DeckType.ServerType onServer;//true代表云端卡组,false代表本地卡组
private String deckId;//如果onServer为true,代表该卡组存储在云上,deckId是唯一id
// public DeckFile(boolean onServer) {
// this.onServer = onServer;
// }
public DeckFile(String deckId, DeckType.ServerType onServer) {
this.deckId = deckId;
this.onServer = onServer;
}
public DeckFile(String name, String typeName, DeckType.ServerType onServer, String deckId) {
this.typeName = typeName;
this.onServer = onServer;
this.deckId = deckId;
this.setName(name);
this.fileFullName = null;
this.path = null;
this.firstCode = -1;
setObject(this);
}
public DeckFile(String path) { public DeckFile(String path) {
this(new File(path)); this(new File(path));
} }
public DeckFile(File file) { public DeckFile(File file) {
this.onServer = DeckType.ServerType.LOCAL;
this.deckId = null;
path = file; path = file;
fullName = file.getName(); fileFullName = file.getName();
String name = fullName; String name = fileFullName;
int index = name.lastIndexOf("."); int index = name.lastIndexOf(".");
if(index > 0) { if (index > 0) {
name = name.substring(0, index); name = name.substring(0, index);
} }
typeName = DeckUtil.getDeckTypeName(path.getAbsolutePath()); typeName = DeckUtil.getDeckTypeName(path.getAbsolutePath());
...@@ -32,7 +59,7 @@ public class DeckFile extends TextSelect { ...@@ -32,7 +59,7 @@ public class DeckFile extends TextSelect {
} }
public int getFirstCode() { public Integer getFirstCode() {
return firstCode; return firstCode;
} }
...@@ -49,7 +76,7 @@ public class DeckFile extends TextSelect { ...@@ -49,7 +76,7 @@ public class DeckFile extends TextSelect {
} }
public String getFileName() { public String getFileName() {
return fullName; return fileFullName;
} }
public File getPathFile() { public File getPathFile() {
...@@ -64,4 +91,38 @@ public class DeckFile extends TextSelect { ...@@ -64,4 +91,38 @@ public class DeckFile extends TextSelect {
return path.lastModified(); return path.lastModified();
} }
public DeckType.ServerType getOnServer() {
return onServer;
}
public void setOnServer(DeckType.ServerType onServer) {
this.onServer = onServer;
}
//true代表卡组位于本地
public boolean isLocal() {
return (this.onServer == DeckType.ServerType.LOCAL);
}
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
@Override
public String toString() {
return "DeckFile{" +
"path=" + path +
", fileFullName='" + fileFullName + '\'' +
", typeName='" + typeName + '\'' +
", firstCode=" + firstCode +
", onServer=" + onServer +
", deckId='" + deckId + '\'' +
'}';
}
} }
package cn.garymb.ygomobile.deck_square;
import android.os.Parcel;
import android.os.Parcelable;
public class DeckInfo implements Parcelable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected DeckInfo(Parcel in) {
name = in.readString();
}
public static final Creator<DeckInfo> CREATOR = new Creator<DeckInfo>() {
@Override
public DeckInfo createFromParcel(Parcel in) {
return new DeckInfo(in);
}
@Override
public DeckInfo[] newArray(int size) {
return new DeckInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
}
package cn.garymb.ygomobile.deck_square;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
public class DeckManageDialog extends DialogFragment implements YGODeckDialogUtil.OnDeckDialogListener {
public void onDismiss() {
dismiss();
}
public void onShow() {
//todo
}
private YGODeckDialogUtil.OnDeckMenuListener mOnDeckMenuListener;
public DeckManageDialog(YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener) {
super();
mOnDeckMenuListener = onDeckMenuListener;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.dialog_deck_manager, container, false);
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager2 viewPager = view.findViewById(R.id.deck_view_pager);
TabLayout tabLayout = view.findViewById(R.id.deck_manager_tab_layout);
// Setup adapter
ViewPagerAdapter adapter = new ViewPagerAdapter(this, mOnDeckMenuListener, this);
viewPager.setAdapter(adapter);
// Connect TabLayout with ViewPager
new TabLayoutMediator(tabLayout, viewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
//tab.setText("Tab " + (position + 1));
switch (position) {
case 0:
tab.setIcon(R.drawable.ic_deck_box);
tab.setText(R.string.local_deck);
break;
case 1:
tab.setIcon(R.drawable.ic_deck_square);
tab.setText(R.string.deck_square);
break;
case 2:
tab.setIcon(R.drawable.my_deck_square);
tab.setText(R.string.my_deck_online);
break;
}
}
}).attach();
}
@Override
public void onStart() {
super.onStart();
// Set dialog dimensions
Window window = getDialog().getWindow();
if (window != null) {
window.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
}
}
private static class ViewPagerAdapter extends FragmentStateAdapter {
private YGODeckDialogUtil.OnDeckMenuListener mOnDeckMenuListener;
private YGODeckDialogUtil.OnDeckDialogListener onDeckDialogListener;
public ViewPagerAdapter(@NonNull Fragment fragment, YGODeckDialogUtil.OnDeckMenuListener listener, YGODeckDialogUtil.OnDeckDialogListener dialogListener) {
super(fragment);
mOnDeckMenuListener = listener;
onDeckDialogListener = dialogListener;
}
@NonNull
@Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new DeckSelectFragment(mOnDeckMenuListener, onDeckDialogListener);
case 1:
return new DeckSquareFragment(mOnDeckMenuListener, onDeckDialogListener);
case 2:
return new DeckSquareMyDeckFragment(mOnDeckMenuListener, onDeckDialogListener);
default:
throw new IllegalArgumentException();
}
}
@Override
public int getItemCount() {
return 3;
}
}
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square;
import java.util.List;
public class DeckResponseJson {
int code;
String message;
String name;
List<DeckInfo> hobbies;
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.FastScrollLinearLayoutManager;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemLongClickListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import cn.garymb.ygomobile.AppsSettings;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.lite.databinding.FragmentDeckSelectBinding;
import cn.garymb.ygomobile.ui.adapters.DeckListAdapter;
import cn.garymb.ygomobile.ui.adapters.SimpleListAdapter;
import cn.garymb.ygomobile.ui.adapters.TextSelectAdapter;
import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.utils.DeckUtil;
import cn.garymb.ygomobile.utils.FileUtils;
import cn.garymb.ygomobile.utils.IOUtils;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
//在dialog中卡组选择的Fragment,选中页面中某项后,在卡组编辑页面中显示卡片
public class DeckSelectFragment extends Fragment {
private FragmentDeckSelectBinding binding;
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private TextSelectAdapter<DeckType> typeAdp;//卡组dialog中,左列的adapter
private DeckListAdapter<DeckFile> deckAdp;//卡组dialog中,右列的adapter
private DeckListAdapter<DeckFile> resultListAdapter;
private List<DeckFile> allDeckList = new ArrayList<>();//存储所有卡组DeckFile,用于支持“根据关键词搜索卡组”功能
private List<DeckFile> resultList = new ArrayList<>();//存储卡组“根据关键词搜索”的结果
List<DeckType> typeList = null;
List<DeckFile> deckList = null; //存储当前卡组分类下的所有卡组
private YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener;//通知外部调用方,(如调用本fragment的activity)
private YGODeckDialogUtil.OnDeckDialogListener mDialogListener;
/**
*
* @param onDeckMenuListener 通知容纳dialog的外部页面,已选中了某项卡组
* @param dialogListener 通知容纳本fragment的dialog,调用dismiss()方法,关闭dialog显示
*/
DeckSelectFragment(YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener, YGODeckDialogUtil.OnDeckDialogListener dialogListener) {
super();
this.onDeckMenuListener = onDeckMenuListener;
this.mDialogListener = dialogListener;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentDeckSelectBinding.inflate(inflater, container, false);
binding.rvDeck.setLayoutManager(new FastScrollLinearLayoutManager(getContext()));
binding.rvType.setLayoutManager(new FastScrollLinearLayoutManager(getContext()));
binding.rvResultList.setLayoutManager(new FastScrollLinearLayoutManager(getContext()));
initAdapter();
binding.rvType.setAdapter(typeAdp);
binding.rvDeck.setAdapter(deckAdp);
binding.rvResultList.setAdapter(resultListAdapter);
hideAllDeckUtil();
{
typeAdp.setOnItemSelectListener(new TextSelectAdapter.OnItemSelectListener<DeckType>() {
@Override
public void onItemSelect(int position, DeckType item) {
clearDeckSelect();
deckList.clear();
deckList.addAll(DeckUtil.getDeckList(item.getPath()));
if (position == 0) {
if (AppsSettings.get().isReadExpansions()) {
try {
if (!DeckUtil.getExpansionsDeckList().isEmpty()) {
deckList.addAll(0, DeckUtil.getExpansionsDeckList());
}
} catch (IOException e) {
YGOUtil.showTextToast("额外卡库加载失败,原因为" + e);
}
}
}
deckAdp.notifyDataSetChanged();
}
});
deckAdp.setOnItemSelectListener(new DeckListAdapter.OnItemSelectListener<DeckFile>() {
@Override
public void onItemSelect(int position, DeckFile item) {
if (deckAdp.isManySelect()) {
deckAdp.addManySelect(item);
if (deckAdp.getSelectList().size() == 0) {
clearDeckSelect();
}
deckAdp.notifyItemChanged(position);
} else {
//dismiss();
mDialogListener.onDismiss();
onDeckMenuListener.onDeckSelect(item);
}
}
});
//对话框中长点击某一卡组名称后,触发该事件
deckAdp.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) {
DeckFile item = (DeckFile) adapter.getItem(position);
//即使为local,也有可能为卡包预览,因此过滤掉selectposition==0
if (deckAdp.isSelect() || typeAdp.getSelectPosition() == 0)
return true;
deckAdp.setManySelect(true);
if (typeAdp.getSelectPosition() == 1) {
showCopyDeckUtil();
} else {
showAllDeckUtil();
}
deckAdp.addManySelect((DeckFile) adapter.getItem(position));
if (deckAdp.getSelectList().size() == 0) {
clearDeckSelect();
}
deckAdp.notifyItemChanged(position);
return true;
}
});
resultListAdapter.setOnItemSelectListener(new DeckListAdapter.OnItemSelectListener<DeckFile>() {
@Override
public void onItemSelect(int position, DeckFile item) {
binding.rvResultList.setVisibility(View.GONE);
binding.llMainUi.setVisibility(View.VISIBLE);
binding.inputDeckName.getEditableText().clear();
//dismiss();
mDialogListener.onDismiss();
onDeckMenuListener.onDeckSelect(item);
}
});
binding.ivSearchDeckName.setOnClickListener(v -> {
searchDeck();
});
binding.inputDeckName.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
searchDeck();
return true;
}
return false;
});
binding.inputDeckName.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// 输入中监听
if (s.toString().isEmpty()) {
binding.llMainUi.setVisibility(View.VISIBLE);
binding.rvResultList.setVisibility(View.GONE);
binding.ivSearchDeckName.setVisibility(View.GONE);
} else {
binding.ivSearchDeckName.setVisibility(View.VISIBLE);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//输入前监听
}
@Override
public void afterTextChanged(Editable s) {
// 输入后的监听
}
});
binding.llAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List list = new ArrayList();
list.add(getContext().getString(R.string.category_name));
list.add(getContext().getString(R.string.deck_name));
SimpleListAdapter catelistadapter = new SimpleListAdapter(getContext());
catelistadapter.set(list);
DialogPlus dialog = new DialogPlus(getContext());
dialog.setTitle(R.string.new_deck);
dialog.setContentView(R.layout.dialog_edit_and_list);
EditText edit = dialog.bind(R.id.room_name);
edit.setVisibility(View.GONE);//不显示输入框
ListView listView = dialog.bind(R.id.room_list);
listView.setAdapter(catelistadapter);
listView.setOnItemClickListener((a, v, pos, index) -> {
switch ((int) index) {
case 0:
dialog.dismiss();
//if (deckList.size()>=8){
// YGOUtil.show("最多只能有5个自定义分类");
//}
DialogPlus builder = new DialogPlus(getContext());
builder.setTitle(R.string.please_input_category_name);
EditText editText = new EditText(getContext());
editText.setGravity(Gravity.TOP | Gravity.LEFT);
editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setSingleLine();
builder.setContentView(editText);
builder.setOnCloseLinster(DialogInterface::dismiss);
builder.setLeftButtonListener((dlg, s) -> {
CharSequence catename = editText.getText();
if (TextUtils.isEmpty(catename)) {
YGOUtil.showTextToast(getContext().getString(R.string.invalid_category_name));
return;
}
File file = new File(AppsSettings.get().getDeckDir(), catename.toString());
if (IOUtils.createFolder(file)) {
typeList.add(new DeckType(catename.toString(), file.getAbsolutePath()));
typeAdp.notifyItemInserted(typeList.size() - 1);
dlg.dismiss();
} else {
YGOUtil.showTextToast(getContext().getString(R.string.create_new_failed));
}
});
builder.show();
break;
case 1:
dialog.dismiss();
onDeckMenuListener.onDeckNew((typeAdp.getSelectPosition() > 1 ? typeList.get(typeAdp.getSelectPosition()) : typeList.get(2)));//如果选中卡包展示和人机卡组的场合创建卡组则在未分类下创建这个新卡组
break;
}
});
dialog.show();
}
});
binding.llMove.setOnClickListener(view -> {
List<DeckType> otherType = getOtherTypeList();
List<String> cateNameList = getStringTypeList(otherType);
SimpleListAdapter simpleListAdapter = new SimpleListAdapter(getContext());
simpleListAdapter.set(cateNameList);
DialogPlus dialog = new DialogPlus(getContext());
dialog.setTitle(R.string.please_select_target_category);
dialog.setContentView(R.layout.dialog_edit_and_list);
EditText edit = dialog.bind(R.id.room_name);
edit.setVisibility(View.GONE);//不显示输入框
ListView listView = dialog.bind(R.id.room_list);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
listView.setForegroundGravity(View.TEXT_ALIGNMENT_CENTER);
}
listView.setAdapter(simpleListAdapter);
listView.setOnItemClickListener((a, v, pos, index) -> {
String name = simpleListAdapter.getItemById(index);
int position = simpleListAdapter.findItem(name);
DeckType toType = otherType.get(position);
IOUtils.createFolder(new File(toType.getPath()));
List<DeckFile> deckFileList = deckAdp.getSelectList();
for (DeckFile deckFile : deckFileList) {
try {
FileUtils.moveFile(deckFile.getPath(), new File(toType.getPath(), deckFile.getFileName()).getPath());
} catch (IOException e) {
e.printStackTrace();
}
deckList.remove(deckFile);
}
YGOUtil.showTextToast(getContext().getString(R.string.done));
onDeckMenuListener.onDeckMove(deckAdp.getSelectList(), toType);
clearDeckSelect();
dialog.dismiss();
});
dialog.show();
});
binding.llCopy.setOnClickListener(view -> {
List<DeckType> otherType = getOtherTypeList();
List<String> cateNameList = getStringTypeList(otherType);
SimpleListAdapter simpleListAdapter = new SimpleListAdapter(getContext());
simpleListAdapter.set(cateNameList);
DialogPlus dialog = new DialogPlus(getContext());
dialog.setTitle(R.string.please_select_target_category);
dialog.setContentView(R.layout.dialog_edit_and_list);
EditText edit = dialog.bind(R.id.room_name);
edit.setVisibility(View.GONE);//不显示输入框
ListView listView = dialog.bind(R.id.room_list);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
listView.setForegroundGravity(View.TEXT_ALIGNMENT_CENTER);
}
listView.setAdapter(simpleListAdapter);
listView.setOnItemClickListener((a, v, pos, index) -> {
DeckType toType = otherType.get(pos);
IOUtils.createFolder(new File(toType.getPath()));
List<DeckFile> deckFileList = deckAdp.getSelectList();
for (DeckFile deckFile : deckFileList) {
try {
FileUtils.copyFile(deckFile.getPath(), new File(toType.getPath(), deckFile.getFileName()).getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
YGOUtil.showTextToast(getContext().getString(R.string.done));
onDeckMenuListener.onDeckCopy(deckAdp.getSelectList(), toType);
clearDeckSelect();
dialog.dismiss();
});
dialog.show();
});
binding.llDel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (deckAdp.getSelectList().size() == 0) {
YGOUtil.showTextToast(getContext().getString(R.string.no_deck_is_selected));
return;
}
DialogPlus dialogPlus = new DialogPlus(getContext());
dialogPlus.setMessage(R.string.question_delete_deck);
dialogPlus.setLeftButtonText(YGOUtil.s(R.string.delete));
dialogPlus.setRightButtonText(R.string.Cancel);
dialogPlus.setLeftButtonListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
List<DeckFile> selectDeckList = deckAdp.getSelectList();
for (DeckFile deckFile : selectDeckList) {
deckFile.getPathFile().delete();
deckList.remove(deckFile);
}
YGOUtil.showTextToast(getContext().getString(R.string.done));
dialogPlus.dismiss();
onDeckMenuListener.onDeckDel(selectDeckList);
clearDeckSelect();
}
});
dialogPlus.setRightButtonListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialogPlus.dismiss();
}
});
dialogPlus.show();
}
});
//todo
// ygoDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
// @Override
// public void onDismiss(DialogInterface dialog) {
// clearDeckSelect();
// }
// });
// ygoDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
// @Override
// public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
// if (keyCode == KeyEvent.KEYCODE_BACK) {
// if (deckAdp.isManySelect()) {
// clearDeckSelect();
// return true;
// }
//
// }
// return false;
// }
// });
}
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
private void initAdapter() {
String selectDeckPath = AppsSettings.get().getLastDeckPath();
typeList = DeckUtil.getDeckTypeList(getContext());
int typeSelectPosition = 2;//卡组分类选择,默认值为2(未分类卡组)。0代表“卡包展示”,1代表“人机卡组”
int deckSelectPosition = -1;
//根据卡组路径selectDeckPath得到该卡组所属分类
if (!TextUtils.isEmpty(selectDeckPath)) {
File file = new File(selectDeckPath);
if (file.exists()) {
String cateName = file.getParentFile().getName();
String parentName = file.getParentFile().getParentFile().getName();
if (cateName.equals("pack") || cateName.equals("cacheDeck")) {
//卡包
typeSelectPosition = 0;
} else if (cateName.equals("Decks") && parentName.equals(Constants.WINDBOT_PATH)) {
//ai卡组
typeSelectPosition = 1;
} else if (cateName.equals("deck") && parentName.equals(Constants.PREF_DEF_GAME_DIR)) {
//如果是deck并且上一个目录是ygocore的话,保证不会把名字为deck的卡包识别为未分类
typeSelectPosition = 2;
} else {
//其他卡包
for (int i = 3; i < typeList.size(); i++) {
DeckType deckType = typeList.get(i);
if (deckType.getName().equals(cateName)) {
typeSelectPosition = i;
break;
}
}
}
}
}
//根据卡组分类查出属于该分类下的所有卡组
deckList = DeckUtil.getDeckList(typeList.get(typeSelectPosition).getPath());
for (int i = 0; i < typeList.size(); i++) {
if (typeList.get(i).isLocal()) {
allDeckList.addAll(DeckUtil.getDeckList(typeList.get(i).getPath()));//把所有分类里的卡组全部纳入,用于关键词查询目标
}//在线卡组对应的项的path是空字符串
}
if (typeSelectPosition == 0) {//如果选中卡包,判断是否开启了先行卡,是的话加载先行卡
if (AppsSettings.get().isReadExpansions()) {
try {
deckList.addAll(0, DeckUtil.getExpansionsDeckList());//置顶ypk缓存的cacheDeck下的先行卡ydk
} catch (IOException e) {
YGOUtil.showTextToast("额外卡库加载失败,原因为" + e);
}
}
}
resultListAdapter = new DeckListAdapter<DeckFile>(getContext(), resultList, -1);
typeAdp = new TextSelectAdapter<>(typeList, typeSelectPosition);
deckAdp = new DeckListAdapter<>(getContext(), deckList, deckSelectPosition);
}
/**
* 根据et_input_deck_name的当前值,在allDeckList中搜索卡组
*/
private void searchDeck() {
resultList.clear();
binding.inputDeckName.clearFocus();
String keyword = binding.inputDeckName.getText().toString();
if (keyword.isEmpty()) {
binding.llMainUi.setVisibility(View.VISIBLE);
binding.rvResultList.setVisibility(View.GONE);
} else {
resultList.addAll(getResultList(keyword, allDeckList));
binding.rvResultList.setVisibility(View.VISIBLE);
binding.llMainUi.setVisibility(View.GONE);
resultListAdapter.notifyDataSetChanged();
}
}
private String[] getStringType(List<DeckType> deckTypeList) {
String[] types = new String[deckTypeList.size()];
for (int i = 0; i < types.length; i++) {
types[i] = deckTypeList.get(i).getName();
}
return types;
}
/**
* 从deckList中检索包含keyword的卡组
*
* @param keyword
* @param deckList
* @return
*/
private List<DeckFile> getResultList(String keyword, List<DeckFile> deckList) {
List<DeckFile> resultList = new ArrayList<>();
for (int i = 0; i < deckList.size(); i++) {
if (deckList.get(i).getFileName().toLowerCase().contains(keyword.toLowerCase()))
resultList.add(deckList.get(i));
}
return resultList;
}
private List<String> getStringTypeList(List<DeckType> deckTypeList) {
List<String> typeList = new ArrayList<>();
for (int i = 0; i < deckTypeList.size(); i++) {
typeList.add(deckTypeList.get(i).getName());
}
return typeList;
}
//获取可以移动的分类
private List<DeckType> getOtherTypeList() {
List<DeckType> typeList = typeAdp.getData();
List<DeckType> moveTypeList = new ArrayList<>();
DeckType selectType = typeList.get(typeAdp.getSelectPosition());
for (int i = 2; i < typeList.size(); i++) {
DeckType deckType = typeList.get(i);
if (!deckType.getPath().equals(selectType.getPath())) {
moveTypeList.add(deckType);
}
}
return moveTypeList;
}
private final int IMAGE_MOVE = 0;
private final int IMAGE_COPY = 1;
private final int IMAGE_DEL = 2;
//将界面上的iv_move、iv_del、iv_copy等图标颜色恢复,启用其点击事件
private void showAllDeckUtil() {
ImageUtil.reImageColor(IMAGE_MOVE, binding.ivMove);//可用时用原图标色
ImageUtil.reImageColor(IMAGE_DEL, binding.ivDel);
ImageUtil.reImageColor(IMAGE_COPY, binding.ivCopy);
binding.tvDel.setTextColor(YGOUtil.c(R.color.holo_blue_bright));//可用时字色蓝
binding.tvCopy.setTextColor(YGOUtil.c(R.color.holo_blue_bright));
binding.tvMove.setTextColor(YGOUtil.c(R.color.holo_blue_bright));
binding.llDel.setEnabled(true);
binding.llCopy.setEnabled(true);
binding.llMove.setEnabled(true);
}
//将界面上的iv_move、iv_del、iv_copy等图标颜色改为灰色,禁用其点击事件
private void hideAllDeckUtil() {
ImageUtil.setGrayImage(IMAGE_MOVE, binding.ivMove);
ImageUtil.setGrayImage(IMAGE_DEL, binding.ivDel);
ImageUtil.setGrayImage(IMAGE_COPY, binding.ivCopy);
binding.tvDel.setTextColor(YGOUtil.c(R.color.star_rank));//不可用时字色灰
binding.tvCopy.setTextColor(YGOUtil.c(R.color.star_rank));
binding.tvMove.setTextColor(YGOUtil.c(R.color.star_rank));
binding.llDel.setEnabled(false);
binding.llCopy.setEnabled(false);
binding.llMove.setEnabled(false);
}
//将界面上的iv_copy图标颜色恢复,启用其点击事件
private void showCopyDeckUtil() {
ImageUtil.setGrayImage(IMAGE_MOVE, binding.ivMove);
ImageUtil.setGrayImage(IMAGE_DEL, binding.ivDel);
ImageUtil.reImageColor(IMAGE_COPY, binding.ivCopy);
binding.tvDel.setTextColor(YGOUtil.c(R.color.star_rank));
binding.tvCopy.setTextColor(YGOUtil.c(R.color.holo_blue_bright));
binding.tvMove.setTextColor(YGOUtil.c(R.color.star_rank));
binding.llDel.setEnabled(false);
binding.llCopy.setEnabled(true);
binding.llMove.setEnabled(false);
}
//清除选中卡组的记录,隐藏对卡组进行复制、移动、删除的控件
private void clearDeckSelect() {
deckAdp.setManySelect(false);
hideAllDeckUtil();
}
// public void show() {
// if (ygoDialog != null && !ygoDialog.isShowing()) {
// ygoDialog.show();
// }
// }
//
// public void dismiss() {
// if (ygoDialog != null && ygoDialog.isShowing())
// ygoDialog.dismiss();
// }
}
package cn.garymb.ygomobile.deck_square;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.deck_square.api_response.DeckIdResponse;
import cn.garymb.ygomobile.deck_square.api_response.DownloadDeckResponse;
import cn.garymb.ygomobile.deck_square.api_response.GetSquareDeckCondition;
import cn.garymb.ygomobile.deck_square.api_response.LoginRequest;
import cn.garymb.ygomobile.deck_square.api_response.LoginResponse;
import cn.garymb.ygomobile.deck_square.api_response.LoginToken;
import cn.garymb.ygomobile.deck_square.api_response.MyDeckResponse;
import cn.garymb.ygomobile.deck_square.api_response.PushCardJson;
import cn.garymb.ygomobile.deck_square.api_response.PushDeckPublicState;
import cn.garymb.ygomobile.deck_square.api_response.PushDeckResponse;
import cn.garymb.ygomobile.deck_square.api_response.SquareDeckResponse;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.OkhttpUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class DeckSquareApiUtil {
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
public static boolean needLogin() {
String serverToken = SharedPreferenceUtil.getServerToken();
Integer serverUserId = SharedPreferenceUtil.getServerUserId();
if (serverToken == null || serverUserId == -1) {
return true;
}
return false;
}
/**
* 如果未登录(不存在token),显示toast提示用户。如果已登录,返回token
*
* @return
*/
public static LoginToken getLoginData() {
String serverToken = SharedPreferenceUtil.getServerToken();
Integer serverUserId = SharedPreferenceUtil.getServerUserId();
if (serverToken == null || serverUserId == -1) {
YGOUtil.showTextToast("Please login first!");
return null;
}
return new LoginToken(serverUserId, serverToken);
}
public static SquareDeckResponse getSquareDecks(GetSquareDeckCondition condition) throws IOException {
SquareDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/list";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("page", condition.getPage());
paramMap.put("size", condition.getSize());
paramMap.put("keyWord", condition.getKeyWord());
paramMap.put("sortLike", condition.getSortLike());
paramMap.put("sortRank", condition.getSortRank());
paramMap.put("contributor", condition.getContributor());
Response response = OkhttpUtil.synchronousGet(url, paramMap, headers);
String responseBodyString = response.body().string();
Gson gson = new Gson();
result = gson.fromJson(responseBodyString, SquareDeckResponse.class);
return result;
}
/**
* 阻塞方法
* 获取指定用户的卡组列表(只能用于获取登录用户本人的卡组)
*
* @param loginToken
* @return
*/
public static MyDeckResponse getUserDecks(LoginToken loginToken) throws IOException {
if (loginToken == null) {
YGOUtil.showTextToast("Login first", Toast.LENGTH_LONG);
return null;
}
MyDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/sync/" + loginToken.getUserId() + "/nodel";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("token", loginToken.getServerToken());
Response response = OkhttpUtil.synchronousGet(url, null, headers);
String responseBodyString = response.body().string();
Gson gson = new Gson();
result = gson.fromJson(responseBodyString, MyDeckResponse.class);
if (result.code == 20) {//用户身份验证失败
YGOUtil.showTextToast("Login first", Toast.LENGTH_LONG);
}
return result;
}
/**
* 阻塞方法
* 根据卡组ID查询一个卡组,不需要传入token,可以查询已登录用户或其它未登录用户的卡组
*
* @param deckId
* @return
*/
public static DownloadDeckResponse getDeckById(String deckId) throws IOException {
DownloadDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/" + deckId;
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
Response response = OkhttpUtil.synchronousGet(url, null, headers);
String responseBodyString = response.body().string();
Gson gson = new Gson();
// Convert JSON to Java object using Gson
result = gson.fromJson(responseBodyString, DownloadDeckResponse.class);
LogUtil.i(TAG, responseBodyString);
return result;
}
/**
* 阻塞方法,用于推送新卡组。首先从服务器请求一个新的卡组id,之后将卡组上传到服务器
* 先同步推送,之后异步推送。首先调用服务端api获取卡组id,之后将卡组id设置到ydk中,之后调用服务器api将卡组上传
*
* @param deckfile
* @param loginToken
*/
public static PushDeckResponse requestIdAndPushDeck(DeckFile deckFile, LoginToken loginToken) throws IOException {
if (loginToken == null) {
return null;
}
String getDeckIdUrl = "http://rarnu.xyz:38383/api/mdpro3/deck/deckId";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
DeckIdResponse deckIdResult = null;
{
Response response = OkhttpUtil.synchronousGet(getDeckIdUrl, null, headers);
String responseBodyString = response.body().string();
// Convert JSON to Java object using Gson
deckIdResult = gson.fromJson(responseBodyString, DeckIdResponse.class);
LogUtil.i(TAG, "deck id result:" + deckIdResult.toString());
}
if (deckIdResult == null) {
return null;
}
String deckId = deckIdResult.getDeckId();//从服务器获取
if (deckId == null) {
return null;
}
return pushDeck(deckFile, loginToken, deckId);
}
/**
* 将对应于deckId、deckName的卡组内容json推送到服务器。
* 如果在服务器上不存在deckId、deckName对应的记录,则创建新卡组
* 如果在服务器存在deckId相同的记录,则更新卡组,deckName会覆盖服务器上的卡组名
* 如果在服务器存在deckName相同、deckId不同的记录,则更新失败
*
* @param deckfile
* @param loginToken
* @param deckId
* @return
* @throws IOException
*/
private static PushDeckResponse pushDeck(DeckFile deckfile, LoginToken loginToken, String deckId) throws IOException {
String deckContent = DeckSquareFileUtil.setDeckId(deckfile.getPath(), loginToken.getUserId(), deckId);
PushDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/sync/single";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
PushCardJson pushCardJson = new PushCardJson();
pushCardJson.setDeckContributor(loginToken.getUserId().toString());
pushCardJson.setUserId(loginToken.getUserId());
PushCardJson.DeckData deckData = new PushCardJson.DeckData();
deckData.setDeckId(deckId);
deckData.setDeckName(deckfile.getName());
deckData.setDeckCoverCard1(deckfile.getFirstCode());
deckData.setDelete(false);
deckData.setDeckYdk(deckContent);
pushCardJson.setDeck(deckData);
String json = gson.toJson(pushCardJson);
Response response = OkhttpUtil.postJson(url, json, headers, 1000);
String responseBodyString = response.body().string();
result = gson.fromJson(responseBodyString, PushDeckResponse.class);
LogUtil.i(TAG, "push deck response:" + responseBodyString);
return result;
}
/**
* 阻塞方法,给卡组点赞
*
* @param deckId
*/
public static BasicResponse likeDeck(String deckId) throws IOException {
BasicResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/like/" + deckId;
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
Response response = OkhttpUtil.postJson(url, null, headers, 1000);
String responseBodyString = response.body().string();
Gson gson = new Gson();
result = gson.fromJson(responseBodyString, BasicResponse.class);
LogUtil.i(TAG, responseBodyString);
return result;
}
/**
* 阻塞方法,给卡组点赞
*
* @param deckId
*/
public static BasicResponse setDeckPublic(String deckId, LoginToken loginToken, boolean publicState) throws IOException {
BasicResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/public";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
PushDeckPublicState pushData = new PushDeckPublicState();
pushData.setPublic(publicState);
pushData.setDeckId(deckId);
pushData.setUserId(loginToken.getUserId());
String json = gson.toJson(pushData);
Response response = OkhttpUtil.postJson(url, json, headers, 1000);
String responseBodyString = response.body().string();
result = gson.fromJson(responseBodyString, BasicResponse.class);
LogUtil.i(TAG, responseBodyString);
return result;
}
public static LoginResponse login(String username, String password) throws IOException {
LoginResponse result = null;
String url = "https://sapi.moecube.com:444/accounts/signin";
// Create request body using Gson
Gson gson = new Gson();
// userId = 107630627;
// password = "Qbz95qbz96";
LoginRequest loginRequest = new LoginRequest(username, password);
String json = gson.toJson(loginRequest);//"{\"id\":1,\"name\":\"John\"}";
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
Response response = okHttpClient.newCall(request).execute();
// Read the response body
String responseBody = response.body().string();
LogUtil.i(TAG, "Login Response body: " + responseBody);
// Process the response
if (response.isSuccessful()) {
// Successful response (code 200-299)
// Parse the JSON response if needed
result = gson.fromJson(responseBody, LoginResponse.class);
LogUtil.i(TAG, "Login response: " + result);
} else {
// Error response
LogUtil.e(TAG, "Request failed: " + responseBody);
}
return result;
}
public static PushDeckResponse deleteDeck(String deckId, LoginToken loginToken) throws IOException {
PushDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/sync/single";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
PushCardJson pushCardJson = new PushCardJson();
PushCardJson.DeckData deckData = new PushCardJson.DeckData();
deckData.setDeckId(deckId);
deckData.setDelete(true);
pushCardJson.setDeck(deckData);
pushCardJson.setUserId(loginToken.getUserId());
String json = gson.toJson(pushCardJson);
Response response = OkhttpUtil.postJson(url, json, headers, 1000);
String responseBodyString = response.body().string();
// Convert JSON to Java object using Gson
result = gson.fromJson(responseBodyString, PushDeckResponse.class);
LogUtil.i(TAG, "push deck response:" + responseBodyString);
return result;
}
/**
* 管理员使用,删除某卡组(听说可以删除别人的卡组,没试过)
* 该api没有权限校验,慎用
*/
public static void adminDelete(String deckId) {
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/" + deckId;
}
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import cn.garymb.ygomobile.AppsSettings;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.utils.IOUtils;
import cn.garymb.ygomobile.utils.LogUtil;
import ocgcore.CardManager;
import ocgcore.DataManager;
import ocgcore.data.Card;
public class DeckSquareFileUtil {
//
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
// public static List<String> readLastLinesWithNIO(File file, int numLines) {
// try {
// List<String> lines = Files.readAllLines(file);
// int fromIndex = Math.max(0, lines.size() - numLines);
// return lines.subList(fromIndex, lines.size());
// } catch (IOException e) {
// e.printStackTrace();
// return Collections.emptyList();
// }
// }
//
// 使用示例
// Path logPath = Paths.get(context.getFilesDir().getAbsolutePath(), "log.txt");
// List<String> lastTwo = readLastLinesWithNIO(logPath, 2);
//读取file指定的ydk文件,返回其内包含的deckId。如果不包含deckId,返回null
public static String getId(File file) {
String deckId = null;
Integer userId = null;
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
InputStreamReader in = null;
in = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(in);
String line = null;
while ((line = reader.readLine()) != null) {
LogUtil.i(TAG, line);
if (line.startsWith("###")) {//注意,先判断###,后判断##。因为###会包括##的情况
try {
String data = line.replace("#", "");
if (!data.isEmpty()) {
userId = Integer.parseInt(data);
}
// userId = Integer.parseInt(line.replaceAll("###", ""));
} catch (NumberFormatException e) {
LogUtil.e(TAG, "integer" + line + "parse error" + e.toString());
}
} else if (line.startsWith("##")) {
line = line.replace("#", "");
deckId = line;
}
}
} catch (IOException e) {
LogUtil.e(TAG, "read 1", e);
} finally {
IOUtils.close(inputStream);
}
return deckId;
}
//查询卡组目录下的所有ydk文件,返回File[]
public static File[] getAllYdk() {
File dir = new File(AppsSettings.get().getResourcePath(), Constants.CORE_DECK_PATH);
File[] files = dir.listFiles((file, s) -> s.toLowerCase(Locale.US).endsWith(Constants.YDK_FILE_EX));
return files;
}
//读取卡组目录下的所有ydk文件,解析ydk文件(包括从ydk文件内容中读取deckId),生成List<MyDeckItem>解析结果
public static List<MyDeckItem> getMyDeckItem() {
List<MyDeckItem> result = new ArrayList<>();
File[] files = getAllYdk();
for (File file : files) {
String deckId = getId(file);
MyDeckItem item = new MyDeckItem();
item.deckName = file.getName();
item.setDeckSouce(0);
item.setDeckPath(file.getPath());
if (deckId != null) {
item.deckId = deckId;
item.idUploaded = 2;
} else {
item.idUploaded = 0;
}
result.add(item);
}
return result;
}
// 读取deckPath对应的卡组文件到string,将卡组id、用户id设置到string中
//注意,不更改ydk文件内容
//下载卡组后,保存卡组之前
//上传卡组前,对于未存在卡组id的卡组,自动填入新的卡组id、用户id
public static String setDeckId(String deckPath, Integer userId, String deckId) {
StringBuilder contentBuilder = new StringBuilder();
boolean userIdFlag = false;
boolean deckIdFlag = false;
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(deckPath);
InputStreamReader in = null;
in = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(in);
String line = null;
while ((line = reader.readLine()) != null) {
/* 如果文件中已经存在deckId,则将其替换 */
if (line.contains("##") && !line.contains("###")) {
deckIdFlag = true;
line = "##" + deckId;
} else if (line.contains("###")) {//存在userId,将其替换
userIdFlag = true;
line = "###" + userId;
}
contentBuilder.append(line);
contentBuilder.append('\n'); // Add line break
}
} catch (Exception e) {
LogUtil.e(TAG, "read 1", e);
} finally {
IOUtils.close(inputStream);
}
if (!userIdFlag) {//原始ydk中不存在userId,添加userId行
contentBuilder.append("\n");
contentBuilder.append("##" + userId);
}
if (!deckIdFlag) {//原始ydk中不存在deckId,添加deckId行
contentBuilder.append("\n");
contentBuilder.append("###" + deckId);
}
String content = contentBuilder.toString();
return content;
}
public static boolean saveFileToPath(String path, String fileName, String content) {
try {
// Create file object
File file = new File(path, fileName);
// Create file output stream
FileOutputStream fos = new FileOutputStream(file);
// Write content
fos.write(content.getBytes());
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
public static List<Card> convertTempDeckYdk(String deckYdk) {
String[] deckLine = deckYdk.split("\r\n|\r|\n");
List<Integer> tempDeck = new ArrayList<>();//存储当前卡组的基本内容
List<Card> cardList = new ArrayList<>();
CardManager mCardManager = DataManager.get().getCardManager();
for (String line : deckLine) {
if (!line.contains("#") && !line.contains("!")) {
//line.to
try {
Integer cardId = Integer.parseInt(line);
tempDeck.add(cardId);
Card card = mCardManager.getCard(cardId);
cardList.add(card);
} catch (NumberFormatException e) {
LogUtil.i(TAG, "cannot parse Interget" + line + e.getMessage());
}
}
}
return cardList;
}
}
package cn.garymb.ygomobile.deck_square;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.deck_square.api_response.OnlineDeckDetail;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.lite.databinding.FragmentDeckSquareBinding;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
public class DeckSquareFragment extends Fragment {
private FragmentDeckSquareBinding binding;
private DeckSquareListAdapter deckSquareListAdapter;
private YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener;//通知外部调用方,(如调用本fragment的activity)
private YGODeckDialogUtil.OnDeckDialogListener mDialogListener;
private String keyWord;
private Boolean sortLike;
private Boolean sortRank;
private String contributor;
public DeckSquareFragment(YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener, YGODeckDialogUtil.OnDeckDialogListener mDialogListener) {
this.onDeckMenuListener = onDeckMenuListener;
this.mDialogListener = mDialogListener;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentDeckSquareBinding.inflate(inflater, container, false);
deckSquareListAdapter = new DeckSquareListAdapter(R.layout.item_deck_info);
GridLayoutManager linearLayoutManager = new GridLayoutManager(getContext(), 3);
binding.listDeckInfo.setLayoutManager(linearLayoutManager);
binding.listDeckInfo.setAdapter(deckSquareListAdapter);
deckSquareListAdapter.loadData();
binding.etGoToPage.setText("1");
sortLike = false;
Drawable icon_like = getContext().getDrawable(R.drawable.ic_recommendation_order);
Drawable icon_new = getContext().getDrawable(R.drawable.upload_time);
binding.refreshData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//根据按钮使用的图标决定是否是按赞排序还是按上传时间排序, 切换成另一种图标
if (sortLike == false) {
sortLike = true;
binding.tvSortMode.setText(R.string.sort_by_thumb);//当按时间顺序时,点击应切换为按点赞顺序
binding.refreshData.setImageDrawable(icon_new);//因为点击后会变成按点赞顺序,就需要图标显示为按时间顺序,告诉用户点它可变回时间顺序
} else {
sortLike = false;
binding.tvSortMode.setText(R.string.sort_by_time);//当按点赞顺序时,点击应切换为按时间顺序
binding.refreshData.setImageDrawable(icon_like);//因为点击后会变成按时间顺序,就需要图标切换为按点赞顺序,告诉用户点它可变成点赞顺序
}
int targetPage = 1;
try {
targetPage = Integer.parseInt(binding.etGoToPage.getText().toString());
} catch (NumberFormatException e) {
}
deckSquareListAdapter.loadData(targetPage, 30, "", sortLike, false, "");
}
});
// 设置页码跳转监听
binding.etGoToPage.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
int targetPage = 0;
try {
targetPage = Integer.parseInt(v.getText().toString());
} catch (NumberFormatException e) {
}
binding.etGoToPage.setText(Integer.toString(targetPage));
deckSquareListAdapter.loadData(targetPage, 30, "", sortLike, false, "");
binding.listDeckInfo.scrollToPosition(0);
return true;
}
return false;
});
binding.nextPageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int targetPage = 0;
try {
targetPage = Integer.parseInt(binding.etGoToPage.getText().toString());
} catch (NumberFormatException e) {
}
int newPage = targetPage + 1;
deckSquareListAdapter.loadData(newPage, 30, "", sortLike, false, "");
binding.etGoToPage.setText(Integer.toString(newPage));
binding.listDeckInfo.scrollToPosition(0);
}
});
binding.formerPageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int targetPage = 0;
try {
targetPage = Integer.parseInt(binding.etGoToPage.getText().toString());
} catch (NumberFormatException e) {
}
int newPage = targetPage - 1;
if (newPage < 1) {
newPage = 1;
}
deckSquareListAdapter.loadData(newPage, 30, "", sortLike, false, "");
binding.etGoToPage.setText(Integer.toString(newPage));
binding.listDeckInfo.scrollToPosition(0);
}
});
//查询卡组名称
binding.etDeckSquareInputDeckName.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
Editable contributorName = binding.etInputContributorName.getText();
if (contributorName != null) contributorName.clear();
keyWord = v.getText().toString();
binding.etGoToPage.setText("1");
binding.etGoToPage.setEnabled(false);
deckSquareListAdapter.loadData(1, 1000, keyWord, true, false, "");
binding.listDeckInfo.scrollToPosition(0);
return true;
}
return false;
});
// 添加文本变化监听器
binding.etDeckSquareInputDeckName.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().isEmpty())
binding.btnClearDeckName.setVisibility(View.GONE);
else
binding.btnClearDeckName.setVisibility(View.VISIBLE);
}
@Override
public void afterTextChanged(Editable s) {
// 当输入框内容为空时
if (s.toString().isEmpty()) {
binding.btnClearDeckName.setVisibility(View.GONE);
// 恢复底部按钮可用状态
binding.formerPageBtn.setEnabled(true);
binding.formerPageBtn.clearColorFilter();
binding.nextPageBtn.setEnabled(true);
binding.nextPageBtn.clearColorFilter();
binding.refreshData.setEnabled(true);
binding.refreshData.clearColorFilter();
// 重置页码为1
binding.etGoToPage.setText("1");
binding.etGoToPage.setEnabled(true);
deckSquareListAdapter.loadData();
binding.listDeckInfo.scrollToPosition(0);
} else {
// 底部按钮不可用状态
binding.formerPageBtn.setEnabled(false);
binding.formerPageBtn.setColorFilter(R.color.navigator_dir_text_color);
binding.nextPageBtn.setEnabled(false);
binding.nextPageBtn.setColorFilter(R.color.navigator_dir_text_color);
binding.refreshData.setEnabled(false);
binding.refreshData.setColorFilter(R.color.navigator_dir_text_color);
}
}
});
//添加贡献者查询
binding.etInputContributorName.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
//清除卡组名称输入的内容
Editable deckName = binding.etDeckSquareInputDeckName.getText();
if (deckName != null) deckName.clear();
//获取输入内容
contributor = v.getText().toString();
binding.etGoToPage.setText("1");
binding.etGoToPage.setEnabled(false);
deckSquareListAdapter.loadData(1, 1000, "", true, false, contributor);
binding.listDeckInfo.scrollToPosition(0);
return true;
}
return false;
});
// 添加文本变化监听器
binding.etInputContributorName.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().isEmpty()) {
binding.btnClearContributorName.setVisibility(View.GONE);
} else {
binding.btnClearContributorName.setVisibility(View.VISIBLE);
}
}
@Override
public void afterTextChanged(Editable s) {
// 当输入框内容为空时
if (s.toString().isEmpty()) {
binding.btnClearDeckName.setVisibility(View.GONE);
// 恢复底部按钮可用状态
binding.formerPageBtn.setEnabled(true);
binding.formerPageBtn.clearColorFilter();
binding.nextPageBtn.setEnabled(true);
binding.nextPageBtn.clearColorFilter();
binding.refreshData.setEnabled(true);
binding.refreshData.clearColorFilter();
// 重置页码为1
binding.etGoToPage.setText("1");
binding.etGoToPage.setEnabled(true);
deckSquareListAdapter.loadData();
binding.listDeckInfo.scrollToPosition(0);
} else {
// 底部按钮不可用状态
binding.formerPageBtn.setEnabled(false);
binding.formerPageBtn.setColorFilter(R.color.navigator_dir_text_color);
binding.nextPageBtn.setEnabled(false);
binding.nextPageBtn.setColorFilter(R.color.navigator_dir_text_color);
binding.refreshData.setEnabled(false);
binding.refreshData.setColorFilter(R.color.navigator_dir_text_color);
}
}
});
//设置清空按钮点击清除输入内容
binding.btnClearDeckName.setOnClickListener(view -> binding.etDeckSquareInputDeckName.getText().clear());
binding.btnClearContributorName.setOnClickListener(view -> binding.etInputContributorName.getText().clear());
// Set click listener in your adapter
deckSquareListAdapter.setOnItemClickListener((adapter, view, position) -> {
OnlineDeckDetail item = (OnlineDeckDetail) adapter.getItem(position);
//调用
mDialogListener.onDismiss();
DeckFile deckFile = new DeckFile(item.getDeckId(), DeckType.ServerType.SQUARE_DECK);
onDeckMenuListener.onDeckSelect(deckFile);
});
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square;
import android.util.Log;
import android.widget.ImageView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import java.util.List;
import cn.garymb.ygomobile.deck_square.api_response.GetSquareDeckCondition;
import cn.garymb.ygomobile.deck_square.api_response.OnlineDeckDetail;
import cn.garymb.ygomobile.deck_square.api_response.SquareDeckResponse;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil;
//提供recyclerview的数据
public class DeckSquareListAdapter extends BaseQuickAdapter<OnlineDeckDetail, BaseViewHolder> {
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private ImageLoader imageLoader;
public DeckSquareListAdapter(int layoutResId) {
super(layoutResId);
imageLoader = new ImageLoader();
}
public void loadData() {
loadData(1, 30, "", false, false, "");
}
public void loadData(Integer page, Integer size, String keyWord, Boolean sortLike, Boolean sortRank, String contributor) {
final DialogPlus dialog_read_ex = DialogPlus.show(getContext(), null, getContext().getString(R.string.fetch_online_deck));
VUiKit.defer().when(() -> {
SquareDeckResponse result = DeckSquareApiUtil.getSquareDecks(new GetSquareDeckCondition(page, size, keyWord, sortLike, sortRank, contributor));
if (result == null) {
return null;
} else {
return result.getData().getRecords();
}
}).fail((e) -> {
Log.e(TAG, e + "");
if (dialog_read_ex.isShowing()) {//关闭异常
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
LogUtil.i(TAG, "Get square deck fail");
}).done((result) -> {
if (result != null) {
LogUtil.i(TAG, "Get square deck success");
getData().clear();
addData(result);
notifyDataSetChanged();
}
if (dialog_read_ex.isShowing()) {
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
});
}
@Override
protected void convert(BaseViewHolder helper, OnlineDeckDetail item) {
helper.setText(R.id.deck_info_name, item.getDeckName());
helper.setText(R.id.deck_contributor, item.getDeckContributor());
helper.setText(R.id.deck_last_date, item.getLastDate());
helper.setText(R.id.like_count, item.getDeckLike()+"");
ImageView cardImage = helper.getView(R.id.deck_info_image);
long code = item.getDeckCoverCard1();
LogUtil.i(TAG, code + " " + item.getDeckName());
if (code != 0) {
imageLoader.bindImage(cardImage, code, null, ImageLoader.Type.small);
} else {
imageLoader.bindImage(cardImage, -1, null, ImageLoader.Type.small);
}
// ImageView imageview = helper.getView(R.id.ex_card_image);
//the function cn.garymb.ygomobile.loader.ImageLoader.bindT(...)
//cn.garymb.ygomobile.loader.ImageLoader.setDefaults(...)
//is a private function,so I copied the content of it to here
/* 如果查不到版本号,则不显示图片 */
/* 如果能查到版本号,则显示图片,利用glide的signature,将版本号和url作为signature,由glide判断是否使用缓存 */
}
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import cn.garymb.ygomobile.deck_square.api_response.LoginResponse;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.lite.databinding.FragmentDeckSquareMyDeckBinding;
import cn.garymb.ygomobile.ui.activities.WebActivity;
import cn.garymb.ygomobile.ui.mycard.MyCard;
import cn.garymb.ygomobile.ui.mycard.bean.McUser;
import cn.garymb.ygomobile.ui.mycard.mcchat.ChatMessage;
import cn.garymb.ygomobile.ui.mycard.mcchat.management.UserManagement;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
import cn.garymb.ygomobile.utils.glide.GlideCompat;
//打开页面后,先扫描本地的卡组,读取其是否包含deckId,是的话代表平台上可能有
//之后读取平台上的卡组,与本地卡组列表做比较。
public class DeckSquareMyDeckFragment extends Fragment {
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private FragmentDeckSquareMyDeckBinding binding;
private MyDeckListAdapter deckListAdapter;
private String keyWord;
private YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener;//通知外部调用方,(如调用本fragment的activity)
private YGODeckDialogUtil.OnDeckDialogListener mDialogListener;
public DeckSquareMyDeckFragment(YGODeckDialogUtil.OnDeckMenuListener onDeckMenuListener, YGODeckDialogUtil.OnDeckDialogListener mDialogListener) {
this.onDeckMenuListener = onDeckMenuListener;
this.mDialogListener = mDialogListener;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentDeckSquareMyDeckBinding.inflate(inflater, container, false);
if (SharedPreferenceUtil.getServerToken() == null) {
binding.llMainUi.setVisibility(View.GONE);
binding.llDialogLogin.setVisibility(View.VISIBLE);
} else {
binding.llMainUi.setVisibility(View.VISIBLE);
binding.llDialogLogin.setVisibility(View.GONE);
binding.tvMycardUserName.setText(SharedPreferenceUtil.getMyCardUserName());
GlideCompat.with(getActivity()).load(ChatMessage.getAvatarUrl(SharedPreferenceUtil.getMyCardUserName())).into(binding.myDeckAvatar);//刷新头像图片
}
binding.btnLogin.setOnClickListener(v -> attemptLogin());
binding.btnRegister.setOnClickListener(v -> WebActivity.open(getContext(), getString(R.string.register), MyCard.URL_MC_SIGN_UP));
deckListAdapter = new MyDeckListAdapter(R.layout.item_my_deck);
GridLayoutManager linearLayoutManager = new GridLayoutManager(getContext(), 3);
binding.listMyDeckInfo.setLayoutManager(linearLayoutManager);
binding.listMyDeckInfo.setAdapter(deckListAdapter);
deckListAdapter.loadData();
//其实仅仅是清除掉本机的token
binding.llMcLogout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DialogPlus dialogPlus = new DialogPlus(getContext());
dialogPlus.setMessage(R.string.logout_mycard);
dialogPlus.setMessageGravity(Gravity.CENTER);
dialogPlus.setLeftButtonListener((dlg, s) -> {
SharedPreferenceUtil.deleteServerToken();
binding.llMainUi.setVisibility(View.GONE);
binding.llDialogLogin.setVisibility(View.VISIBLE);
dialogPlus.dismiss();
});
dialogPlus.setRightButtonListener((dlg, s) -> {
dialogPlus.dismiss();
});
dialogPlus.show();
}
});
//查询卡组名称
binding.etMyDeckInputDeckName.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
keyWord = v.getText().toString();
//直接过滤列表中的item名称,而不是像卡组广场那样重新查询
deckListAdapter.filter(keyWord);
return true;
}
return false;
});
// 添加文本变化监听器
binding.etMyDeckInputDeckName.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
deckListAdapter.filter(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
// 当输入框内容为空时
if (s.toString().isEmpty()) {
deckListAdapter.loadData();//悄悄留一个刷新我的云备份的方式,方便
} else {
deckListAdapter.filter(s.toString());
}
}
});
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
private void attemptLogin() {
String username = binding.etUsername.getText().toString().trim();
String password = binding.etPassword.getText().toString().trim();
if (username.isEmpty()) {
binding.tvAccountWarning.setVisibility(View.VISIBLE);
return;
} else {
binding.tvAccountWarning.setVisibility(View.GONE);
}
if (password.isEmpty()) {
binding.tvPwdWarning.setVisibility(View.VISIBLE);
return;
} else {
binding.tvPwdWarning.setVisibility(View.GONE);
}
binding.progressBar.setVisibility(View.VISIBLE);
binding.btnLogin.setEnabled(false);
VUiKit.defer().when(() -> {
LoginResponse result = DeckSquareApiUtil.login(username, password);//执行登录
SharedPreferenceUtil.setServerToken(result.token);
SharedPreferenceUtil.setServerUserId(result.user.id);
SharedPreferenceUtil.setMyCardUserName(result.user.username);
return result;
}).fail((e) -> {
YGOUtil.showTextToast(R.string.logining_failed);
binding.llMainUi.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.GONE);
binding.btnLogin.setEnabled(true);
}).done((result) -> {
if (result != null) {
binding.llMainUi.setVisibility(View.VISIBLE);
deckListAdapter.loadData();
binding.llDialogLogin.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.GONE);
binding.btnLogin.setEnabled(true);
//储存信息
String userName = result.user.username;
binding.tvMycardUserName.setText(userName);
McUser mcUser = new McUser();
mcUser.setUsername(userName);
mcUser.setExternal_id(result.user.id);
mcUser.setAvatar_url(ChatMessage.getAvatarUrl(userName));
mcUser.setToken(result.token);
GlideCompat.with(getActivity()).load(mcUser.getAvatar_url()).into(binding.myDeckAvatar);//刷新头像图片
UserManagement.getDx().setMcUser(mcUser);
YGOUtil.showTextToast(R.string.login_succeed);
} else {
YGOUtil.showTextToast(R.string.logining_failed);
binding.llMainUi.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.GONE);
binding.btnLogin.setEnabled(true);
}
});
}
}
package cn.garymb.ygomobile.deck_square;
public class MyDeckItem {
//0代表未推到服务器,3代表包含deckId,1代表服务器存在可下载到本地,2代表已同步
public int idUploaded;
public int userId;
public String deckName;
public String deckId;
public String updateDate;
public int deckSouce;//卡组来源,0代表来自本地,1代表来自服务器
public String deckPath;//本地卡组时,存储卡组路径
public int deckCoverCard1;
public Boolean isPublic;
public int getIdUploaded() {
return idUploaded;
}
public void setIdUploaded(int idUploaded) {
this.idUploaded = idUploaded;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getDeckName() {
return deckName;
}
public void setDeckName(String deckName) {
this.deckName = deckName;
}
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
public String getUpdateDate() {
return updateDate;
}
public void setUpdateDate(String updateDate) {
this.updateDate = updateDate;
}
public int getDeckSouce() {
return deckSouce;
}
public void setDeckSouce(int deckSouce) {
this.deckSouce = deckSouce;
}
public int getDeckCoverCard1() {
return deckCoverCard1;
}
public void setDeckCoverCard1(int deckCoverCard1) {
this.deckCoverCard1 = deckCoverCard1;
}
public String getDeckPath() {
return deckPath;
}
public void setDeckPath(String deckPath) {
this.deckPath = deckPath;
}
public Boolean getPublic() {
return isPublic;
}
public void setPublic(Boolean aPublic) {
isPublic = aPublic;
}
@Override
public String toString() {
return "MyDeckItem{" +
"idUploaded=" + idUploaded +
", userId=" + userId +
", deckName='" + deckName + '\'' +
", deckId='" + deckId + '\'' +
", updateDate='" + updateDate + '\'' +
", deckSouce=" + deckSouce +
", deckPath='" + deckPath + '\'' +
", deckCoverCard1=" + deckCoverCard1 +
", isPublic=" + isPublic +
'}';
}
}
package cn.garymb.ygomobile.deck_square;
import android.util.Log;
import android.widget.ImageView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import java.util.ArrayList;
import java.util.List;
import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.deck_square.api_response.LoginToken;
import cn.garymb.ygomobile.deck_square.api_response.MyDeckResponse;
import cn.garymb.ygomobile.deck_square.api_response.MyOnlineDeckDetail;
import cn.garymb.ygomobile.deck_square.api_response.PushDeckResponse;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
//提供“我的”卡组数据,打开后先从sharePreference查询,没有则从服务器查询,然后缓存到sharePreference
public class MyDeckListAdapter extends BaseQuickAdapter<MyDeckItem, BaseViewHolder> {
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private ImageLoader imageLoader;
private List<MyDeckItem> originalData; // 保存原始数据
public MyDeckListAdapter(int layoutResId) {
super(layoutResId);
originalData = new ArrayList<>();
imageLoader = new ImageLoader();
}
public void loadData() {
List<MyDeckItem> myOnlineDecks = new ArrayList<>();
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
return;
}
final DialogPlus dialog_read_ex = DialogPlus.show(getContext(), null, getContext().getString(R.string.fetch_online_deck));
VUiKit.defer().when(() -> {
MyDeckResponse result = DeckSquareApiUtil.getUserDecks(loginToken);
if (result == null) {
return null;
} else {
return result.getData();
}
}).fail((e) -> {
Log.e(TAG, e + "");
if (dialog_read_ex.isShowing()) {//关闭异常
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
LogUtil.i(TAG, "load mycard from server fail");
}).done((serverDecks) -> {
if (serverDecks != null) {//将服务端的卡组也放到LocalDecks中
for (MyOnlineDeckDetail detail : serverDecks) {
MyDeckItem item = new MyDeckItem();
item.setDeckName(detail.getDeckName());
item.setDeckSouce(1);
item.setDeckId(detail.getDeckId());
item.setUserId(detail.getUserId());
item.setDeckCoverCard1(detail.getDeckCoverCard1());
item.setUpdateDate(detail.getDeckUpdateDate());
item.setPublic(detail.isPublic());
myOnlineDecks.add(item);
}
}
LogUtil.i(TAG, "load mycard from server done");
originalData.clear();
originalData.addAll(myOnlineDecks); // 保存原始数据
getData().clear();
addData(myOnlineDecks);
notifyDataSetChanged();
if (dialog_read_ex.isShowing()) {
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
});
}
// 筛选函数
public void filter(String keyword) {
List<MyDeckItem> filteredList = new ArrayList<>();
if (keyword.isEmpty()) {
// 如果关键词为空,则显示所有数据
filteredList.addAll(originalData);
} else {
// 遍历原始数据,筛选出包含关键词的item
for (MyDeckItem item : originalData) {
if (item.getDeckName().contains(keyword)) {
filteredList.add(item);
}
}
}
// 更新显示的数据
getData().clear();
addData(filteredList);
notifyDataSetChanged();
}
private void deleteMyDeckOnLine(MyDeckItem item) {
if (item != null) {
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
return;
}
VUiKit.defer().when(() -> {
PushDeckResponse result = DeckSquareApiUtil.deleteDeck(item.getDeckId(), loginToken);
return result;
}).fail(e -> {
LogUtil.i(TAG, "square deck detail fail" + e.getMessage());
}).done(data -> {
if (data.isData()) {
remove(item);
} else {
YGOUtil.showTextToast("delete fail " + data.getMessage());
}
});
}
}
/**
* 注意,更新卡组状态要过很久才生效(实测延迟偶尔达5s)
* @param item
*/
private void changeDeckPublicState(MyDeckItem item) {
if (item != null) {
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
return;
}
VUiKit.defer().when(() -> {
BasicResponse result = DeckSquareApiUtil.setDeckPublic(item.getDeckId(), loginToken, !item.getPublic());
return result;
}).fail(e -> {
LogUtil.i(TAG, "square deck detail fail" + e.getMessage());
}).done(data -> {
});
}
}
@Override
protected void convert(BaseViewHolder helper, MyDeckItem item) {
helper.setText(R.id.my_deck_name, item.getDeckName());
helper.setText(R.id.deck_update_date, item.getUpdateDate());
ImageView cardImage = helper.getView(R.id.deck_info_image);
long code = item.getDeckCoverCard1();
if (item.getPublic()) {
helper.setText(R.id.change_show_or_hide, R.string.in_public);
helper.getView(R.id.show_on_deck_square).setBackgroundResource(R.drawable.baseline_remove_red_eye_24);
helper.getView(R.id.ll_switch_show).setBackgroundResource(R.drawable.button_radius_red);
} else {
helper.setText(R.id.change_show_or_hide, R.string.in_personal_use);
helper.getView(R.id.show_on_deck_square).setBackgroundResource(R.drawable.closed_eyes_24);
helper.getView(R.id.ll_switch_show).setBackgroundResource(R.drawable.button_radius_n);
}
LogUtil.i(TAG, code + " " + item.getDeckName());
if (code != 0) {
imageLoader.bindImage(cardImage, code, null, ImageLoader.Type.small);
} else {
imageLoader.bindImage(cardImage, -1, null, ImageLoader.Type.small);
}
helper.getView(R.id.delete_my_online_deck_btn).setOnClickListener(view -> {
deleteMyDeckOnLine(item);
});
helper.getView(R.id.ll_switch_show).setOnClickListener(view -> {
if (item.getPublic()) {
helper.setText(R.id.change_show_or_hide, R.string.in_personal_use);
helper.getView(R.id.show_on_deck_square).setBackgroundResource(R.drawable.closed_eyes_24);
helper.getView(R.id.ll_switch_show).setBackgroundResource(R.drawable.button_radius_n);
item.setPublic(false);
} else {
helper.setText(R.id.change_show_or_hide, R.string.in_public);
helper.getView(R.id.show_on_deck_square).setBackgroundResource(R.drawable.baseline_remove_red_eye_24);
helper.getView(R.id.ll_switch_show).setBackgroundResource(R.drawable.button_radius_red);
item.setPublic(true);
}
LogUtil.i(TAG, "current " + item.toString());
changeDeckPublicState(item);
});
helper.getView(R.id.ll_download).setOnClickListener(view -> {
//TODO
//点击“我的卡组”中的某个卡组后,弹出dialog,dialog根据卡组的同步情况自动显示对应的下载/上传按钮
DeckFile deckFile = new DeckFile(item.getDeckId(), DeckType.ServerType.MY_SQUARE);
});
}
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square;
import java.util.List;
public class UserDeckIds {
public List<String> deckId;
}
package cn.garymb.ygomobile.deck_square.api_response;
public class BasicResponse {
private Integer code;
private String message;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
/**
* 后端设计的有点怪,接口成功时,message的内容为“true”
* @return
*/
public boolean isMessageTrue(){
return message.equals("true");
}
}
package cn.garymb.ygomobile.deck_square.api_response;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class DeckIdResponse {
@Expose
public int code;
@Expose
public String message;
@Expose
@SerializedName("data")
public String deckId;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
@Override
public String toString() {
return "DeckIdResponse{" +
"code=" + code +
", message='" + message + '\'' +
", deckId='" + deckId + '\'' +
'}';
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class DeleteCardJson {
private String deckContributor;
private Integer userId;
private DeckData deck;
public String getDeckContributor() {
return deckContributor;
}
public void setDeckContributor(String deckContributor) {
this.deckContributor = deckContributor;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public DeckData getDeck() {
return deck;
}
public void setDeck(DeckData deck) {
this.deck = deck;
}
public static class DeckData {
private boolean isDelete = false;
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean delete) {
isDelete = delete;
}
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class DownloadDeckResponse {
private Integer code;
private String message;
private MyOnlineDeckDetail data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public MyOnlineDeckDetail getData() {
return data;
}
public void setData(MyOnlineDeckDetail data) {
this.data = data;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class GetSquareDeckCondition {
Integer page;
Integer size;
String keyWord;
Boolean sortLike;
Boolean sortRank;
String contributor;
public GetSquareDeckCondition() {
}
public GetSquareDeckCondition(Integer page, Integer size, String keyWord, Boolean sortLike, Boolean sortRank, String contributor) {
this.page = page;
this.size = size;
this.keyWord = keyWord;
this.sortLike = sortLike;
this.sortRank = sortRank;
this.contributor = contributor;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public String getKeyWord() {
return keyWord;
}
public void setKeyWord(String keyWord) {
this.keyWord = keyWord;
}
public Boolean getSortLike() {
return sortLike;
}
public void setSortLike(Boolean sortLike) {
this.sortLike = sortLike;
}
public Boolean getSortRank() {
return sortRank;
}
public void setSortRank(Boolean sortRank) {
this.sortRank = sortRank;
}
public String getContributor() {
return contributor;
}
public void setContributor(String contributor) {
this.contributor = contributor;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class LoginRequest {
public String account;
public String password;
public LoginRequest(String account, String password) {
this.account = account;
this.password = password;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class LoginResponse {
public String token;
public Boolean success;
public User user;
public static class User {
public int id;
public String username;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class LoginToken {
Integer userId;
String serverToken;
public LoginToken(Integer userId, String serverToken) {
this.userId = userId;
this.serverToken = serverToken;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getServerToken() {
return serverToken;
}
public void setServerToken(String serverToken) {
this.serverToken = serverToken;
}
@Override
public String toString() {
return "LoginToken{" +
"userId=" + userId +
", serverToken='" + serverToken + '\'' +
'}';
}
}
package cn.garymb.ygomobile.deck_square.api_response;
import java.util.List;
public class MyDeckResponse {
public Integer code;
public String message;
public List<MyOnlineDeckDetail> data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<MyOnlineDeckDetail> getData() {
return data;
}
public void setData(List<MyOnlineDeckDetail> data) {
this.data = data;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class MyOnlineDeckDetail implements Parcelable {
private String deckId;
private String deckContributor;
private String deckName;
private String deckRank;
private String deckLike;
private String deckUploadDate;
private String deckUpdateDate;
private int deckCoverCard1;
private int deckCoverCard2;
private int deckCoverCard3;
private String deckCase;
private String deckProtector;
private String deckMainSerial;
private String deckYdk;
private Integer userId;
private boolean isPublic;
private boolean isDelete;
protected MyOnlineDeckDetail(Parcel in) {
deckId = in.readString();
deckContributor = in.readString();
deckName = in.readString();
deckRank = in.readString();
deckLike = in.readString();
deckUploadDate = in.readString();
deckUpdateDate = in.readString();
deckCoverCard1 = in.readInt();
deckCoverCard2 = in.readInt();
deckCoverCard3 = in.readInt();
deckCase = in.readString();
deckProtector = in.readString();
deckMainSerial = in.readString();
deckYdk = in.readString();
userId = in.readInt();
isPublic = (in.readByte() != 0);
isDelete = (in.readByte() != 0);
}
public static final Creator<MyOnlineDeckDetail> CREATOR = new Creator<MyOnlineDeckDetail>() {
@Override
public MyOnlineDeckDetail createFromParcel(Parcel in) {
return new MyOnlineDeckDetail(in);
}
@Override
public MyOnlineDeckDetail[] newArray(int size) {
return new MyOnlineDeckDetail[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(deckId);
dest.writeString(deckContributor);
dest.writeString(deckName);
dest.writeString(deckRank);
dest.writeString(deckLike);
dest.writeString(deckUploadDate);
dest.writeString(deckUpdateDate);
dest.writeInt(deckCoverCard1);
dest.writeInt(deckCoverCard2);
dest.writeInt(deckCoverCard3);
dest.writeString(deckCase);
dest.writeString(deckProtector);
dest.writeString(deckMainSerial);
dest.writeString(deckYdk);
dest.writeInt(userId);
dest.writeByte((byte) (isPublic ? 1 : 0));
dest.writeByte((byte) (isDelete ? 1 : 0));
}
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
public String getDeckContributor() {
return deckContributor;
}
public void setDeckContributor(String deckContributor) {
this.deckContributor = deckContributor;
}
public String getDeckName() {
return deckName;
}
public void setDeckName(String deckName) {
this.deckName = deckName;
}
public String getDeckRank() {
return deckRank;
}
public void setDeckRank(String deckRank) {
this.deckRank = deckRank;
}
public String getDeckLike() {
return deckLike;
}
public void setDeckLike(String deckLike) {
this.deckLike = deckLike;
}
public String getDeckUploadDate() {
return deckUploadDate;
}
public void setDeckUploadDate(String deckUploadDate) {
this.deckUploadDate = deckUploadDate;
}
public String getDeckUpdateDate() {
return deckUpdateDate;
}
public void setDeckUpdateDate(String deckUpdateDate) {
this.deckUpdateDate = deckUpdateDate;
}
public int getDeckCoverCard1() {
return deckCoverCard1;
}
public void setDeckCoverCard1(int deckCoverCard1) {
this.deckCoverCard1 = deckCoverCard1;
}
public int getDeckCoverCard2() {
return deckCoverCard2;
}
public void setDeckCoverCard2(int deckCoverCard2) {
this.deckCoverCard2 = deckCoverCard2;
}
public int getDeckCoverCard3() {
return deckCoverCard3;
}
public void setDeckCoverCard3(int deckCoverCard3) {
this.deckCoverCard3 = deckCoverCard3;
}
public String getDeckCase() {
return deckCase;
}
public void setDeckCase(String deckCase) {
this.deckCase = deckCase;
}
public String getDeckProtector() {
return deckProtector;
}
public void setDeckProtector(String deckProtector) {
this.deckProtector = deckProtector;
}
public String getDeckMainSerial() {
return deckMainSerial;
}
public void setDeckMainSerial(String deckMainSerial) {
this.deckMainSerial = deckMainSerial;
}
public String getDeckYdk() {
return deckYdk;
}
public void setDeckYdk(String deckYdk) {
this.deckYdk = deckYdk;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public boolean isPublic() {
return isPublic;
}
public void setPublic(boolean aPublic) {
isPublic = aPublic;
}
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean delete) {
isDelete = delete;
}
}
\ No newline at end of file
package cn.garymb.ygomobile.deck_square.api_response;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class OnlineDeckDetail implements Parcelable {
private String deckId;
private String deckContributor;
private String deckName;
private int deckLike;
private int deckCoverCard1;
private int deckCoverCard2;
private int deckCoverCard3;
private int deckCase;
private int deckProtector;
private String lastDate;
private int userId;
protected OnlineDeckDetail(Parcel in) {
deckId = in.readString();
deckContributor = in.readString();
deckName = in.readString();
deckLike = in.readInt();
deckCoverCard1 = in.readInt();
deckCoverCard2 = in.readInt();
deckCoverCard3 = in.readInt();
deckCase = in.readInt();
deckProtector = in.readInt();
lastDate = in.readString();
userId = in.readInt();
}
public static final Creator<OnlineDeckDetail> CREATOR = new Creator<OnlineDeckDetail>() {
@Override
public OnlineDeckDetail createFromParcel(Parcel in) {
return new OnlineDeckDetail(in);
}
@Override
public OnlineDeckDetail[] newArray(int size) {
return new OnlineDeckDetail[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(deckId);
dest.writeString(deckContributor);
dest.writeString(deckName);
dest.writeInt(deckLike);
dest.writeInt(deckCoverCard1);
dest.writeInt(deckCoverCard2);
dest.writeInt(deckCoverCard3);
dest.writeInt(deckCase);
dest.writeInt(deckProtector);
dest.writeString(lastDate);
dest.writeInt(userId);
}
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
public String getDeckContributor() {
return deckContributor;
}
public void setDeckContributor(String deckContributor) {
this.deckContributor = deckContributor;
}
public String getDeckName() {
return deckName;
}
public void setDeckName(String deckName) {
this.deckName = deckName;
}
public int getDeckLike() {
return deckLike;
}
public void setDeckLike(int deckLike) {
this.deckLike = deckLike;
}
public int getDeckCoverCard1() {
return deckCoverCard1;
}
public void setDeckCoverCard1(int deckCoverCard1) {
this.deckCoverCard1 = deckCoverCard1;
}
public int getDeckCoverCard2() {
return deckCoverCard2;
}
public void setDeckCoverCard2(int deckCoverCard2) {
this.deckCoverCard2 = deckCoverCard2;
}
public int getDeckCoverCard3() {
return deckCoverCard3;
}
public void setDeckCoverCard3(int deckCoverCard3) {
this.deckCoverCard3 = deckCoverCard3;
}
public int getDeckCase() {
return deckCase;
}
public void setDeckCase(int deckCase) {
this.deckCase = deckCase;
}
public int getDeckProtector() {
return deckProtector;
}
public void setDeckProtector(int deckProtector) {
this.deckProtector = deckProtector;
}
public String getLastDate() {
return lastDate;
}
public void setLastDate(String lastDate) {
this.lastDate = lastDate;
}
public Integer getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class PushCardJson {
private String deckContributor;
private Integer userId;
private DeckData deck;
public String getDeckContributor() {
return deckContributor;
}
public void setDeckContributor(String deckContributor) {
this.deckContributor = deckContributor;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public DeckData getDeck() {
return deck;
}
public void setDeck(DeckData deck) {
this.deck = deck;
}
public static class DeckData {
private String deckId;
private String deckName;
private Integer deckCoverCard1 = 0;
private Integer deckCoverCard2 = 0;
private Integer deckCoverCard3 = 0;
private Integer deckCase = 0;
private Integer deckProtector = 0;
private String deckYdk;
private boolean isDelete = false;
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
public String getDeckName() {
return deckName;
}
public void setDeckName(String deckName) {
this.deckName = deckName;
}
public Integer getDeckCoverCard1(Integer firstCode) {
return deckCoverCard1;
}
public void setDeckCoverCard1(Integer deckCoverCard1) {
this.deckCoverCard1 = deckCoverCard1;
}
public Integer getDeckCoverCard2() {
return deckCoverCard2;
}
public void setDeckCoverCard2(Integer deckCoverCard2) {
this.deckCoverCard2 = deckCoverCard2;
}
public Integer getDeckCoverCard3() {
return deckCoverCard3;
}
public void setDeckCoverCard3(Integer deckCoverCard3) {
this.deckCoverCard3 = deckCoverCard3;
}
public Integer getDeckCase() {
return deckCase;
}
public void setDeckCase(Integer deckCase) {
this.deckCase = deckCase;
}
public Integer getDeckProtector() {
return deckProtector;
}
public void setDeckProtector(Integer deckProtector) {
this.deckProtector = deckProtector;
}
public String getDeckYdk() {
return deckYdk;
}
public void setDeckYdk(String deckYdk) {
this.deckYdk = deckYdk;
}
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean delete) {
isDelete = delete;
}
}
}
package cn.garymb.ygomobile.deck_square.api_response;
public class PushDeckPublicState {
private Integer userId;
private String deckId;
private boolean isPublic;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getDeckId() {
return deckId;
}
public void setDeckId(String deckId) {
this.deckId = deckId;
}
public boolean isPublic() {
return isPublic;
}
public void setPublic(boolean aPublic) {
isPublic = aPublic;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
//将卡组上传后,返回的响应
//对应接口http://rarnu.xyz:38383/api/mdpro3/sync/single
public class PushDeckResponse {
private Integer code;
private String message;
private boolean data;//服务器的执行结果,true代表卡组上传成功。false代表卡组上传失败
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isData() {
return data;
}
public void setData(boolean data) {
this.data = data;
}
}
package cn.garymb.ygomobile.deck_square.api_response;
import java.util.List;
public class SquareDeckResponse {
private Integer code;
private String message;
private ApiData data;
public static class ApiData {
private int current;
private int size;
private int total;
private int pages;
private List<OnlineDeckDetail> records;
// Getters and setters
public int getCurrent() {
return current;
}
public int getSize() {
return size;
}
public int getTotal() {
return total;
}
public int getPages() {
return pages;
}
public List<OnlineDeckDetail> getRecords() {
return records;
}
}
// Getters and setters
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public ApiData getData() {
return data;
}
}
...@@ -29,7 +29,6 @@ import okhttp3.Response; ...@@ -29,7 +29,6 @@ import okhttp3.Response;
public class ExCardListAdapter extends BaseQuickAdapter<ExCardData, BaseViewHolder> { public class ExCardListAdapter extends BaseQuickAdapter<ExCardData, BaseViewHolder> {
private static final String TAG = ExCardListAdapter.class.getSimpleName(); private static final String TAG = ExCardListAdapter.class.getSimpleName();
private ImageLoader imageLoader;
public ExCardListAdapter(int layoutResId) { public ExCardListAdapter(int layoutResId) {
super(layoutResId); super(layoutResId);
......
...@@ -185,7 +185,9 @@ public class ExCardListFragment extends Fragment { ...@@ -185,7 +185,9 @@ public class ExCardListFragment extends Fragment {
enum DownloadState { enum DownloadState {
DOWNLOAD_ING, DOWNLOAD_ING,
NO_DOWNLOAD NO_DOWNLOAD
} @SuppressLint("HandlerLeak") }
@SuppressLint("HandlerLeak")
Handler handler = new Handler() { Handler handler = new Handler() {
@Override @Override
...@@ -209,7 +211,8 @@ public class ExCardListFragment extends Fragment { ...@@ -209,7 +211,8 @@ public class ExCardListFragment extends Fragment {
// break; // break;
case DownloadUtil.TYPE_DOWNLOAD_OK: case DownloadUtil.TYPE_DOWNLOAD_OK:
downloadState = DownloadState.NO_DOWNLOAD; downloadState = DownloadState.NO_DOWNLOAD;
AddServer(getActivity(), context.getString(R.string.Pre_Server_Name), context.getString(R.string.tip_superpre_desc), Constants.URL_Mycard_Super_Pre_Server, Constants.PORT_Mycard_Super_Pre_Server, "Knight of Hanoi"); AddServer(getActivity(), context.getString(R.string.Pre_Server_Name), context.getString(R.string.tip_superpre_desc),
Constants.URL_Mycard_Super_Pre_Server, Constants.PORT_Mycard_Super_Pre_Server, "Knight of Hanoi");
//changeDownloadButton();在下载完成后,通过EventBus通知下载完成(加入用户点击下载后临时切出本fragment,又在下载完成后切回,通过eventbus能保证按钮样式正确更新 //changeDownloadButton();在下载完成后,通过EventBus通知下载完成(加入用户点击下载后临时切出本fragment,又在下载完成后切回,通过eventbus能保证按钮样式正确更新
/* 注意,要先更新版本号 */ /* 注意,要先更新版本号 */
SharedPreferenceUtil.setExpansionDataVer(ServerUtil.serverExCardVersion); SharedPreferenceUtil.setExpansionDataVer(ServerUtil.serverExCardVersion);
...@@ -237,6 +240,4 @@ public class ExCardListFragment extends Fragment { ...@@ -237,6 +240,4 @@ public class ExCardListFragment extends Fragment {
}; };
} }
\ No newline at end of file
package cn.garymb.ygomobile.loader; package cn.garymb.ygomobile.loader;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseArray; import android.util.SparseArray;
...@@ -13,8 +12,6 @@ import java.util.Comparator; ...@@ -13,8 +12,6 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import cn.garymb.ygomobile.Constants; import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.ui.plus.VUiKit; import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.CardSort; import cn.garymb.ygomobile.utils.CardSort;
import cn.garymb.ygomobile.utils.LogUtil; import cn.garymb.ygomobile.utils.LogUtil;
...@@ -27,9 +24,9 @@ import ocgcore.enums.LimitType; ...@@ -27,9 +24,9 @@ import ocgcore.enums.LimitType;
/** /**
* 包括LimitManager、CardManager、LimitList * 包括LimitManager、CardManager、LimitList
* <p>
* LimitList负责判断禁止卡等 * LimitList负责判断禁止卡等
* field包括LimitManager、CardManager * LimitManager、CardManager已封装成单例,使用时不需要构造实例
* 未封装成单例,使用时要构造实例
*/ */
public class CardLoader implements ICardSearcher { public class CardLoader implements ICardSearcher {
private final LimitManager mLimitManager; private final LimitManager mLimitManager;
......
...@@ -20,9 +20,11 @@ import java.nio.charset.StandardCharsets; ...@@ -20,9 +20,11 @@ import java.nio.charset.StandardCharsets;
import cn.garymb.ygomobile.Constants; import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.bean.Deck; import cn.garymb.ygomobile.bean.Deck;
import cn.garymb.ygomobile.bean.DeckInfo; import cn.garymb.ygomobile.bean.DeckInfo;
import cn.garymb.ygomobile.deck_square.DeckSquareListAdapter;
import cn.garymb.ygomobile.ui.cards.deck.DeckItemType; import cn.garymb.ygomobile.ui.cards.deck.DeckItemType;
import cn.garymb.ygomobile.ui.cards.deck.DeckUtils; import cn.garymb.ygomobile.ui.cards.deck.DeckUtils;
import cn.garymb.ygomobile.utils.IOUtils; import cn.garymb.ygomobile.utils.IOUtils;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import ocgcore.data.Card; import ocgcore.data.Card;
import ocgcore.data.LimitList; import ocgcore.data.LimitList;
...@@ -30,12 +32,12 @@ import ocgcore.data.LimitList; ...@@ -30,12 +32,12 @@ import ocgcore.data.LimitList;
public class DeckLoader { public class DeckLoader {
private static Boolean isChanged; private static Boolean isChanged;
public static DeckInfo readDeck(CardLoader cardLoader, File file, LimitList limitList) { public static DeckInfo readDeck(CardLoader cardLoader, File file) {
DeckInfo deckInfo = null; DeckInfo deckInfo = null;
FileInputStream fileinputStream = null; FileInputStream fileinputStream = null;
try { try {
fileinputStream = new FileInputStream(file); fileinputStream = new FileInputStream(file);
deckInfo = readDeck(cardLoader, fileinputStream, limitList); deckInfo = readDeck(cardLoader, fileinputStream);
if (deckInfo != null) { if (deckInfo != null) {
deckInfo.source = file; deckInfo.source = file;
if (isChanged) { if (isChanged) {
...@@ -51,7 +53,7 @@ public class DeckLoader { ...@@ -51,7 +53,7 @@ public class DeckLoader {
return deckInfo; return deckInfo;
} }
private static DeckInfo readDeck(CardLoader cardLoader, InputStream inputStream, LimitList limitList) { private static DeckInfo readDeck(CardLoader cardLoader, InputStream inputStream) {
Deck deck = new Deck(); Deck deck = new Deck();
SparseArray<Integer> mIds = new SparseArray<>(); SparseArray<Integer> mIds = new SparseArray<>();
InputStreamReader in = null; InputStreamReader in = null;
...@@ -60,6 +62,7 @@ public class DeckLoader { ...@@ -60,6 +62,7 @@ public class DeckLoader {
in = new InputStreamReader(inputStream, StandardCharsets.UTF_8); in = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(in); BufferedReader reader = new BufferedReader(in);
String line = null; String line = null;
//按行读取ydk文件
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
if (line.startsWith("!side")) { if (line.startsWith("!side")) {
type = DeckItemType.SideCard; type = DeckItemType.SideCard;
......
...@@ -5,6 +5,7 @@ import android.content.Context; ...@@ -5,6 +5,7 @@ import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
...@@ -15,14 +16,22 @@ import com.chad.library.adapter.base.listener.OnItemClickListener; ...@@ -15,14 +16,22 @@ import com.chad.library.adapter.base.listener.OnItemClickListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.bean.Deck; import cn.garymb.ygomobile.bean.Deck;
import cn.garymb.ygomobile.bean.DeckInfo; import cn.garymb.ygomobile.bean.DeckInfo;
import cn.garymb.ygomobile.bean.TextSelect; import cn.garymb.ygomobile.bean.TextSelect;
import cn.garymb.ygomobile.bean.events.DeckFile; import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.deck_square.DeckSquareApiUtil;
import cn.garymb.ygomobile.deck_square.DeckSquareListAdapter;
import cn.garymb.ygomobile.deck_square.api_response.LoginToken;
import cn.garymb.ygomobile.deck_square.api_response.PushDeckResponse;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.CardLoader; import cn.garymb.ygomobile.loader.CardLoader;
import cn.garymb.ygomobile.loader.DeckLoader; import cn.garymb.ygomobile.loader.DeckLoader;
import cn.garymb.ygomobile.loader.ImageLoader; import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGOUtil; import cn.garymb.ygomobile.utils.YGOUtil;
import ocgcore.DataManager; import ocgcore.DataManager;
import ocgcore.data.LimitList; import ocgcore.data.LimitList;
...@@ -38,9 +47,11 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -38,9 +47,11 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
private OnItemSelectListener onItemSelectListener; private OnItemSelectListener onItemSelectListener;
private int selectPosition; private int selectPosition;
private final boolean isSelect; private final boolean isSelect;
private boolean isManySelect; private boolean isManySelect;//标志位,是否选中多个卡组
private final List<T> selectList; private final List<T> selectList;
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
public DeckListAdapter(Context context, List<T> data, int select) { public DeckListAdapter(Context context, List<T> data, int select) {
super(R.layout.item_deck_list_swipe, data); super(R.layout.item_deck_list_swipe, data);
this.selectPosition = select; this.selectPosition = select;
...@@ -66,8 +77,40 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -66,8 +77,40 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
deckInfo = new DeckInfo(); deckInfo = new DeckInfo();
mLimitList = DataManager.get().getLimitManager().getTopLimit(); mLimitList = DataManager.get().getLimitManager().getTopLimit();
mContext = context; mContext = context;
addChildClickViewIds(R.id.local_deck_upload_btn);
LogUtil.i(TAG, "DeckListAdapter constructor");
setOnItemChildClickListener((adapter, view, position) -> {
//判断是否登录,如果未登录,直接返回
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
return;
}
//获得点击的卡组
DeckFile deckFile = (DeckFile) adapter.getData().get(position);
LogUtil.i(TAG, "deckFile " + deckFile.toString());
//上传卡组
VUiKit.defer().when(() -> {
PushDeckResponse result = DeckSquareApiUtil.requestIdAndPushDeck(deckFile,loginToken);
return result;
}).fail(e -> {
LogUtil.i(TAG, "square deck detail fail" + e.getMessage());
}).done(pushDeckResponse -> {
if (pushDeckResponse.isData()) {
YGOUtil.showTextToast("push success!");
} else {
YGOUtil.showTextToast("卡组上传失败!");
}
});
});
} }
@SuppressLint("ResourceType") @SuppressLint("ResourceType")
@Override @Override
protected void convert(DeckViewHolder holder, T item) { protected void convert(DeckViewHolder holder, T item) {
...@@ -76,7 +119,7 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -76,7 +119,7 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
this.deckFile = (DeckFile) item; this.deckFile = (DeckFile) item;
holder.deckName.setText(item.getName()); holder.deckName.setText(item.getName());
//预读卡组信息 //预读卡组信息
this.deckInfo = DeckLoader.readDeck(mCardLoader, deckFile.getPathFile(), mLimitList); this.deckInfo = DeckLoader.readDeck(mCardLoader, deckFile.getPathFile());
//加载卡组第一张卡的图 //加载卡组第一张卡的图
holder.cardImage.setVisibility(View.VISIBLE); holder.cardImage.setVisibility(View.VISIBLE);
imageLoader.bindImage(holder.cardImage, deckFile.getFirstCode(), ImageLoader.Type.middle); imageLoader.bindImage(holder.cardImage, deckFile.getFirstCode(), ImageLoader.Type.middle);
...@@ -106,7 +149,8 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -106,7 +149,8 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
holder.side.setText("-"); holder.side.setText("-");
holder.side.setTextColor(Color.RED); holder.side.setTextColor(Color.RED);
} }
if (deckFile.getTypeName().equals(YGOUtil.s(R.string.category_pack)) || deckFile.getPath().contains("cacheDeck")) {//卡包展示时不显示额外和副卡组数量文本 if (deckFile.getTypeName().equals(YGOUtil.s(R.string.category_pack)) || deckFile.getPath().contains("cacheDeck")) {
//卡包展示时不显示额外和副卡组数量文本
holder.ll_extra_n_side.setVisibility(View.GONE); holder.ll_extra_n_side.setVisibility(View.GONE);
} else { } else {
holder.ll_extra_n_side.setVisibility(View.VISIBLE); holder.ll_extra_n_side.setVisibility(View.VISIBLE);
...@@ -178,6 +222,14 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -178,6 +222,14 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
} else { } else {
holder.item_deck_list.setBackgroundResource(Color.TRANSPARENT); holder.item_deck_list.setBackgroundResource(Color.TRANSPARENT);
} }
//卡包展示、人机卡组不显示上传按钮图标
if (deckFile.getPathFile().getParent().endsWith(Constants.CORE_PACK_PATH)
|| deckFile.getPathFile().getParent().endsWith(Constants.WINDBOT_DECK_PATH)
||deckFile.getPathFile().getParent().endsWith("cacheDeck")) {
holder.local_deck_upload_btn.setVisibility(View.GONE);
} else {
holder.local_deck_upload_btn.setVisibility(View.VISIBLE);
}
} }
public void setSelectPosition(int selectPosition) { public void setSelectPosition(int selectPosition) {
...@@ -199,6 +251,12 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -199,6 +251,12 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
selectList.add(t); selectList.add(t);
} }
/**
* 内部维护了selectList,用于存储当前选中的卡组
* DeckListAdapter支持多选,传入false清除已选中的卡组,并更新adapter。传入true将标志位置1
*
* @param manySelect
*/
public void setManySelect(boolean manySelect) { public void setManySelect(boolean manySelect) {
isManySelect = manySelect; isManySelect = manySelect;
if (!isManySelect) { if (!isManySelect) {
...@@ -222,6 +280,8 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -222,6 +280,8 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
public interface OnItemSelectListener<T> { public interface OnItemSelectListener<T> {
void onItemSelect(int position, T item); void onItemSelect(int position, T item);
} }
} }
class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHolder { class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHolder {
...@@ -229,12 +289,14 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo ...@@ -229,12 +289,14 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
ImageView prerelease_star; ImageView prerelease_star;
ImageView banned_mark; ImageView banned_mark;
TextView deckName; TextView deckName;
TextView deckId;
TextView main; TextView main;
TextView extra; TextView extra;
TextView side; TextView side;
LinearLayout ll_extra_n_side; LinearLayout ll_extra_n_side;
View item_deck_list; View item_deck_list;
View deck_info; View deck_info;
Button local_deck_upload_btn;
public DeckViewHolder(View view) { public DeckViewHolder(View view) {
super(view); super(view);
...@@ -242,6 +304,7 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo ...@@ -242,6 +304,7 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
item_deck_list = findView(R.id.item_deck_list); item_deck_list = findView(R.id.item_deck_list);
cardImage = findView(R.id.card_image); cardImage = findView(R.id.card_image);
deckName = findView(R.id.deck_name); deckName = findView(R.id.deck_name);
deckId = findView(R.id.onlie_deck_id);
main = findView(R.id.count_main); main = findView(R.id.count_main);
extra = findView(R.id.count_ex); extra = findView(R.id.count_ex);
side = findView(R.id.count_side); side = findView(R.id.count_side);
...@@ -249,5 +312,6 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo ...@@ -249,5 +312,6 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
prerelease_star = findView(R.id.prerelease_star); prerelease_star = findView(R.id.prerelease_star);
banned_mark = findView(R.id.banned_mark); banned_mark = findView(R.id.banned_mark);
deck_info = findView(R.id.deck_info); deck_info = findView(R.id.deck_info);
local_deck_upload_btn = findView(R.id.local_deck_upload_btn);
} }
} }
\ No newline at end of file
package cn.garymb.ygomobile.ui.adapters;
import androidx.annotation.NonNull;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import java.util.List;
import cn.garymb.ygomobile.ex_card.ExCardListAdapter;
import cn.garymb.ygomobile.lite.R;
import ocgcore.data.Card;
//卡组预览的adapter
public class DeckPreviewListAdapter extends BaseQuickAdapter<Card, BaseViewHolder> {
private static final String TAG = ExCardListAdapter.class.getSimpleName();
public DeckPreviewListAdapter(int layoutResId) {
super(layoutResId);
}
public void updateData(List<Card> dataList) {
getData().clear();
addData(dataList);
notifyDataSetChanged();
}
@Override
protected void convert(@NonNull BaseViewHolder baseViewHolder, Card item) {
baseViewHolder.setText(R.id.preview_card_name, item.Name);
baseViewHolder.setText(R.id.preview_card_id, Integer.toString(item.Code));
}
}
...@@ -37,7 +37,7 @@ public class TextSelectAdapter<T extends TextSelect> extends BaseQuickAdapter<T, ...@@ -37,7 +37,7 @@ public class TextSelectAdapter<T extends TextSelect> extends BaseQuickAdapter<T,
selectPosition = position; selectPosition = position;
notifyDataSetChanged(); notifyDataSetChanged();
if (onItemSelectListener != null) if (onItemSelectListener != null)
onItemSelectListener.onItemSelect(position, data.get(position).getObject()); onItemSelectListener.onItemSelect(position, data.get(position));
} }
}); });
} }
...@@ -59,7 +59,7 @@ public class TextSelectAdapter<T extends TextSelect> extends BaseQuickAdapter<T, ...@@ -59,7 +59,7 @@ public class TextSelectAdapter<T extends TextSelect> extends BaseQuickAdapter<T,
} else { } else {
helper.setBackgroundResource(R.id.ll_layout, Color.TRANSPARENT); helper.setBackgroundResource(R.id.ll_layout, Color.TRANSPARENT);
} }
}else { } else {
helper.setBackgroundResource(R.id.ll_layout, Color.TRANSPARENT); helper.setBackgroundResource(R.id.ll_layout, Color.TRANSPARENT);
} }
......
...@@ -19,7 +19,7 @@ import android.widget.Toast; ...@@ -19,7 +19,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.RecyclerViewItemListener; import androidx.recyclerview.widget.RecyclerViewItemListener;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.FastScrollLinearLayoutManager; import androidx.recyclerview.widget.FastScrollLinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
......
...@@ -33,18 +33,19 @@ import android.widget.AdapterView; ...@@ -33,18 +33,19 @@ import android.widget.AdapterView;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatSpinner; import androidx.appcompat.widget.AppCompatSpinner;
import androidx.appcompat.widget.RecyclerViewItemListener;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.FastScrollLinearLayoutManager; import androidx.recyclerview.widget.FastScrollLinearLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelperPlus; import androidx.recyclerview.widget.ItemTouchHelperPlus;
import androidx.recyclerview.widget.OnItemDragListener; import androidx.recyclerview.widget.OnItemDragListener;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerViewItemListener;
import com.app.hubert.guide.NewbieGuide; import com.app.hubert.guide.NewbieGuide;
import com.app.hubert.guide.model.GuidePage; import com.app.hubert.guide.model.GuidePage;
...@@ -75,6 +76,11 @@ import cn.garymb.ygomobile.bean.DeckType; ...@@ -75,6 +76,11 @@ import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.events.CardInfoEvent; import cn.garymb.ygomobile.bean.events.CardInfoEvent;
import cn.garymb.ygomobile.bean.events.DeckFile; import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.core.IrrlichtBridge; import cn.garymb.ygomobile.core.IrrlichtBridge;
import cn.garymb.ygomobile.deck_square.DeckManageDialog;
import cn.garymb.ygomobile.deck_square.DeckSquareApiUtil;
import cn.garymb.ygomobile.deck_square.DeckSquareFileUtil;
import cn.garymb.ygomobile.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.deck_square.api_response.DownloadDeckResponse;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.CardLoader; import cn.garymb.ygomobile.loader.CardLoader;
import cn.garymb.ygomobile.loader.CardSearchInfo; import cn.garymb.ygomobile.loader.CardSearchInfo;
...@@ -98,8 +104,9 @@ import cn.garymb.ygomobile.utils.BitmapUtil; ...@@ -98,8 +104,9 @@ import cn.garymb.ygomobile.utils.BitmapUtil;
import cn.garymb.ygomobile.utils.DeckUtil; import cn.garymb.ygomobile.utils.DeckUtil;
import cn.garymb.ygomobile.utils.FileUtils; import cn.garymb.ygomobile.utils.FileUtils;
import cn.garymb.ygomobile.utils.IOUtils; import cn.garymb.ygomobile.utils.IOUtils;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.ShareUtil; import cn.garymb.ygomobile.utils.ShareUtil;
import cn.garymb.ygomobile.utils.YGODialogUtil; import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
import cn.garymb.ygomobile.utils.YGOUtil; import cn.garymb.ygomobile.utils.YGOUtil;
import cn.garymb.ygomobile.utils.glide.GlideCompat; import cn.garymb.ygomobile.utils.glide.GlideCompat;
import ocgcore.CardManager; import ocgcore.CardManager;
...@@ -109,7 +116,12 @@ import ocgcore.data.Card; ...@@ -109,7 +116,12 @@ import ocgcore.data.Card;
import ocgcore.data.LimitList; import ocgcore.data.LimitList;
import ocgcore.enums.LimitType; import ocgcore.enums.LimitType;
public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewItemListener.OnItemListener, OnItemDragListener, YGODialogUtil.OnDeckMenuListener, CardLoader.CallBack, CardSearcher.CallBack { /**
* 卡组编辑页面,在本页面中显示某个卡组的内容
* 注意,卡组编辑页面中的长按事件回调在ItemTouchHelperPlus中实现,而非在
* RecyclerViewItemListener.OnItemListener中
*/
public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewItemListener.OnItemListener, OnItemDragListener, YGODeckDialogUtil.OnDeckMenuListener, CardLoader.CallBack, CardSearcher.CallBack {
private static final String TAG = "DeckManagerFragment"; private static final String TAG = "DeckManagerFragment";
protected DrawerLayout mDrawerLayout; protected DrawerLayout mDrawerLayout;
protected RecyclerView mListView; protected RecyclerView mListView;
...@@ -120,6 +132,9 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -120,6 +132,9 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
protected CardListAdapter mCardListAdapter; protected CardListAdapter mCardListAdapter;
protected boolean isLoad = false; protected boolean isLoad = false;
private HomeActivity activity; private HomeActivity activity;
private String mDeckId;
private LinearLayout ll_click_like;
private TextView tv_add_1;
protected int screenWidth; protected int screenWidth;
...@@ -130,7 +145,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -130,7 +145,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
private BaseActivity mContext; private BaseActivity mContext;
long exitLasttime = 0; long exitLasttime = 0;
private File mPreLoadFile; private File mPreLoadFile;//预加载卡组,用于外部打开ydk文件或通过卡组广场预览卡组时,值为file。当未通过预加载打开ydk(打开卡组时),值为null
private DeckItemTouchHelper mDeckItemTouchHelper; private DeckItemTouchHelper mDeckItemTouchHelper;
private TextView tv_deck; private TextView tv_deck;
private TextView tv_result_count; private TextView tv_result_count;
...@@ -149,6 +164,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -149,6 +164,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
layoutView = inflater.inflate(R.layout.fragment_deck_cards, container, false); layoutView = inflater.inflate(R.layout.fragment_deck_cards, container, false);
AnimationShake2(layoutView); AnimationShake2(layoutView);
initView(layoutView); initView(layoutView);
//检查外部调用方是否传入了ydk文件路径,如果传入,则打开外部ydk文件
preLoadFile(); preLoadFile();
//event //event
if (!EventBus.getDefault().isRegistered(this)) {//加上判断 if (!EventBus.getDefault().isRegistered(this)) {//加上判断
...@@ -196,20 +212,61 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -196,20 +212,61 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
initBoomMenuButton(layoutView.findViewById(R.id.bmb)); initBoomMenuButton(layoutView.findViewById(R.id.bmb));
layoutView.findViewById(R.id.btn_nav_search).setOnClickListener((v) -> doMenu(R.id.action_search)); layoutView.findViewById(R.id.btn_nav_search).setOnClickListener((v) -> doMenu(R.id.action_search));
layoutView.findViewById(R.id.btn_nav_list).setOnClickListener((v) -> doMenu(R.id.action_card_list)); layoutView.findViewById(R.id.btn_nav_list).setOnClickListener((v) -> doMenu(R.id.action_card_list));
tv_deck.setOnClickListener(v -> //只有当加载的是具有id的deck时才显示点赞按钮
YGODialogUtil.dialogDeckSelect(getActivity(), AppsSettings.get().getLastDeckPath(), this)); tv_add_1 = layoutView.findViewById(R.id.tv_add_1);
ll_click_like = layoutView.findViewById(R.id.ll_click_like);
ll_click_like.setOnClickListener(v -> {
if (mDeckId != null) {
VUiKit.defer().when(() -> {
BasicResponse result = DeckSquareApiUtil.likeDeck(mDeckId);
return result;
}).fail(e -> {
LogUtil.i(TAG, "Like deck fail" + e.getMessage());
YGOUtil.showTextToast("点赞失败");
}).done(data -> {
if (data != null && data.getMessage() != null && data.getMessage().equals("true")) {
// 显示点赞动画
tv_add_1.setText("+1");
ll_click_like.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.fade_out));
ll_click_like.setVisibility(View.GONE);
} else {
YGOUtil.showTextToast(data != null ? data.getMessage() : "点赞失败");
}
});
}
});
tv_deck.setOnClickListener(v -> {
new DeckManageDialog(this).show(
getActivity().getSupportFragmentManager(), "pagerDialog");
});
// YGODeckDialogUtil.dialogDeckSelect(getActivity(), AppsSettings.get().getLastDeckPath(), this));
mContext = (BaseActivity) getActivity(); mContext = (BaseActivity) getActivity();
} }
/**
* 外部调用fragment时,如果通过setArguments(mBundle)方法设置了ydk文件路径,则直接打开该ydk文件
* 将mPreLoadFile设置为对应的File
*/
public void preLoadFile() { public void preLoadFile() {
String preLoadFile = ""; String preLoadFilePath = "";
if (getArguments() != null) { if (getArguments() != null) {
preLoadFile = getArguments().getString("setDeck"); preLoadFilePath = getArguments().getString("setDeck");
getArguments().clear(); getArguments().clear();
} }
preLoadFile(preLoadFilePath);
}
/**
* 传入外部ydk文件的路径,临时在本页面中打开该ydk的内容,用于后续的保存
* @param preLoadFilePath 外部ydk文件的路径
*/
public void preLoadFile(String preLoadFilePath) {
final File _file; final File _file;
//打开指定卡组 //打开指定卡组
if (!TextUtils.isEmpty(preLoadFile) && (mPreLoadFile = new File(preLoadFile)).exists()) { if (!TextUtils.isEmpty(preLoadFilePath) && (mPreLoadFile = new File(preLoadFilePath)).exists()) {
//外面卡组 //外面卡组
_file = mPreLoadFile; _file = mPreLoadFile;
} else { } else {
...@@ -304,6 +361,11 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -304,6 +361,11 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} }
/**
* 在此处处理卡组中卡片的长按删除
*
* @param pos
*/
@Override @Override
public void onDragLongPress(int pos) { public void onDragLongPress(int pos) {
if (pos < 0) return; if (pos < 0) return;
...@@ -371,7 +433,9 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -371,7 +433,9 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} }
} }
//region load deck //region load deck
//从文件file中读取deck
private void loadDeckFromFile(File file) { private void loadDeckFromFile(File file) {
if (!mCardLoader.isOpen() || file == null || !file.exists()) { if (!mCardLoader.isOpen() || file == null || !file.exists()) {
setCurDeck(new DeckInfo(), false); setCurDeck(new DeckInfo(), false);
...@@ -386,7 +450,8 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -386,7 +450,8 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} }
}).done((rs) -> { }).done((rs) -> {
dlg.dismiss(); dlg.dismiss();
setCurDeck(rs, file.getParent().equals(mSettings.getPackDeckDir()) || file.getParent().equals(mSettings.getCacheDeckDir())); //setCurDeck(rs, file.getParent().equals(mSettings.getPackDeckDir()) || file.getParent().equals(mSettings.getCacheDeckDir()));
setCurDeck(rs, file.getParent().equals(mSettings.getPackDeckDir()));
}); });
} }
...@@ -434,7 +499,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -434,7 +499,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} }
/** /**
* 设置当前卡组 * 用户选中某个卡组后,更新当前界面,显示已选中的卡组。包括更新界面显示(tv_deck)、更新AppsSettings、通知DeckAdapter
*/ */
private void setCurDeck(DeckInfo deckInfo, boolean isPack) { private void setCurDeck(DeckInfo deckInfo, boolean isPack) {
if (deckInfo == null) { if (deckInfo == null) {
...@@ -773,8 +838,8 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -773,8 +838,8 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} }
shareDeck(); shareDeck();
break; break;
case R.id.action_save: case R.id.action_save://如果是通过“预加载”打开ydk,则将ydk保存到
if (mPreLoadFile != null && mPreLoadFile == mDeckAdapater.getYdkFile()) { if (mPreLoadFile != null && mPreLoadFile == mDeckAdapater.getYdkFile()) {//代表通过预加载功能打开的ydk
//需要保存到deck文件夹 //需要保存到deck文件夹
inputDeckName(mPreLoadFile, null, true); inputDeckName(mPreLoadFile, null, true);
} else { } else {
...@@ -1013,6 +1078,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -1013,6 +1078,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
return null; return null;
} }
//从存储卡组的文件夹中获取所有名字以.ydk结尾的文件,并将mPreLoadFile也加入到返回结果中
private List<File> getYdkFiles() { private List<File> getYdkFiles() {
File dir = new File(mSettings.getResourcePath(), Constants.CORE_DECK_PATH); File dir = new File(mSettings.getResourcePath(), Constants.CORE_DECK_PATH);
File[] files = dir.listFiles((file, s) -> s.toLowerCase(Locale.US).endsWith(Constants.YDK_FILE_EX)); File[] files = dir.listFiles((file, s) -> s.toLowerCase(Locale.US).endsWith(Constants.YDK_FILE_EX));
...@@ -1212,9 +1278,42 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -1212,9 +1278,42 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
YGOUtil.showTextToast(R.string.done); YGOUtil.showTextToast(R.string.done);
} }
//在卡组选择的dialog中点击某个卡组(来自本地或服务器)后,dialog通过本回调函数通知本页面。
//在本页面中根据卡组来源(本地或服务器)显示卡组内容
@Override @Override
public void onDeckSelect(DeckFile deckFile) { public void onDeckSelect(DeckFile deckFile) {
loadDeckFromFile(deckFile.getPathFile()); if (!deckFile.isLocal()) {//不在本地,在云上(卡组广场中或用户的云上)
VUiKit.defer().when(() -> {
DownloadDeckResponse response = DeckSquareApiUtil.getDeckById(deckFile.getDeckId());
if (response != null) {
return response.getData();
} else {
return null;
}
}).fail((e) -> {
LogUtil.i(TAG, "square deck detail fail" + e.getMessage());
}).done((deckData) -> {
if (deckData != null) {
mDeckId = deckData.getDeckId();
Log.w("seesee mDeckId", mDeckId);
deckData.getDeckYdk();
String fileFullName = deckData.getDeckName() + ".ydk";
File dir = new File(getActivity().getApplicationInfo().dataDir, "cache");
//将卡组存到cache缓存目录中
boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk());
if (result) {//存储成功,使用预加载功能
LogUtil.i(TAG, "square deck detail done");
//File file = new File(dir, fileFullName);
preLoadFile(dir.getPath() + "/" + fileFullName);
tv_add_1.setText(R.string.like_deck_thumb);
ll_click_like.setVisibility(View.VISIBLE);
}
}
});
} else {
loadDeckFromFile(deckFile.getPathFile());
}
} }
@Override @Override
......
...@@ -32,6 +32,9 @@ import ocgcore.data.LimitList; ...@@ -32,6 +32,9 @@ import ocgcore.data.LimitList;
import ocgcore.enums.CardType; import ocgcore.enums.CardType;
import ocgcore.enums.LimitType; import ocgcore.enums.LimitType;
/**
* 在对应的recyclerview中添加了很多透明的item来“占位”,占位后便于根据“拖动卡片的位置”计算添加的卡片类型(是主卡组、额外卡组还是副卡组)
*/
public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implements CardListProvider { public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implements CardListProvider {
private final List<DeckItem> mItems = new ArrayList<>(); private final List<DeckItem> mItems = new ArrayList<>();
private final SparseArray<Integer> mCount = new SparseArray<>(); private final SparseArray<Integer> mCount = new SparseArray<>();
...@@ -107,7 +110,7 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -107,7 +110,7 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
int id = DeckItem.MainStart + getMainCount(); int id = DeckItem.MainStart + getMainCount();
removeItem(DeckItem.MainEnd); removeItem(DeckItem.MainEnd);
addItem(id, new DeckItem(cardInfo, type)); addItem(id, new DeckItem(cardInfo, type));
notifyItemChanged(DeckItem.MainEnd); //notifyItemChanged(DeckItem.MainEnd);//todo 这行好像没啥用啊??
notifyItemChanged(id); notifyItemChanged(id);
notifyItemChanged(DeckItem.MainLabel); notifyItemChanged(DeckItem.MainLabel);
return true; return true;
...@@ -403,7 +406,7 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -403,7 +406,7 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
if (limitList != null) { if (limitList != null) {
setLimitList(limitList); setLimitList(limitList);
} }
return DeckLoader.readDeck(cardLoader, file, limitList); return DeckLoader.readDeck(cardLoader, file);
} }
public boolean save(File file) { public boolean save(File file) {
...@@ -445,12 +448,6 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -445,12 +448,6 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
return !TextUtils.equals(mDeckMd5, md5); return !TextUtils.equals(mDeckMd5, md5);
} }
@Override
public DeckViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.item_deck_card, parent, false);
return new DeckViewHolder(view);
}
private String getString(int id, Object... args) { private String getString(int id, Object... args) {
return context.getString(id, args); return context.getString(id, args);
} }
...@@ -536,13 +533,22 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -536,13 +533,22 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
// notifyItemChanged(DeckItem.HeadView); // notifyItemChanged(DeckItem.HeadView);
} }
@Override
public DeckViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Inflating a layout from XML and returning the holder
View view = mLayoutInflater.inflate(R.layout.item_deck_card, parent, false);
return new DeckViewHolder(view);
}
@Override @Override
public void onBindViewHolder(DeckViewHolder holder, int position) { public void onBindViewHolder(DeckViewHolder holder, int position) {
//Populating data into the item through holder
//根据data的内容调整view的样式
DeckItem item = mItems.get(position); DeckItem item = mItems.get(position);
holder.setItemType(item.getType()); holder.setItemType(item.getType());
if (item.getType() == DeckItemType.MainLabel || item.getType() == DeckItemType.SideLabel if (item.getType() == DeckItemType.MainLabel || item.getType() == DeckItemType.SideLabel
|| item.getType() == DeckItemType.ExtraLabel) { || item.getType() == DeckItemType.ExtraLabel) {//处理分隔栏的item view
//分隔栏
if (item.getType() == DeckItemType.MainLabel) { if (item.getType() == DeckItemType.MainLabel) {
holder.setText(getMainString()); holder.setText(getMainString());
} else if (item.getType() == DeckItemType.SideLabel) { } else if (item.getType() == DeckItemType.SideLabel) {
...@@ -550,7 +556,8 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -550,7 +556,8 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
} else if (item.getType() == DeckItemType.ExtraLabel) { } else if (item.getType() == DeckItemType.ExtraLabel) {
holder.setText(getExtraString()); holder.setText(getExtraString());
} }
} else { } else {//处理展示卡图的item view
/* 动态计算控件的高度,优先根据卡图的实际大小计算高度,如果结果<=0,则根据recyclerView的宽度计算控件高度 */
if (mHeight <= 0) { if (mHeight <= 0) {
if (holder.cardImage.getMeasuredWidth() > 0) { if (holder.cardImage.getMeasuredWidth() > 0) {
mWidth = holder.cardImage.getMeasuredWidth(); mWidth = holder.cardImage.getMeasuredWidth();
...@@ -567,11 +574,10 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -567,11 +574,10 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
//显示卡片 //显示卡片
holder.showImage(); holder.showImage();
holder.setSize(mHeight); holder.setSize(mHeight);
if (item.getType() == DeckItemType.Space) { if (item.getType() == DeckItemType.Space) {//占位,不显示卡图
//占位但是不显示卡图
holder.setCardType(0); holder.setCardType(0);
holder.showEmpty(); holder.showEmpty();
} else { } else {//非占位,显示卡图
Card cardInfo = item.getCardInfo(); Card cardInfo = item.getCardInfo();
// holder.cardImage.setOnClickListener(new View.OnClickListener() { // holder.cardImage.setOnClickListener(new View.OnClickListener() {
...@@ -582,7 +588,7 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement ...@@ -582,7 +588,7 @@ public class DeckAdapater extends RecyclerView.Adapter<DeckViewHolder> implement
// else // else
// Toast.makeText(context,"空点击"+position,Toast.LENGTH_SHORT).show(); // Toast.makeText(context,"空点击"+position,Toast.LENGTH_SHORT).show();
// } // }
// }); // });//将cardInfo在LimitList中检查,根据结果(限制、准限制、禁止)对应显示卡图
if (cardInfo != null) { if (cardInfo != null) {
holder.setCardType(cardInfo.Type); holder.setCardType(cardInfo.Type);
if (mImageTop == null) { if (mImageTop == null) {
......
package cn.garymb.ygomobile.ui.cards.deck; package cn.garymb.ygomobile.ui.cards.deck;
/**
* DeckItemType的不同值对应着,recyclerView中的item的不同布局形式
*/
public enum DeckItemType { public enum DeckItemType {
MainLabel, MainLabel,//对应“主卡组:60怪兽:21...“这种分隔标签
MainCard, MainCard,//对应主卡组中的卡图控件
ExtraLabel, ExtraLabel,//额外卡组
ExtraCard, ExtraCard,//对应额外卡组中的卡图控件
SideLabel, SideLabel,//副卡组
SideCard, SideCard,//对应副卡组中的卡图控件
Space, Space,//对应占位的卡图控件
Pack Pack
} }
...@@ -109,6 +109,14 @@ class DeckItemUtils { ...@@ -109,6 +109,14 @@ class DeckItemUtils {
return deck; return deck;
} }
/**
* 将file内容更新为List<DeckItem>中的内容
* 删除file,之后将List<DeckItem>中的内容保存到file中
* @param items
* @param file 原有file
* @return 如果file为null,返回false
*/
public static boolean save(List<DeckItem> items, File file) { public static boolean save(List<DeckItem> items, File file) {
FileOutputStream outputStream = null; FileOutputStream outputStream = null;
OutputStreamWriter writer = null; OutputStreamWriter writer = null;
......
...@@ -20,6 +20,7 @@ import cn.garymb.ygomobile.utils.IOUtils; ...@@ -20,6 +20,7 @@ import cn.garymb.ygomobile.utils.IOUtils;
import ocgcore.data.Card; import ocgcore.data.Card;
public class DeckUtils { public class DeckUtils {
//将Deck通过ByteArrayOutputStream)转为String
public static String getDeckString(Deck deck) { public static String getDeckString(Deck deck) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
save(deck, outputStream); save(deck, outputStream);
...@@ -28,6 +29,7 @@ public class DeckUtils { ...@@ -28,6 +29,7 @@ public class DeckUtils {
return str; return str;
} }
//将DeckInfo(通过ByteArrayOutputStream)转为String
public static String getDeckString(DeckInfo deck) { public static String getDeckString(DeckInfo deck) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
save(deck, outputStream); save(deck, outputStream);
...@@ -36,6 +38,13 @@ public class DeckUtils { ...@@ -36,6 +38,13 @@ public class DeckUtils {
return str; return str;
} }
/**
* 将DeckInfo对象以ydk文件的格式存入到outputStream对应的文件中
*
* @param deck
* @param outputStream
* @return
*/
private static boolean save(DeckInfo deck, OutputStream outputStream) { private static boolean save(DeckInfo deck, OutputStream outputStream) {
OutputStreamWriter writer = null; OutputStreamWriter writer = null;
try { try {
...@@ -64,6 +73,8 @@ public class DeckUtils { ...@@ -64,6 +73,8 @@ public class DeckUtils {
return true; return true;
} }
//将Deck对象以ydk文件的格式存入到outputStream对应的文件中
private static boolean save(Deck deck, OutputStream outputStream) { private static boolean save(Deck deck, OutputStream outputStream) {
OutputStreamWriter writer = null; OutputStreamWriter writer = null;
try { try {
...@@ -92,6 +103,7 @@ public class DeckUtils { ...@@ -92,6 +103,7 @@ public class DeckUtils {
return true; return true;
} }
//将deck对象以ydk文件的格式存入到file对应的文件中
public static boolean save(DeckInfo deck, File file) { public static boolean save(DeckInfo deck, File file) {
if (deck == null) return false; if (deck == null) return false;
FileOutputStream outputStream = null; FileOutputStream outputStream = null;
...@@ -113,6 +125,7 @@ public class DeckUtils { ...@@ -113,6 +125,7 @@ public class DeckUtils {
return true; return true;
} }
//将Deck对象以ydk文件的格式存入到File对应的文件中
public static boolean save(Deck deck, File file) { public static boolean save(Deck deck, File file) {
if (deck == null) return false; if (deck == null) return false;
FileOutputStream outputStream = null; FileOutputStream outputStream = null;
...@@ -127,7 +140,7 @@ public class DeckUtils { ...@@ -127,7 +140,7 @@ public class DeckUtils {
outputStream = new FileOutputStream(file); outputStream = new FileOutputStream(file);
save(deck, outputStream); save(deck, outputStream);
} catch (Exception e) { } catch (Exception e) {
Log.e("DeckUtil","保存出错"+e); Log.e("DeckUtil", "保存出错" + e);
//ignore //ignore
} finally { } finally {
IOUtils.close(outputStream); IOUtils.close(outputStream);
...@@ -135,11 +148,12 @@ public class DeckUtils { ...@@ -135,11 +148,12 @@ public class DeckUtils {
return true; return true;
} }
public static File save(String name,String deckMessage) throws IOException { @Deprecated
public static File save(String name, String deckMessage) throws IOException {
FileWriter fw = null; FileWriter fw = null;
//如果文件存在,则重写内容;如果文件不存在,则创建文件 //如果文件存在,则重写内容;如果文件不存在,则创建文件
File f = new File(AppsSettings.get().getDeckDir(),name + Constants.YDK_FILE_EX); File f = new File(AppsSettings.get().getDeckDir(), name + Constants.YDK_FILE_EX);
fw = new FileWriter(f, false); fw = new FileWriter(f, false);
PrintWriter pw = new PrintWriter(fw); PrintWriter pw = new PrintWriter(fw);
......
...@@ -12,7 +12,11 @@ import androidx.recyclerview.widget.RecyclerView; ...@@ -12,7 +12,11 @@ import androidx.recyclerview.widget.RecyclerView;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.ImageLoader; import cn.garymb.ygomobile.loader.ImageLoader;
// Provide a direct reference to each of the views within a data item
// Used to cache the views within the item layout for fast access
class DeckViewHolder extends RecyclerView.ViewHolder { class DeckViewHolder extends RecyclerView.ViewHolder {
// Your holder should contain a member variable
// for any view that will be set as you render a row
private final View view; private final View view;
private final View headView; private final View headView;
private final View textlayout; private final View textlayout;
...@@ -22,8 +26,11 @@ class DeckViewHolder extends RecyclerView.ViewHolder { ...@@ -22,8 +26,11 @@ class DeckViewHolder extends RecyclerView.ViewHolder {
private long mCardType; private long mCardType;
private DeckItemType mItemType; private DeckItemType mItemType;
// Create a constructor that accepts the entire item row
// and does the view lookups to find each subview
public DeckViewHolder(View view) { public DeckViewHolder(View view) {
// Stores the view in a public final member variable that can be used
// to access the context from any ViewHolder instance.
super(view); super(view);
this.view = view; this.view = view;
view.setTag(view.getId(), this); view.setTag(view.getId(), this);
...@@ -88,6 +95,10 @@ class DeckViewHolder extends RecyclerView.ViewHolder { ...@@ -88,6 +95,10 @@ class DeckViewHolder extends RecyclerView.ViewHolder {
// imageLoader.$(outFile, cardImage, outFile.getName().endsWith(Constants.BPG), 0, null); // imageLoader.$(outFile, cardImage, outFile.getName().endsWith(Constants.BPG), 0, null);
} }
/**
* 只展示分隔标签(例如“主卡组:60怪兽:21“),隐藏掉卡图ImageView
* @param text
*/
public void setText(String text) { public void setText(String text) {
labelText.setText(text); labelText.setText(text);
textlayout.setVisibility(View.VISIBLE); textlayout.setVisibility(View.VISIBLE);
...@@ -95,6 +106,9 @@ class DeckViewHolder extends RecyclerView.ViewHolder { ...@@ -95,6 +106,9 @@ class DeckViewHolder extends RecyclerView.ViewHolder {
rightImage.setVisibility(View.GONE); rightImage.setVisibility(View.GONE);
} }
/**
* 展示卡图,隐藏分隔标签
*/
public void showImage() { public void showImage() {
textlayout.setVisibility(View.GONE); textlayout.setVisibility(View.GONE);
cardImage.setVisibility(View.VISIBLE); cardImage.setVisibility(View.VISIBLE);
......
...@@ -184,7 +184,7 @@ public class MainActivity extends HomeActivity implements BottomNavigationBar.On ...@@ -184,7 +184,7 @@ public class MainActivity extends HomeActivity implements BottomNavigationBar.On
enableStart = error >= 0; enableStart = error >= 0;
getGameUriManager().doIntent(getIntent()); getGameUriManager().doIntent(getIntent());
}); });
} else { } else {//外部选择通过本应用打开ydk文件,会执行到这里
getGameUriManager().doIntent(intent); getGameUriManager().doIntent(intent);
} }
} }
......
...@@ -14,6 +14,8 @@ import android.util.Log; ...@@ -14,6 +14,8 @@ import android.util.Log;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.tencent.smtt.sdk.WebView; import com.tencent.smtt.sdk.WebView;
import org.json.JSONArray; import org.json.JSONArray;
...@@ -40,6 +42,7 @@ import cn.garymb.ygomobile.ui.plus.DefWebViewClient; ...@@ -40,6 +42,7 @@ import cn.garymb.ygomobile.ui.plus.DefWebViewClient;
import cn.garymb.ygomobile.utils.DeckUtil; import cn.garymb.ygomobile.utils.DeckUtil;
import cn.garymb.ygomobile.utils.JsonUtil; import cn.garymb.ygomobile.utils.JsonUtil;
import cn.garymb.ygomobile.utils.OkhttpUtil; import cn.garymb.ygomobile.utils.OkhttpUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Callback; import okhttp3.Callback;
import okhttp3.Response; import okhttp3.Response;
...@@ -67,6 +70,7 @@ public class MyCard { ...@@ -67,6 +70,7 @@ public class MyCard {
public static final String ARG_UPDATE_AT = "updated_at"; public static final String ARG_UPDATE_AT = "updated_at";
public static final String ARG_URL = "url"; public static final String ARG_URL = "url";
public static final String ARG_NEWS = "news"; public static final String ARG_NEWS = "news";
public static final String URL_MC_SIGN_UP = "https://accounts.moecube.com/signup";
public static final String URL_MC_LOGOUT = "https://accounts.moecube.com/signin"; public static final String URL_MC_LOGOUT = "https://accounts.moecube.com/signin";
private final DefWebViewClient mDefWebViewClient = new DefWebViewClient() { private final DefWebViewClient mDefWebViewClient = new DefWebViewClient() {
@Override @Override
...@@ -336,7 +340,11 @@ public class MyCard { ...@@ -336,7 +340,11 @@ public class MyCard {
McUser mcUser = null; McUser mcUser = null;
if (TextUtils.isEmpty(exception)) { if (TextUtils.isEmpty(exception)) {
mcUser = new Gson().fromJson(userInfo, McUser.class); mcUser = new Gson().fromJson(userInfo, McUser.class);
UserManagement.getDx().setMcUser(mcUser); UserManagement.getDx().setMcUser(mcUser);//登录后,mcUser信息存在此
//另外保存一份token和id信息作为其他登录验证场景调用
SharedPreferenceUtil.setServerToken(mcUser.getToken());
SharedPreferenceUtil.setServerUserId(mcUser.getExternal_id());
SharedPreferenceUtil.setMyCardUserName(mcUser.getUsername());
} }
if (mListener!=null) if (mListener!=null)
mListener.onLogin(mcUser,exception); mListener.onLogin(mcUser,exception);
......
...@@ -58,6 +58,7 @@ import cn.garymb.ygomobile.ui.mycard.mcchat.management.ServiceManagement; ...@@ -58,6 +58,7 @@ import cn.garymb.ygomobile.ui.mycard.mcchat.management.ServiceManagement;
import cn.garymb.ygomobile.utils.DownloadUtil; import cn.garymb.ygomobile.utils.DownloadUtil;
import cn.garymb.ygomobile.utils.FileUtils; import cn.garymb.ygomobile.utils.FileUtils;
import cn.garymb.ygomobile.utils.HandlerUtil; import cn.garymb.ygomobile.utils.HandlerUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGOUtil; import cn.garymb.ygomobile.utils.YGOUtil;
import cn.garymb.ygomobile.utils.glide.GlideCompat; import cn.garymb.ygomobile.utils.glide.GlideCompat;
import ocgcore.DataManager; import ocgcore.DataManager;
......
...@@ -10,8 +10,8 @@ public class McUser implements Serializable { ...@@ -10,8 +10,8 @@ public class McUser implements Serializable {
private int id; private int id;
private int external_id; private int external_id;
private String username; private String username;
//不要用
private String name; private String token;
private String email; private String email;
private String avatar_url; private String avatar_url;
private boolean admin; private boolean admin;
...@@ -57,17 +57,12 @@ public class McUser implements Serializable { ...@@ -57,17 +57,12 @@ public class McUser implements Serializable {
this.username = username; this.username = username;
} }
/** public String getToken() {
* 不要用这个,用getUserName return token;
* @return
*/
@Deprecated
public String getName() {
return name;
} }
public void setName(String name) { public void setToken(String token) {
this.name = name; this.token = token;
} }
public String getEmail() { public String getEmail() {
......
...@@ -72,7 +72,7 @@ public class ChatMessage { ...@@ -72,7 +72,7 @@ public class ChatMessage {
this.avatar = getAvatarUrl(name); this.avatar = getAvatarUrl(name);
} }
public String getAvatarUrl(String userName) { public static String getAvatarUrl(String userName) {
return "https://sapi.moecube.com:444/avatar/avatar/" + userName + "/100/ygomobile.png"; return "https://sapi.moecube.com:444/avatar/avatar/" + userName + "/100/ygomobile.png";
} }
......
...@@ -2,6 +2,8 @@ package cn.garymb.ygomobile.ui.mycard.mcchat.management; ...@@ -2,6 +2,8 @@ package cn.garymb.ygomobile.ui.mycard.mcchat.management;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Handler; import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
...@@ -20,7 +22,9 @@ import org.jxmpp.stringprep.XmppStringprepException; ...@@ -20,7 +22,9 @@ import org.jxmpp.stringprep.XmppStringprepException;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import cn.garymb.ygomobile.ui.mycard.base.OnJoinChatListener; import cn.garymb.ygomobile.ui.mycard.base.OnJoinChatListener;
import cn.garymb.ygomobile.ui.mycard.bean.McUser; import cn.garymb.ygomobile.ui.mycard.bean.McUser;
...@@ -45,142 +49,121 @@ public class ServiceManagement { ...@@ -45,142 +49,121 @@ public class ServiceManagement {
public static final int CHAT_USER_NULL = 8; public static final int CHAT_USER_NULL = 8;
private static final ServiceManagement su = new ServiceManagement(); private static final ServiceManagement su = new ServiceManagement();
private XMPPTCPConnection con;
private MultiUserChat muc;
private boolean isConnected = false;
private boolean isListener = false;
private boolean isStartLoading=false;
private final List<ChatMessage> chatMessageList; private final List<ChatMessage> chatMessageList;
private final List<ChatListener> chatListenerList; private final ConcurrentHashMap<Integer, ChatListener> chatListenerList;
private final List<OnJoinChatListener> joinChatListenerList; private final ConcurrentHashMap<Integer, OnJoinChatListener> joinChatListenerList;
private int chatListenerId = 0;
private int joinChatListenerId = 0;
@SuppressLint("HandlerLeak") @SuppressLint("HandlerLeak")
Handler han = new Handler() { private final Handler han = new Handler(Looper.getMainLooper()) {
@Override @Override
public void handleMessage(android.os.Message msg) { public void handleMessage(Message msg) {
// TODO: Implement this method
super.handleMessage(msg);
int i = 0;
switch (msg.what) { switch (msg.what) {
case TYPE_ADD_MESSAGE: case TYPE_ADD_MESSAGE:
while (i < chatListenerList.size()) { broadcastChatMessage((ChatMessage) msg.obj);
ChatListener chatListener = chatListenerList.get(i);
if (chatListener.isListenerEffective()) {
chatListener.addChatMessage((ChatMessage) msg.obj);
i++;
} else {
chatListenerList.remove(i);
}
}
break; break;
case TYPE_RE_LOGIN: case TYPE_RE_LOGIN:
while (i < chatListenerList.size()) { broadcastReLogin((boolean) msg.obj);
ChatListener chatListener = chatListenerList.get(i);
if (chatListener.isListenerEffective()) {
chatListener.reChatLogin((boolean) msg.obj);
i++;
} else {
chatListenerList.remove(i);
}
}
break; break;
case TYPE_RE_JOIN: case TYPE_RE_JOIN:
broadcastReJoin((boolean) msg.obj);
while (i < chatListenerList.size()) {
ChatListener chatListener = chatListenerList.get(i);
if (chatListener.isListenerEffective()) {
chatListener.reChatJoin((boolean) msg.obj);
i++;
} else {
chatListenerList.remove(i);
}
}
break; break;
case CHAT_LOGIN_EXCEPTION_RE: case CHAT_LOGIN_EXCEPTION_RE:
// while (i < joinChatListenerList.size()) { // 处理重新登录异常的逻辑
// OnJoinChatListener ou = joinChatListenerList.get(i); //for (OnJoinChatListener listener : joinChatListenerList.values()) {
// if (ou.isListenerEffective()) { // if (listener != null && listener.isListenerEffective()) {
// ou.onLoginExceptionClickRe(); // listener.onLoginExceptionClickRe();
// i++; // }
// } else { //}
// joinChatListenerList.remove(i); //break;
// }
// }
// break;
case CHAT_LOGIN_OK: case CHAT_LOGIN_OK:
while (i < joinChatListenerList.size()) { for (OnJoinChatListener listener : joinChatListenerList.values()) {
OnJoinChatListener onJoinChatListener = joinChatListenerList.get(i); if (listener != null && listener.isListenerEffective()) {
if (onJoinChatListener.isListenerEffective()) { listener.onChatLogin(null);
onJoinChatListener.onChatLogin(null);
i++;
} else {
joinChatListenerList.remove(i);
} }
} }
break; break;
case CHAT_LOGIN_EXCEPTION: case CHAT_LOGIN_EXCEPTION:
while (i < joinChatListenerList.size()) { for (OnJoinChatListener listener : joinChatListenerList.values()) {
OnJoinChatListener onJoinChatListener = joinChatListenerList.get(i); if (listener != null && listener.isListenerEffective()) {
if (onJoinChatListener.isListenerEffective()) { listener.onChatLogin(msg.obj + "");
onJoinChatListener.onChatLogin(msg.obj + "");
i++;
} else {
joinChatListenerList.remove(i);
} }
} }
break; break;
case CHAT_LOGIN_LOADING: case CHAT_LOGIN_LOADING:
while (i < joinChatListenerList.size()) { for (OnJoinChatListener listener : joinChatListenerList.values()) {
OnJoinChatListener onJoinChatListener = joinChatListenerList.get(i); if (listener != null && listener.isListenerEffective()) {
if (onJoinChatListener.isListenerEffective()) { listener.onChatLoginLoading();
onJoinChatListener.onChatLoginLoading();
i++;
} else {
joinChatListenerList.remove(i);
} }
} }
break; break;
case CHAT_JOIN_ROOM_LOADING: case CHAT_JOIN_ROOM_LOADING:
while (i < joinChatListenerList.size()) { for (OnJoinChatListener listener : joinChatListenerList.values()) {
OnJoinChatListener onJoinChatListener = joinChatListenerList.get(i); if (listener != null && listener.isListenerEffective()) {
if (onJoinChatListener.isListenerEffective()) { listener.onJoinRoomLoading();
onJoinChatListener.onJoinRoomLoading();
i++;
} else {
joinChatListenerList.remove(i);
} }
} }
break; break;
case CHAT_USER_NULL: case CHAT_USER_NULL:
while (i < joinChatListenerList.size()) { for (OnJoinChatListener listener : joinChatListenerList.values()) {
OnJoinChatListener onJoinChatListener = joinChatListenerList.get(i); if (listener != null && listener.isListenerEffective()) {
if (onJoinChatListener.isListenerEffective()) { listener.onChatUserNull();
onJoinChatListener.onChatUserNull();
i++;
} else {
joinChatListenerList.remove(i);
} }
} }
break; break;
} }
} }
private void broadcastChatMessage(ChatMessage message) {
for (ChatListener listener : chatListenerList.values()) {
if (listener != null && listener.isListenerEffective()) {
listener.addChatMessage(message);
}
}
}
private void broadcastReLogin(boolean state) {
for (ChatListener listener : chatListenerList.values()) {
if (listener != null && listener.isListenerEffective()) {
listener.reChatLogin(state);
}
}
}
private void broadcastReJoin(boolean state) {
for (ChatListener listener : chatListenerList.values()) {
if (listener != null && listener.isListenerEffective()) {
listener.reChatJoin(state);
}
}
}
}; };
private XMPPTCPConnection con;
private MultiUserChat muc;
private boolean isConnected = false;
private boolean isListener = false;
private boolean isStartLoading = false;
private ServiceManagement() { private ServiceManagement() {
chatMessageList = new ArrayList<>(); chatMessageList = Collections.synchronizedList(new ArrayList<>());
chatListenerList = new ArrayList<>(); chatListenerList = new ConcurrentHashMap<>();
joinChatListenerList = new ArrayList<>(); joinChatListenerList = new ConcurrentHashMap<>();
} }
public static ServiceManagement getDx() { public static ServiceManagement getDx() {
return su; return su;
} }
public void addListener(ChatListener c) { public int addListener(ChatListener c) {
chatListenerList.add(c); int id = ++chatListenerId;
chatListenerList.put(id, c);
return id;
}
public void removeListener(int id) {
chatListenerList.remove(id);
} }
public List<ChatMessage> getData() { public List<ChatMessage> getData() {
...@@ -233,28 +216,36 @@ public class ServiceManagement { ...@@ -233,28 +216,36 @@ public class ServiceManagement {
} }
public void sendMessage(String message) throws SmackException.NotConnectedException, InterruptedException { public void sendMessage(String message) throws SmackException.NotConnectedException, InterruptedException {
muc.sendMessage(message); if (muc != null && isListener) {
muc.sendMessage(message);
}
} }
public int getMemberNum(){ public int getMemberNum() {
if (!isListener) if (!isListener || muc == null)
return 0; return 0;
return muc.getOccupantsCount(); return muc.getOccupantsCount();
} }
public void joinChat() throws SmackException.NoResponseException, XMPPException.XMPPErrorException, MultiUserChatException.NotAMucServiceException, SmackException.NotConnectedException, XmppStringprepException, MultiUserChatException.MucAlreadyJoinedException, InterruptedException { public void joinChat() throws SmackException.NoResponseException, XMPPException.XMPPErrorException,
MultiUserChatException.NotAMucServiceException, SmackException.NotConnectedException,
XmppStringprepException, MultiUserChatException.MucAlreadyJoinedException, InterruptedException {
if (!isListener) { if (!isListener) {
McUser mcUser = UserManagement.getDx().getMcUser();
if (mcUser == null || TextUtils.isEmpty(mcUser.getUsername())) {
throw new IllegalStateException("User not logged in");
}
MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor(getCon()); MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor(getCon());
muc = multiUserChatManager.getMultiUserChat(JidCreate.entityBareFrom(GROUP_ADDRESS)); muc = multiUserChatManager.getMultiUserChat(JidCreate.entityBareFrom(GROUP_ADDRESS));
muc.createOrJoin(Resourcepart.from(UserManagement.getDx().getMcUser().getUsername())); muc.createOrJoin(Resourcepart.from(mcUser.getUsername()));
chatMessageList.clear(); chatMessageList.clear();
muc.addMessageListener(message -> { muc.addMessageListener(message -> {
Log.e("接收消息", "接收" + message); Log.e("接收消息", "接收" + message);
ChatMessage cm = ChatMessage.toChatMessage(message); ChatMessage cm = ChatMessage.toChatMessage(message);
if (cm != null) { if (cm != null) {
chatMessageList.add(cm); chatMessageList.add(cm);
HandlerUtil.sendMessage(han,TYPE_ADD_MESSAGE,cm); HandlerUtil.sendMessage(han, TYPE_ADD_MESSAGE, cm);
} }
}); });
setIsListener(true); setIsListener(true);
...@@ -262,23 +253,36 @@ public class ServiceManagement { ...@@ -262,23 +253,36 @@ public class ServiceManagement {
} }
public void setReLogin(boolean state) { public void setReLogin(boolean state) {
android.os.Message me = new android.os.Message(); Message me = new Message();
me.what = TYPE_RE_LOGIN; me.what = TYPE_RE_LOGIN;
me.obj = state; me.obj = state;
han.sendMessage(me); han.sendMessage(me);
} }
public void setReJoin(boolean state) { public void setReJoin(boolean state) {
android.os.Message me = new android.os.Message(); Message me = new Message();
me.what = TYPE_RE_JOIN; me.what = TYPE_RE_JOIN;
me.obj = state; me.obj = state;
han.sendMessage(me); han.sendMessage(me);
} }
public void disSerVice() { public void disSerVice() {
if (muc != null) {
try {
if (isListener) {
muc.leave();
}
} catch (SmackException.NotConnectedException | InterruptedException e) {
Log.e("ServiceManagement", "Error leaving MUC", e);
}
muc = null;
}
if (con != null) { if (con != null) {
con.disconnect(); con.disconnect();
con = null;
} }
setIsConnected(false); setIsConnected(false);
setIsListener(false); setIsListener(false);
} }
...@@ -290,28 +294,32 @@ public class ServiceManagement { ...@@ -290,28 +294,32 @@ public class ServiceManagement {
joinChatListenerList.clear(); joinChatListenerList.clear();
} }
public void addJoinRoomListener(OnJoinChatListener onJoinChatListener) { public int addJoinRoomListener(OnJoinChatListener onJoinChatListener) {
joinChatListenerList.add(onJoinChatListener); int id = ++joinChatListenerId;
joinChatListenerList.put(id, onJoinChatListener);
return id;
} }
public void removeJoinRoomListener(OnJoinChatListener onJoinChatListener) { public void removeJoinRoomListener(int id) {
joinChatListenerList.remove(onJoinChatListener); joinChatListenerList.remove(id);
} }
public void start() { public void start() {
if (isStartLoading) if (isStartLoading)
return; return;
isStartLoading=true; isStartLoading = true;
String name, password; String name, password;
McUser mcUser=UserManagement.getDx().getMcUser(); McUser mcUser = UserManagement.getDx().getMcUser();
name=mcUser.getUsername();
password=mcUser.getPassword(); if (mcUser == null || TextUtils.isEmpty(mcUser.getUsername()) || TextUtils.isEmpty(mcUser.getPassword())) {
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {
isStartLoading = false; isStartLoading = false;
han.sendEmptyMessage(CHAT_USER_NULL); han.sendEmptyMessage(CHAT_USER_NULL);
return; return;
} }
name = mcUser.getUsername();
password = mcUser.getPassword();
if (su.isListener()) { if (su.isListener()) {
isStartLoading = false; isStartLoading = false;
han.sendEmptyMessage(CHAT_LOGIN_OK); han.sendEmptyMessage(CHAT_LOGIN_OK);
...@@ -321,52 +329,51 @@ public class ServiceManagement { ...@@ -321,52 +329,51 @@ public class ServiceManagement {
new Thread(() -> { new Thread(() -> {
if (!su.isConnected()) { if (!su.isConnected()) {
han.sendEmptyMessage(CHAT_LOGIN_LOADING); han.sendEmptyMessage(CHAT_LOGIN_LOADING);
android.os.Message me = new android.os.Message(); Message me = new Message();
me.what = CHAT_LOGIN_EXCEPTION; me.what = CHAT_LOGIN_EXCEPTION;
try { try {
su.login(name, password); su.login(name, password);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); Log.e("ServiceManagement", "Login interrupted", e);
isStartLoading=false; isStartLoading = false;
me.obj = "InterruptedException:" + e; me.obj = "InterruptedException:" + e;
han.sendMessage(me); han.sendMessage(me);
} catch (IOException e) { } catch (IOException e) {
isStartLoading=false; Log.e("ServiceManagement", "IO error during login", e);
isStartLoading = false;
me.obj = "IOException:" + e; me.obj = "IOException:" + e;
e.printStackTrace();
han.sendMessage(me); han.sendMessage(me);
} catch (SmackException e) { } catch (SmackException e) {
isStartLoading=false; Log.e("ServiceManagement", "Smack error during login", e);
isStartLoading = false;
me.obj = "SmackException:" + e; me.obj = "SmackException:" + e;
e.printStackTrace();
han.sendMessage(me); han.sendMessage(me);
} catch (XMPPException e) { } catch (XMPPException e) {
isStartLoading=false; Log.e("ServiceManagement", "XMPP error during login", e);
isStartLoading = false;
me.obj = "XMPPException:" + e; me.obj = "XMPPException:" + e;
e.printStackTrace();
han.sendMessage(me); han.sendMessage(me);
} catch (Exception e) { } catch (Exception e) {
isStartLoading=false; Log.e("ServiceManagement", "Other error during login", e);
isStartLoading = false;
me.obj = "otherException:" + e; me.obj = "otherException:" + e;
e.printStackTrace();
han.sendMessage(me); han.sendMessage(me);
} }
} }
if (su.isConnected()) { if (su.isConnected()) {
han.sendEmptyMessage(CHAT_JOIN_ROOM_LOADING); han.sendEmptyMessage(CHAT_JOIN_ROOM_LOADING);
try { try {
su.joinChat(); su.joinChat();
isStartLoading=false; isStartLoading = false;
han.sendEmptyMessage(CHAT_LOGIN_OK); han.sendEmptyMessage(CHAT_LOGIN_OK);
} catch (Exception e) { } catch (Exception e) {
isStartLoading=false; Log.e("ServiceManagement", "Error joining chat", e);
isStartLoading = false;
HandlerUtil.sendMessage(han, CHAT_LOGIN_EXCEPTION, e); HandlerUtil.sendMessage(han, CHAT_LOGIN_EXCEPTION, e);
} }
} }
// TODO: Implement this method
}).start(); }).start();
} }
}
} \ No newline at end of file
...@@ -52,6 +52,11 @@ public class ImageUtil { ...@@ -52,6 +52,11 @@ public class ImageUtil {
show(context, url, im, null); show(context, url, im, null);
} }
/**
* 将图片变换为灰度图(变成灰白色)
* @param key
* @param imageView
*/
public static void setGrayImage(int key, ImageView imageView) { public static void setGrayImage(int key, ImageView imageView) {
ColorMatrix matrix = new ColorMatrix(); ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0); matrix.setSaturation(0);
......
...@@ -68,11 +68,18 @@ public class DeckUtil { ...@@ -68,11 +68,18 @@ public class DeckUtil {
} }
}; };
/**
* 生成卡组类型的list
*
* @param context
* @return
*/
public static List<DeckType> getDeckTypeList(Context context) { public static List<DeckType> getDeckTypeList(Context context) {
List<DeckType> deckTypeList = new ArrayList<>(); List<DeckType> deckTypeList = new ArrayList<>();
deckTypeList.add(new DeckType(YGOUtil.s(R.string.category_pack), AppsSettings.get().getPackDeckDir())); deckTypeList.add(new DeckType(YGOUtil.s(R.string.category_pack), AppsSettings.get().getPackDeckDir(), DeckType.ServerType.LOCAL));
deckTypeList.add(new DeckType(YGOUtil.s(R.string.category_windbot_deck), AppsSettings.get().getAiDeckDir())); deckTypeList.add(new DeckType(YGOUtil.s(R.string.category_windbot_deck), AppsSettings.get().getAiDeckDir(), DeckType.ServerType.LOCAL));
deckTypeList.add(new DeckType(YGOUtil.s(R.string.category_Uncategorized), AppsSettings.get().getDeckDir())); deckTypeList.add(new DeckType(YGOUtil.s(R.string.category_Uncategorized), AppsSettings.get().getDeckDir(), DeckType.ServerType.LOCAL));
File[] files = new File(AppsSettings.get().getDeckDir()).listFiles(); File[] files = new File(AppsSettings.get().getDeckDir()).listFiles();
if (files != null) { if (files != null) {
...@@ -138,6 +145,7 @@ public class DeckUtil { ...@@ -138,6 +145,7 @@ public class DeckUtil {
/** /**
* 根据卡组绝对路径获取卡组分类名称 * 根据卡组绝对路径获取卡组分类名称
*
* @param deckPath * @param deckPath
* @return * @return
*/ */
...@@ -149,19 +157,20 @@ public class DeckUtil { ...@@ -149,19 +157,20 @@ public class DeckUtil {
if (name.equals("pack") || name.equals("cacheDeck")) { if (name.equals("pack") || name.equals("cacheDeck")) {
//卡包 //卡包
return YGOUtil.s(R.string.category_pack); return YGOUtil.s(R.string.category_pack);
} else if (name.equals("Decks")&&lastName.equals(Constants.WINDBOT_PATH)) { } else if (name.equals("Decks") && lastName.equals(Constants.WINDBOT_PATH)) {
//ai卡组 //ai卡组
return YGOUtil.s(R.string.category_windbot_deck); return YGOUtil.s(R.string.category_windbot_deck);
} else if (name.equals("deck") && lastName.equals(Constants.PREF_DEF_GAME_DIR)) { } else if (name.equals("deck") && lastName.equals(Constants.PREF_DEF_GAME_DIR)) {
//如果是deck并且上一个目录是ygocore的话,保证不会把名字为deck的卡包识别为未分类 //如果是deck并且上一个目录是ygocore的话,保证不会把名字为deck的卡包识别为未分类
return YGOUtil.s(R.string.category_Uncategorized); return YGOUtil.s(R.string.category_Uncategorized);
} else { } else {
return name; return name;
} }
} }
return null; return null;
} }
//获取扩展卡的列表
public static List<DeckFile> getExpansionsDeckList() throws IOException { public static List<DeckFile> getExpansionsDeckList() throws IOException {
AppsSettings appsSettings = AppsSettings.get(); AppsSettings appsSettings = AppsSettings.get();
List<DeckFile> deckList = new ArrayList<>(); List<DeckFile> deckList = new ArrayList<>();
......
...@@ -9,7 +9,6 @@ import java.util.List; ...@@ -9,7 +9,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import cn.garymb.ygomobile.bean.Header;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Callback; import okhttp3.Callback;
import okhttp3.FormBody; import okhttp3.FormBody;
...@@ -26,89 +25,6 @@ public class OkhttpUtil { ...@@ -26,89 +25,6 @@ public class OkhttpUtil {
private static OkHttpClient okHttpClient; private static OkHttpClient okHttpClient;
public static void post(String address, Map<String, Object> map, Callback callback) {
post(address, map, null, null, 0, callback);
}
public static void post(String address, Map<String, Object> map, Header oyHeader, String tag, int timeout, Callback callback) {
post(address, map, null, oyHeader, tag, timeout, callback);
}
public static void post(String address, Map<String, Object> map, String cookie, Header oyHeader, String tag, int timeout, Callback callback) {
okHttpClient = new OkHttpClient();
if (timeout != 0)
okHttpClient = okHttpClient.newBuilder().connectTimeout(timeout, TimeUnit.SECONDS)//设置连接超时时间
.readTimeout(timeout, TimeUnit.SECONDS)//设置读取超时时间
.build();
MultipartBody.Builder builder1 = new MultipartBody.Builder();
if (map != null) {
builder1.setType(MultipartBody.FORM);
for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
String key = stringObjectEntry.getKey();
Object value = stringObjectEntry.getValue();
if (value instanceof List) {
List list = (List) value;
for (Object object : list) {
if (object instanceof File) {
File file = (File) object;
builder1.addFormDataPart(key
, file.getName(),
RequestBody.create(MediaType.parse("multipart/form-data"), file));
} else {
builder1.addFormDataPart(key, value.toString());
}
}
} else if (value instanceof File) {//如果请求的值是文件
File file = (File) value;
//MediaType.parse("application/octet-stream")以二进制的形式上传文件
builder1.addFormDataPart(key, file.getName(),
RequestBody.create(MediaType.parse("multipart/form-data"), file));
} else if (value instanceof String[]) {
String[] list = (String[]) value;
for (Object object : list) {
if (object instanceof File) {
File file = (File) object;
builder1.addFormDataPart(key
, file.getName(),
RequestBody.create(MediaType.parse("multipart/form-data"), file));
} else {
Log.e("OkHttpUtil", key + "添加数组" + object.toString());
builder1.addFormDataPart(key, object.toString());
}
}
// Log.e("OkhttpUtil","添加数组"+new Gson().toJson(value));
} else {
//如果请求的值是string类型
builder1.addFormDataPart(key, value.toString());
}
}
}
Request.Builder request = new Request.Builder()
.url(address);
if (oyHeader != null)
request = request.header(oyHeader.getName(), oyHeader.getValue());
// request.addHeader("Connection", "keep-alive");
if (!TextUtils.isEmpty(tag))
request = request.tag(tag);
if (map != null)
request.post(builder1.build());
else
request.post(okhttp3.internal.Util.EMPTY_REQUEST);
// Log.e("OkhttpUtil","post请求:"+builder1.build().toString());
if (!TextUtils.isEmpty(cookie)) {
request.addHeader("cookie", cookie);
}
okHttpClient.newCall(request.build()).enqueue(callback);
}
public static void put(String address, Map<String, Object> map, String cookie, Callback callback) { public static void put(String address, Map<String, Object> map, String cookie, Callback callback) {
OkHttpClient.Builder client = new OkHttpClient.Builder(); OkHttpClient.Builder client = new OkHttpClient.Builder();
...@@ -198,22 +114,27 @@ public class OkhttpUtil { ...@@ -198,22 +114,27 @@ public class OkhttpUtil {
client.newCall(request.build()).enqueue(callback); client.newCall(request.build()).enqueue(callback);
} }
public static Response synchronousGet(String address, Map<String, Object> map, String cookie) throws IOException { public static Response synchronousGet(String address, Map<String, Object> paramMap, Map<String, String> headers) throws IOException {
OkHttpClient client = new OkHttpClient(); OkHttpClient client = new OkHttpClient();
HttpUrl.Builder httpBuilder = HttpUrl.parse(address).newBuilder(); HttpUrl.Builder httpBuilder = HttpUrl.parse(address).newBuilder();
if (map != null) { if (paramMap != null) {
for (Map.Entry<String, Object> param : map.entrySet()) { for (Map.Entry<String, Object> param : paramMap.entrySet()) {
httpBuilder.addQueryParameter(param.getKey(), param.getValue().toString()); httpBuilder.addQueryParameter(param.getKey(), param.getValue().toString());
} }
} }
Request.Builder request = new Request.Builder() Request.Builder request = new Request.Builder()
.url(httpBuilder.build()); .url(httpBuilder.build());
Log.e("OkhttpUtil", "为" + httpBuilder.build()); Log.e("OkhttpUtil", "get " + httpBuilder.build());
if (!TextUtils.isEmpty(cookie)) { if (headers != null) {
request.addHeader("cookie", cookie); for (Map.Entry<String, String> header : headers.entrySet()) {
request.addHeader(header.getKey(), header.getValue().toString());
}
} }
// if (!TextUtils.isEmpty(cookie)) {
// request.addHeader("cookie", cookie);
// }
return client.newCall(request.build()).execute(); return client.newCall(request.build()).execute();
} }
...@@ -254,10 +175,8 @@ public class OkhttpUtil { ...@@ -254,10 +175,8 @@ public class OkhttpUtil {
public static void post(String url, String json, String cookie, Callback callback) { public static void post(String url, String json, String cookie, Callback callback) {
OkHttpClient okHttpClient = new OkHttpClient(); OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8") RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json);
, json); Request.Builder request = new Request.Builder().url(url);//请求的url
Request.Builder request = new Request.Builder()
.url(url);//请求的url
if (TextUtils.isEmpty(json)) if (TextUtils.isEmpty(json))
request.post(okhttp3.internal.Util.EMPTY_REQUEST); request.post(okhttp3.internal.Util.EMPTY_REQUEST);
else else
...@@ -281,11 +200,15 @@ public class OkhttpUtil { ...@@ -281,11 +200,15 @@ public class OkhttpUtil {
} }
} }
public static void postJson(String url, String json, Callback callback) { /**
postJson(url, json, null, null, null, 0, callback); * 阻塞方法,POST推送json
} *
* @param url
public static void postJson(String url, String json, String cookie, Header oyHeader, String tag, int timeout, Callback callback) { * @param json 可以传入null或空字符串,均代表不需要发送json
* @param headers 可以传入null
* @param timeout 可以为0,为0代表使用默认值
*/
public static Response postJson(String url, String json, Map<String, String> headers, int timeout) throws IOException {
okHttpClient = new OkHttpClient(); okHttpClient = new OkHttpClient();
if (timeout != 0) if (timeout != 0)
...@@ -294,26 +217,23 @@ public class OkhttpUtil { ...@@ -294,26 +217,23 @@ public class OkhttpUtil {
.build(); .build();
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8") Request.Builder request = new Request.Builder().url(url);//请求的url
, json); if (json == null || TextUtils.isEmpty(json)) {
Request.Builder request = new Request.Builder()
.url(url);//请求的url
if (TextUtils.isEmpty(json))
request.post(okhttp3.internal.Util.EMPTY_REQUEST); request.post(okhttp3.internal.Util.EMPTY_REQUEST);
else } else {
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json);
request.post(requestBody); request.post(requestBody);
if (oyHeader != null) }
request = request.header(oyHeader.getName(), oyHeader.getValue());
if (!TextUtils.isEmpty(tag))
request = request.tag(tag);
if (!TextUtils.isEmpty(cookie)) { if (headers != null) {
request.addHeader("cookie", cookie); for (Map.Entry<String, String> header : headers.entrySet()) {
request.addHeader(header.getKey(), header.getValue().toString());
}
} }
Log.e("OkhttpUtil", json + " 状态 " + request.build()); Log.e("OkhttpUtil", json + " 状态 " + request.build());
okHttpClient.newCall(request.build()).enqueue(callback); return okHttpClient.newCall(request.build()).execute();
} }
/** /**
......
...@@ -194,6 +194,31 @@ public class SharedPreferenceUtil { ...@@ -194,6 +194,31 @@ public class SharedPreferenceUtil {
getShareType().edit().putInt("deckEditType", type).apply(); getShareType().edit().putInt("deckEditType", type).apply();
} }
public static String getServerToken() {
return getShareRecord().getString("server_token", null);
}
public static boolean setServerToken(String token) {
return getShareRecord().edit().putString("server_token", token).commit();
}
public static Integer getServerUserId() {
return getShareType().getInt("server_user_id", -1);
}
public static void setServerUserId(int userId) {
getShareType().edit().putInt("server_user_id", userId).apply();
}
public static boolean deleteServerToken() {
// Get SharedPreferences instance
SharedPreferences sharedPreferences = getShareRecord();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.remove("server_token"); // Replace "key_name" with your actual key
return editor.commit(); // Or editor.commit() if you need immediate results
}
public static String[] getArray(int id) { public static String[] getArray(int id) {
return App.get().getResources().getStringArray(id); return App.get().getResources().getStringArray(id);
} }
......
...@@ -45,15 +45,56 @@ import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil; ...@@ -45,15 +45,56 @@ import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil;
import cn.garymb.ygomobile.ui.plus.DialogPlus; import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.utils.recyclerview.DeckTypeTouchHelperCallback; import cn.garymb.ygomobile.utils.recyclerview.DeckTypeTouchHelperCallback;
public class YGODialogUtil { public class YGODeckDialogUtil {
private static final String TAG = "YGODialogUtil"; /* public enum DeckTypeEnum {
CARD_PACK(0, "PACK"),
WINDBOT(1, "WINDBOT"),
Uncategorized(2, "Uncategorized"),
ONLINE(3, "Online");
private final int code;
private final String description;
// Constructor
DeckTypeEnum(int code, String description) {
this.code = code;
this.description = description;
}
// Getter methods
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
// Lookup by code
public static DeckTypeEnum fromCode(int code) {
for (DeckTypeEnum status : DeckTypeEnum.values()) {
if (status.code == code) {
return status;
}
}
throw new IllegalArgumentException("No DeckTypeEnum found for code: " + code);
}
}
*/
private static final String TAG = "YGODeckDialogUtil";
/**
* @param context
* @param selectDeckPath 卡组路径。由调用方传入,本dialog根据selectDeckPath的值来确定“默认选中的卡组分类”。
* @param onDeckMenuListener
*/
public static void dialogDeckSelect(Context context, String selectDeckPath, OnDeckMenuListener onDeckMenuListener) { public static void dialogDeckSelect(Context context, String selectDeckPath, OnDeckMenuListener onDeckMenuListener) {
ViewHolder viewHolder = new ViewHolder(context, selectDeckPath, onDeckMenuListener); ViewHolder viewHolder = new ViewHolder(context, selectDeckPath, onDeckMenuListener);
viewHolder.show(); viewHolder.show();
} }
//注册listener,发生点击卡组事件后,通知外部的activity进行对应的显示更新
public interface OnDeckMenuListener { public interface OnDeckMenuListener {
void onDeckSelect(DeckFile deckFile); void onDeckSelect(DeckFile deckFile);
...@@ -67,10 +108,20 @@ public class YGODialogUtil { ...@@ -67,10 +108,20 @@ public class YGODialogUtil {
} }
public interface OnDeckDialogListener {
void onDismiss();
void onShow();
}
public interface OnDeckTypeListener { public interface OnDeckTypeListener {
void onDeckTypeListener(int position); void onDeckTypeListener(int position);
} }
/**
* 封装DialogPlus,在本类中调用DialogPlus.setContentView()
*/
private static class ViewHolder { private static class ViewHolder {
private final int IMAGE_MOVE = 0; private final int IMAGE_MOVE = 0;
...@@ -89,18 +140,23 @@ public class YGODialogUtil { ...@@ -89,18 +140,23 @@ public class YGODialogUtil {
private final TextView tv_move; private final TextView tv_move;
private final TextView tv_copy; private final TextView tv_copy;
private final TextView tv_del; private final TextView tv_del;
private final TextSelectAdapter<DeckType> typeAdp; private final TextSelectAdapter<DeckType> typeAdp;//卡组dialog中,左列的adapter
private final DeckListAdapter<DeckFile> deckAdp; private final DeckListAdapter<DeckFile> deckAdp;//卡组dialog中,右列的adapter
private final DeckListAdapter<DeckFile> resultListAdapter; private final DeckListAdapter<DeckFile> resultListAdapter;
private final List<DeckFile> allDeckList; private final List<DeckFile> allDeckList;//存储所有卡组DeckFile,用于支持“根据关键词搜索卡组”功能
private final RecyclerView rv_type, rv_deck, rv_result_list; private final RecyclerView rv_type, rv_deck, rv_result_list;
private final List<DeckFile> resultList; private final List<DeckFile> resultList;//存储卡组“根据关键词搜索”的结果
private final DialogPlus ygoDialog; private final DialogPlus ygoDialog;
/**
* @param context
* @param selectDeckPath 外部传入当前选中的卡组路径
* @param onDeckMenuListener
*/
public ViewHolder(Context context, String selectDeckPath, OnDeckMenuListener onDeckMenuListener) { public ViewHolder(Context context, String selectDeckPath, OnDeckMenuListener onDeckMenuListener) {
ygoDialog = new DialogPlus(context); ygoDialog = new DialogPlus(context);
ygoDialog.setContentView(R.layout.dialog_deck_select); ygoDialog.setContentView(R.layout.fragment_deck_select);
ygoDialog.setTitle(R.string.category_manager); ygoDialog.setTitle(R.string.category_manager);
allDeckList = new ArrayList<>(); allDeckList = new ArrayList<>();
...@@ -131,9 +187,10 @@ public class YGODialogUtil { ...@@ -131,9 +187,10 @@ public class YGODialogUtil {
List<DeckType> typeList = DeckUtil.getDeckTypeList(context); List<DeckType> typeList = DeckUtil.getDeckTypeList(context);
int typeSelectPosition = 2; int typeSelectPosition = 2;//卡组分类选择,默认值为2(未分类卡组)。0代表“卡包展示”,1代表“人机卡组”
int deckSelectPosition = -1; int deckSelectPosition = -1;
List<DeckFile> deckList; List<DeckFile> deckList; //存储当前卡组分类下的所有卡组
//根据卡组路径得到该卡组所属分类
if (!TextUtils.isEmpty(selectDeckPath)) { if (!TextUtils.isEmpty(selectDeckPath)) {
File file = new File(selectDeckPath); File file = new File(selectDeckPath);
if (file.exists()) { if (file.exists()) {
...@@ -147,6 +204,7 @@ public class YGODialogUtil { ...@@ -147,6 +204,7 @@ public class YGODialogUtil {
typeSelectPosition = 1; typeSelectPosition = 1;
} else if (cateName.equals("deck") && parentName.equals(Constants.PREF_DEF_GAME_DIR)) { } else if (cateName.equals("deck") && parentName.equals(Constants.PREF_DEF_GAME_DIR)) {
//如果是deck并且上一个目录是ygocore的话,保证不会把名字为deck的卡包识别为未分类 //如果是deck并且上一个目录是ygocore的话,保证不会把名字为deck的卡包识别为未分类
typeSelectPosition = 2;
} else { } else {
//其他卡包 //其他卡包
for (int i = 3; i < typeList.size(); i++) { for (int i = 3; i < typeList.size(); i++) {
...@@ -159,11 +217,14 @@ public class YGODialogUtil { ...@@ -159,11 +217,14 @@ public class YGODialogUtil {
} }
} }
} }
//根据卡组分类查出属于该分类下的所有卡组
deckList = DeckUtil.getDeckList(typeList.get(typeSelectPosition).getPath()); deckList = DeckUtil.getDeckList(typeList.get(typeSelectPosition).getPath());
for (int i = 0; i < typeList.size(); i++) { for (int i = 0; i < typeList.size(); i++) {
allDeckList.addAll(DeckUtil.getDeckList(typeList.get(i).getPath()));//把所有分类里的卡组全部纳入,用于关键词查询目标 if (typeList.get(i).isLocal()) {
allDeckList.addAll(DeckUtil.getDeckList(typeList.get(i).getPath()));//把所有分类里的卡组全部纳入,用于关键词查询目标
}//在线卡组对应的项的path是空字符串
} }
if (typeSelectPosition == 0) { if (typeSelectPosition == 0) {//如果选中卡包,判断是否开启了先行卡,是的话加载先行卡
if (AppsSettings.get().isReadExpansions()) { if (AppsSettings.get().isReadExpansions()) {
try { try {
deckList.addAll(0, DeckUtil.getExpansionsDeckList());//置顶ypk缓存的cacheDeck下的先行卡ydk deckList.addAll(0, DeckUtil.getExpansionsDeckList());//置顶ypk缓存的cacheDeck下的先行卡ydk
...@@ -194,6 +255,7 @@ public class YGODialogUtil { ...@@ -194,6 +255,7 @@ public class YGODialogUtil {
} }
} }
deckAdp.notifyDataSetChanged(); deckAdp.notifyDataSetChanged();
} }
}); });
deckAdp.setOnItemSelectListener(new DeckListAdapter.OnItemSelectListener<DeckFile>() { deckAdp.setOnItemSelectListener(new DeckListAdapter.OnItemSelectListener<DeckFile>() {
...@@ -211,10 +273,13 @@ public class YGODialogUtil { ...@@ -211,10 +273,13 @@ public class YGODialogUtil {
} }
} }
}); });
//对话框中长点击某一卡组名称后,触发该事件
deckAdp.setOnItemLongClickListener(new OnItemLongClickListener() { deckAdp.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override @Override
public boolean onItemLongClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) { public boolean onItemLongClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) {
if (deckAdp.isSelect() || typeAdp.getSelectPosition() == 0) DeckFile item = (DeckFile) adapter.getItem(position);
//即使为local,也有可能为卡包预览,因此过滤掉selectposition==0
if (deckAdp.isSelect() || !item.isLocal() || typeAdp.getSelectPosition() == 0)
return true; return true;
deckAdp.setManySelect(true); deckAdp.setManySelect(true);
...@@ -503,6 +568,9 @@ public class YGODialogUtil { ...@@ -503,6 +568,9 @@ public class YGODialogUtil {
} }
} }
/**
* 根据et_input_deck_name的当前值,在allDeckList中搜索卡组
*/
private void searchDeck() { private void searchDeck() {
resultList.clear(); resultList.clear();
et_input_deck_name.clearFocus(); et_input_deck_name.clearFocus();
...@@ -526,6 +594,13 @@ public class YGODialogUtil { ...@@ -526,6 +594,13 @@ public class YGODialogUtil {
return types; return types;
} }
/**
* 从deckList中检索包含keyword的卡组
*
* @param keyword
* @param deckList
* @return
*/
private List<DeckFile> getResultList(String keyword, List<DeckFile> deckList) { private List<DeckFile> getResultList(String keyword, List<DeckFile> deckList) {
List<DeckFile> resultList = new ArrayList<>(); List<DeckFile> resultList = new ArrayList<>();
for (int i = 0; i < deckList.size(); i++) { for (int i = 0; i < deckList.size(); i++) {
...@@ -557,6 +632,7 @@ public class YGODialogUtil { ...@@ -557,6 +632,7 @@ public class YGODialogUtil {
return moveTypeList; return moveTypeList;
} }
//将界面上的iv_move、iv_del、iv_copy等图标颜色恢复,启用其点击事件
private void showAllDeckUtil() { private void showAllDeckUtil() {
ImageUtil.reImageColor(IMAGE_MOVE, iv_move);//可用时用原图标色 ImageUtil.reImageColor(IMAGE_MOVE, iv_move);//可用时用原图标色
ImageUtil.reImageColor(IMAGE_DEL, iv_del); ImageUtil.reImageColor(IMAGE_DEL, iv_del);
...@@ -569,6 +645,7 @@ public class YGODialogUtil { ...@@ -569,6 +645,7 @@ public class YGODialogUtil {
ll_move.setEnabled(true); ll_move.setEnabled(true);
} }
//将界面上的iv_move、iv_del、iv_copy等图标颜色改为灰色,禁用其点击事件
private void hideAllDeckUtil() { private void hideAllDeckUtil() {
ImageUtil.setGrayImage(IMAGE_MOVE, iv_move); ImageUtil.setGrayImage(IMAGE_MOVE, iv_move);
ImageUtil.setGrayImage(IMAGE_DEL, iv_del); ImageUtil.setGrayImage(IMAGE_DEL, iv_del);
...@@ -581,6 +658,7 @@ public class YGODialogUtil { ...@@ -581,6 +658,7 @@ public class YGODialogUtil {
ll_move.setEnabled(false); ll_move.setEnabled(false);
} }
//将界面上的iv_copy图标颜色恢复,启用其点击事件
private void showCopyDeckUtil() { private void showCopyDeckUtil() {
ImageUtil.setGrayImage(IMAGE_MOVE, iv_move); ImageUtil.setGrayImage(IMAGE_MOVE, iv_move);
ImageUtil.setGrayImage(IMAGE_DEL, iv_del); ImageUtil.setGrayImage(IMAGE_DEL, iv_del);
...@@ -593,6 +671,7 @@ public class YGODialogUtil { ...@@ -593,6 +671,7 @@ public class YGODialogUtil {
ll_move.setEnabled(false); ll_move.setEnabled(false);
} }
//清除选中卡组的记录,隐藏对卡组进行复制、移动、删除的控件
private void clearDeckSelect() { private void clearDeckSelect() {
deckAdp.setManySelect(false); deckAdp.setManySelect(false);
hideAllDeckUtil(); hideAllDeckUtil();
...@@ -609,6 +688,10 @@ public class YGODialogUtil { ...@@ -609,6 +688,10 @@ public class YGODialogUtil {
ygoDialog.dismiss(); ygoDialog.dismiss();
} }
public void hide() {
if (ygoDialog != null && ygoDialog.isShowing())
ygoDialog.hide();
}
} }
} }
...@@ -9,16 +9,16 @@ import androidx.recyclerview.widget.RecyclerView; ...@@ -9,16 +9,16 @@ import androidx.recyclerview.widget.RecyclerView;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.adapters.TextSelectAdapter; import cn.garymb.ygomobile.ui.adapters.TextSelectAdapter;
import cn.garymb.ygomobile.ui.plus.DialogPlus; import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.utils.YGODialogUtil; import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
public class DeckTypeTouchHelperCallback extends ItemTouchHelper.Callback { public class DeckTypeTouchHelperCallback extends ItemTouchHelper.Callback {
private int dragFlags; private int dragFlags;
private int swipeFlags; private int swipeFlags;
private RecyclerView recyclerView; private RecyclerView recyclerView;
private final YGODialogUtil.OnDeckTypeListener onDeckTypeListener; private final YGODeckDialogUtil.OnDeckTypeListener onDeckTypeListener;
public DeckTypeTouchHelperCallback(YGODialogUtil.OnDeckTypeListener onDeckTypeListener) { public DeckTypeTouchHelperCallback(YGODeckDialogUtil.OnDeckTypeListener onDeckTypeListener) {
this.onDeckTypeListener = onDeckTypeListener; this.onDeckTypeListener = onDeckTypeListener;
} }
......
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="false">
<!-- 位移动画:从当前位置向上移动150dp -->
<translate
android:duration="1500"
android:fromYDelta="0"
android:toYDelta="-30dp"
android:interpolator="@android:anim/decelerate_interpolator" />
<!-- 透明度动画:从完全可见到完全透明 -->
<alpha
android:duration="1500"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator" />
<!-- 缩放动画:稍微缩小一点 -->
<scale
android:duration="1000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.8"
android:toYScale="0.8"
android:interpolator="@android:anim/decelerate_interpolator" />
</set>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.8" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M14,7l-5,5 5,5V7z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.8" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M10,17l5,-5 -5,-5v10z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.9" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M11,7L9.6,8.4l2.6,2.6H2v2h10.2l-2.6,2.6L11,17l5,-5L11,7zM20,19h-8v2h8c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2h-8v2h8V19z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-2z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_cloud_upload_p" android:state_pressed="true" />
<item android:drawable="@drawable/ic_cloud_upload_n" />
</selector>
\ No newline at end of file
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
<item android:state_pressed="true"> <item android:state_pressed="true">
<shape> <shape>
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<solid android:color="#B0BEC5" /> <solid android:color="#FF000000" />
</shape> </shape>
</item> </item>
<item> <item>
<shape> <shape>
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<solid android:color="#cfd8dc" /> <solid android:color="#80000000" />
</shape> </shape>
</item> </item>
</selector> </selector>
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<item> <item>
<shape> <shape>
<corners android:radius="8dp" /> <corners android:radius="8dp" />
<solid android:color="@android:color/white" /> <solid android:color="@android:color/holo_green_dark" />
</shape> </shape>
</item> </item>
</selector> </selector>
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
<item android:state_pressed="true"> <item android:state_pressed="true">
<shape> <shape>
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<solid android:color="#E3F2FD" /> <solid android:color="#6A0101" />
</shape> </shape>
</item> </item>
<item> <item>
<shape> <shape>
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<solid android:color="@color/white" /> <solid android:color="@color/colorAccentDark" />
</shape> </shape>
</item> </item>
</selector> </selector>
\ No newline at end of file
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
</item> </item>
<item> <item>
<shape> <shape>
<solid android:color="@color/white"/> <solid android:color="@color/holo_orange_bright_transparents"/>
<corners android:radius="6dp"/> <corners android:radius="6dp"/>
</shape> </shape>
</item> </item>
......
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.8" android:height="16.032064dp" android:viewportHeight="1024" android:viewportWidth="1533" android:width="24dp">
<path android:fillColor="#000000" android:pathData="M1035.4,348.1l-136.7,136.6a176.3,176.3 0,0 1,1.3 21.4,195.3 195.3,0 0,1 -195.2,194.8 175.7,175.7 0,0 1,-21.3 -1.3L597.7,785.4a449.9,449.9 0,0 0,107.5 12.6c217.8,0 377.8,-174.7 487.9,-289.4a1268.1,1268.1 0,0 0,-157.7 -160.4zM996.3,186.1l-81.1,81.1a452.2,452.2 0,0 0,-210.5 -53.8c-178.3,0 -317.3,111.5 -487.8,292.6 80.6,84.9 154.3,164.4 240.2,219.2l-53.3,53.3 59.3,59.3 592.4,-592.4zM510.2,506.1a194.5,194.5 0,0 1,317.3 -151.1l-57.2,57.2a112.3,112.3 0,0 0,-64.8 -20.6A113.3,113.3 0,0 0,611.7 570.9l-57.9,58.5a193.2,193.2 0,0 1,-44 -123.3z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="64dp"
android:height="24dp" android:height="64dp"
android:viewportWidth="24.0" android:viewportWidth="1024"
android:viewportHeight="24.0"> android:viewportHeight="1024">
<path <path
android:fillColor="@color/black" android:pathData="M512.2,1014.7c-274.7,0 -501.8,-227.1 -501.8,-501.8C10.3,238.1 237.5,11 512.2,11 786.9,11 1014,238.1 1014,512.8c0,274.7 -227.1,501.9 -501.8,501.9zM512.2,116.7C295.6,116.7 116,296.2 116,512.8 116,729.4 295.6,909 512.2,909s396.2,-179.6 396.2,-396.2c-0.1,-216.6 -179.6,-396.1 -396.2,-396.1zM512.2,116.7"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" /> android:fillColor="#fd9803"/>
<path
android:pathData="M712.9,565.6L316.7,565.6c-31.7,0 -52.8,-21.1 -52.8,-52.8 0,-31.7 21.1,-52.8 52.8,-52.8h396.2c31.7,0 52.8,21.1 52.8,52.8 0,31.7 -21.1,52.8 -52.8,52.8zM712.9,565.6"
android:fillColor="#f4ea2a"/>
<path
android:pathData="M512.2,766.4c-31.7,0 -52.8,-21.1 -52.8,-52.8L459.4,312.1c0,-31.7 21.1,-52.8 52.8,-52.8 31.7,0 52.8,21.1 52.8,52.8v401.5c0,31.7 -21.1,52.8 -52.8,52.8zM512.2,766.4"
android:fillColor="#f4ea2a"/>
</vector> </vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.9" android:height="10dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="10dp">
<path android:fillColor="#00FFFF" android:pathData="M518.3,459c-3.2,-4.1 -9.4,-4.1 -12.6,0l-112,141.7c-4.1,5.2 -0.4,12.9 6.3,12.9h73.9V856c0,4.4 3.6,8 8,8h60c4.4,0 8,-3.6 8,-8V613.7H624c6.7,0 10.4,-7.7 6.3,-12.9L518.3,459z"/>
<path android:fillColor="#FFFFFF" android:pathData="M811.4,366.7C765.6,245.9 648.9,160 512.2,160S258.8,245.8 213,366.6C127.3,389.1 64,467.2 64,560c0,110.5 89.5,200 199.9,200H304c4.4,0 8,-3.6 8,-8v-60c0,-4.4 -3.6,-8 -8,-8h-40.1c-33.7,0 -65.4,-13.4 -89,-37.7 -23.5,-24.2 -36,-56.8 -34.9,-90.6 0.9,-26.4 9.9,-51.2 26.2,-72.1 16.7,-21.3 40.1,-36.8 66.1,-43.7l37.9,-9.9 13.9,-36.6c8.6,-22.8 20.6,-44.1 35.7,-63.4 14.9,-19.2 32.6,-35.9 52.4,-49.9 41.1,-28.9 89.5,-44.2 140,-44.2s98.9,15.3 140,44.2c19.9,14 37.5,30.8 52.4,49.9 15.1,19.3 27.1,40.7 35.7,63.4l13.8,36.5 37.8,10C846.1,454.5 884,503.8 884,560c0,33.1 -12.9,64.3 -36.3,87.7 -23.4,23.4 -54.5,36.3 -87.6,36.3H720c-4.4,0 -8,3.6 -8,8v60c0,4.4 3.6,8 8,8h40.1C870.5,760 960,670.5 960,560c0,-92.7 -63.1,-170.7 -148.6,-193.3z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.9" android:height="10dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="10dp">
<path android:fillColor="#00FF00" android:pathData="M518.3,459c-3.2,-4.1 -9.4,-4.1 -12.6,0l-112,141.7c-4.1,5.2 -0.4,12.9 6.3,12.9h73.9V856c0,4.4 3.6,8 8,8h60c4.4,0 8,-3.6 8,-8V613.7H624c6.7,0 10.4,-7.7 6.3,-12.9L518.3,459z"/>
<path android:fillColor="#FFFF00" android:pathData="M811.4,366.7C765.6,245.9 648.9,160 512.2,160S258.8,245.8 213,366.6C127.3,389.1 64,467.2 64,560c0,110.5 89.5,200 199.9,200H304c4.4,0 8,-3.6 8,-8v-60c0,-4.4 -3.6,-8 -8,-8h-40.1c-33.7,0 -65.4,-13.4 -89,-37.7 -23.5,-24.2 -36,-56.8 -34.9,-90.6 0.9,-26.4 9.9,-51.2 26.2,-72.1 16.7,-21.3 40.1,-36.8 66.1,-43.7l37.9,-9.9 13.9,-36.6c8.6,-22.8 20.6,-44.1 35.7,-63.4 14.9,-19.2 32.6,-35.9 52.4,-49.9 41.1,-28.9 89.5,-44.2 140,-44.2s98.9,15.3 140,44.2c19.9,14 37.5,30.8 52.4,49.9 15.1,19.3 27.1,40.7 35.7,63.4l13.8,36.5 37.8,10C846.1,454.5 884,503.8 884,560c0,33.1 -12.9,64.3 -36.3,87.7 -23.4,23.4 -54.5,36.3 -87.6,36.3H720c-4.4,0 -8,3.6 -8,8v60c0,4.4 3.6,8 8,8h40.1C870.5,760 960,670.5 960,560c0,-92.7 -63.1,-170.7 -148.6,-193.3z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M837,66L333.7,66A122.4,122.4 0,0 0,211.5 188.2v22h-24.5a122.4,122.4 0,0 0,-122.2 122.2v503.3a122.4,122.4 0,0 0,122.2 122.2h503.3a122.4,122.4 0,0 0,122.2 -122.2v-22h24.5a122.4,122.4 0,0 0,122.2 -122.2L959.2,188.2a122.4,122.4 0,0 0,-122.2 -122.2zM751.1,835.8a60.8,60.8 0,0 1,-60.8 60.8L187,896.6a60.8,60.8 0,0 1,-60.8 -60.8L126.2,332.4a60.8,60.8 0,0 1,60.8 -60.8h503.3a60.8,60.8 0,0 1,60.8 60.8zM897.8,691.6a60.8,60.8 0,0 1,-60.8 60.8h-24.5v-419.8a122.4,122.4 0,0 0,-122.2 -122.2L272.9,210.3v-22a60.8,60.8 0,0 1,60.8 -60.8h503.3a60.8,60.8 0,0 1,60.8 60.8z"
android:fillColor="#fd9803"/>
<path
android:pathData="M574.9,553.4H469.4V447.9a30.7,30.7 0,0 0,-61.4 0v105.5h-105.5a30.7,30.7 0,1 0,0 61.4h105.5v105.5a30.7,30.7 0,0 0,61.4 0v-105.5h105.5a30.7,30.7 0,0 0,0 -61.4z"
android:fillColor="#f4ea2a"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="128dp" android:viewportHeight="500" android:viewportWidth="500" android:width="128dp">
<path android:fillColor="#00000000" android:pathData="M277.53,128.06l91.52,-14.14v142.86l-91.52,14.14v-142.86h0Z" android:strokeColor="#F9A46A" android:strokeWidth="20"/>
<path android:fillColor="#00000000" android:pathData="M240.04,453.74l0.1,-128.18" android:strokeColor="#03FBF9" android:strokeWidth="20"/>
<path android:fillColor="#00000000" android:pathData="M408.1,288.91v123.93l-168.06,43.89 -157.64,-43.45V74.05l175.76,-22.2 155.93,18.03 -0.29,216.51 -36.72,7.28 -0.62,50.44 -98.78,20.74 0.04,-51.5 -46.91,9.29 -0.58,-218.81 -147.82,-24.5" android:strokeColor="#FFFFFF" android:strokeWidth="20"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M461.2,122.2a80.2,80.2 0,0 1,101.6 0L929.8,422.6a28,28 0,0 1,-35.5 43.3L527.4,165.5a24.2,24.2 0,0 0,-30.7 0L129.7,465.9a28,28 0,1 1,-35.5 -43.3L461.2,122.2zM205.3,456c15.5,0 28,12.5 28,28v321.8A42,42 0,0 0,275.2 848L508,848a28,28 0,1 1,0 56L275.2,904c-54.2,0 -97.9,-44.1 -97.9,-98.2L177.3,484c0,-15.5 12.5,-28 28,-28zM816.5,456c15.5,0 28,12.5 28,28v45.3a28,28 0,1 1,-56 0L788.5,484c0,-15.5 12.5,-28 28,-28z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M304,645.2a45.5,45.5 0,0 1,45.5 -45.6h96a45.5,45.5 0,0 1,45.5 45.6v96.6a45.5,45.5 0,0 1,-45.5 45.6h-96A45.5,45.5 0,0 1,304 741.8L304,645.2zM360,655.7v75.7h75v-75.7L360,655.6zM304,417.6A45.5,45.5 0,0 1,349.5 372h96a45.5,45.5 0,0 1,45.5 45.6v96.6a45.5,45.5 0,0 1,-45.5 45.6h-96A45.5,45.5 0,0 1,304 514.1v-96.6zM360,428v75.7h75L435,428L360,428zM531,417.6A45.5,45.5 0,0 1,576.4 372h96a45.5,45.5 0,0 1,45.5 45.6v96.6a45.5,45.5 0,0 1,-45.5 45.6h-96a45.5,45.5 0,0 1,-45.5 -45.6v-96.6zM587,428v75.7h75L662,428h-75zM588,720c0,-15.5 12.5,-28 28,-28h272c15.5,0 28,12.5 28,28v134.1c0,28.7 -24,49.9 -50.9,49.9L638.9,904C612,904 588,882.8 588,854.1L588,720zM644,748v100h216L860,748L644,748z"
android:fillColor="#F9A46A"/>
<path
android:pathData="M660.9,672.1c-1.1,2.8 -2.2,6 -3.3,9.6l-14.9,46.8a28,28 0,1 1,-53.4 -17l14.9,-46.8c2.2,-7.1 6,-18.9 12.5,-28.9 6.9,-10.6 20,-23.8 41,-23.8h188.5c21,0 34.1,13.2 41,23.8 6.5,10 10.3,21.8 12.5,28.9l14.9,46.8a28,28 0,1 1,-53.4 17l-14.9,-46.8a142.2,142.2 0,0 0,-3.3 -9.6,47 47,0 0,0 -1.8,-4.1H662.7a44.3,44.3 0,0 0,-1.8 4.1z"
android:fillColor="#03FBF9"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M607.9,768c-17.7,0 -32,-14.3 -32,-32L575.9,383.9c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,351.9C639.9,753.6 625.6,768 607.9,768z"
android:fillColor="#f4ea2a"/>
<path
android:pathData="M415.9,768c-17.7,0 -32,-14.3 -32,-32L383.9,383.9c0,-17.7 14.3,-32 32,-32 17.7,0 32,14.3 32,32l0,351.9C447.9,753.6 433.6,768 415.9,768z"
android:fillColor="#f4ea2a"/>
<path
android:pathData="M928,224l-160,0L768,160c0,-53 -42.7,-96 -95.3,-96L351.9,64c-53,0 -96,43 -96,96l0,64 -160,0c-17.7,0 -32,14.3 -32,32s14.3,32 32,32l832,0c17.7,0 32,-14.3 32,-32S945.7,224 928,224zM319.9,160c0,-17.5 14.4,-32 32,-32l320.8,0c17.5,0 31.3,14.1 31.3,32l0,64L319.9,224 319.9,160 319.9,160z"
android:fillColor="#fd9803"/>
<path
android:pathData="M736,960 L288.1,960c-53,0 -96,-43 -96,-96L192.1,383.6c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,480.4c0,17.7 14.4,32 32,32l448.1,0c17.7,0 32,-14.3 32,-32L768.2,384.8c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,479.2C832,916.8 789,960 736,960z"
android:fillColor="#fd9803"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M514.6,511m-84.8,0a84.8,84.8 0,1 0,169.5 0,84.8 84.8,0 1,0 -169.5,0Z"
android:fillColor="#f4ea2a"/>
<path
android:pathData="M661.4,190.9L548.5,78a47.8,47.8 0,0 0,-32 -14c-1.2,-0.1 -2.4,-0.2 -3.7,-0.2A49,49 0,0 0,478.6 78L365.8,190.9a48,48 0,0 0,0 67.9,48 48,0 0,0 67.9,0l31.2,-31.2v115.2a48,48 0,0 0,48 48,48 48,0 0,0 48,-48V226.1l32.6,32.6a48,48 0,0 0,67.9 0,48 48,0 0,0 0,-67.9zM364.2,832.9l112.8,112.8a47.8,47.8 0,0 0,32 14c1.2,0.1 2.4,0.2 3.7,0.2A48.9,48.9 0,0 0,547 945.7l112.8,-112.8a48,48 0,0 0,0 -67.9,48 48,0 0,0 -67.9,0l-31.2,31.2V681a48,48 0,0 0,-48 -48,48 48,0 0,0 -48,48v116.6L432.1,765a48,48 0,0 0,-67.9 0,48 48,0 0,0 0,67.9zM831.1,663.8L943.9,551a47.9,47.9 0,0 0,14 -32c0.1,-1.2 0.2,-2.4 0.2,-3.7A48.9,48.9 0,0 0,943.9 481L831.1,368.2a48,48 0,0 0,-67.9 0,48 48,0 0,0 0,67.9l31.2,31.2H679.2a48,48 0,0 0,-48 48,48 48,0 0,0 48,48h116.6l-32.6,32.6a48,48 0,0 0,0 67.9,48 48,0 0,0 67.9,0zM187.9,366.6L75.1,479.5a47.8,47.8 0,0 0,-14 32c-0.1,1.2 -0.2,2.4 -0.2,3.7a48.9,48.9 0,0 0,14.2 34.3l112.8,112.8a48,48 0,0 0,67.9 0,48 48,0 0,0 0,-67.9l-31.2,-31.2h115.2a48,48 0,0 0,48 -48,48 48,0 0,0 -48,-48H223.1l32.6,-32.6a48,48 0,0 0,0 -67.9,48 48,0 0,0 -67.9,0z"
android:fillColor="#fd9803"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="500" android:viewportWidth="500" android:width="24dp">
<path android:fillColor="#00000000" android:pathData="M319.81,95.49l77.67,2.33 -2.49,77.81" android:strokeColor="#FFFFFF" android:strokeWidth="40"/>
<path android:fillColor="#00000000" android:pathData="M39.07,321.57l150.98,-142.19 56.56,60.05 148.07,-139.45" android:strokeColor="#FFFFFF" android:strokeWidth="40"/>
<path android:fillColor="#00000000" android:pathData="M411.08,369.05h27.7l-64.63,83.33h-202.38l33.53,-35.71" android:strokeColor="#FFFFFF" android:strokeWidth="10"/>
<path android:fillColor="#00000000" android:pathData="M411.08,333.33h27.7l-64.63,83.33h-202.38l33.53,-35.71" android:strokeColor="#FFFFFF" android:strokeWidth="10"/>
<path android:fillColor="#00000000" android:pathData="M250,297.62h188.78l-64.63,83.33h-202.38l78.23,-83.33Z" android:strokeColor="#FFFFFF" android:strokeWidth="10"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="251.8dp"
android:height="200dp"
android:viewportWidth="1289"
android:viewportHeight="1024">
<path
android:pathData="M647,898.9H214.7C92.3,874.5 1,768.4 1,639.5c0,-138.6 109.3,-254.5 248,-262.6C252.2,168.1 423.5,0 632.3,0c166.4,0 282.2,58.7 357.3,200.7l-84.8,37.5c-55.4,-112.6 -143.5,-153.4 -272.4,-153.4A298.7,298.7 0,0 0,333.7 383.4c0,11.4 0,21.2 1.6,32.6l6.5,52.2 -52.2,-6.5c-6.5,0 -14.7,-1.6 -21.2,-1.6 -99.5,0 -181.1,79.9 -181.1,179.5 0,96.2 76.7,174.5 172.9,179.4h388.2v79.9h-1.6z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M647,898.9H214.7C92.3,874.5 1,768.4 1,639.5c0,-138.6 109.3,-254.5 248,-262.6 84.8,6.6 91.3,91.4 91.3,91.4l-52.2,-6.6c-6.5,0 -14.7,-1.6 -21.2,-1.6 -99.5,0 -181.1,79.9 -181.1,179.5 0,96.2 76.7,174.5 172.9,179.4h388.2v79.9z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M1200.6,284.4a75.9,75.9 0,0 1,75.9 75.9v455.1a75.9,75.9 0,0 1,-75.9 75.9H1137.8v-78.2h33.9a37.9,37.9 0,0 0,37.7 -33.5l0.3,-4.4v-384.6a37.9,37.9 0,0 0,-37.9 -37.9h-241.3a37.9,37.9 0,0 0,-37.7 33.5l-0.3,4.4V417.2h-71.1V360.3a75.9,75.9 0,0 1,75.9 -75.9h303.4z"
android:fillColor="#F9A46A"/>
<path
android:pathData="M1086.8,398.2a75.9,75.9 0,0 1,75.9 75.9v455.1a75.9,75.9 0,0 1,-75.9 75.9h-303.4a75.9,75.9 0,0 1,-75.9 -75.9v-455.1a75.9,75.9 0,0 1,75.9 -75.9h303.4zM1053.6,480.3h-237a37.9,37.9 0,0 0,-37.9 37.9v370.7a37.9,37.9 0,0 0,37.9 37.9h237a37.9,37.9 0,0 0,37.9 -37.9v-370.7a37.9,37.9 0,0 0,-37.9 -37.9z"
android:fillColor="#03FBF9"/>
</vector>
...@@ -5,4 +5,5 @@ ...@@ -5,4 +5,5 @@
<stroke <stroke
android:width="2dp" android:width="2dp"
android:color="@color/brightgreen" /> android:color="@color/brightgreen" />
<corners android:radius="6dp"/>
</shape> </shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M371.7,665.3a40.8,40.8 0,0 1,-40.5 -40.6,40.5 40.5,0 0,1 11.9,-28.6l114.6,-114.6L457.6,212.5a40.6,40.6 0,0 1,81.2 0v287.3c0,1.5 -0.5,3.8 -1.2,5.1 0,0.3 -0.1,0.6 -0.2,0.9h0.3a14.3,14.3 0,0 1,-0.7 1.5h0.3l-0.4,1.2 0.1,-0.1 -0.2,0.8s-1.5,4.1 -2,5v0.1a9.9,9.9 0,0 0,0.9 -1.3,61.7 61.7,0 0,1 -3.4,6.8 41.1,41.1 0,0 1,-6 7.4l-126.1,126.1a39.9,39.9 0,0 1,-28.6 11.9zM750.9,949.6a40.3,40.3 0,0 1,-40.4 -40.5l0.5,-218.9 -89.4,89.4a40.5,40.5 0,0 1,-57.3 -57.3l158.1,-158.2a40.5,40.5 0,0 1,28.7 -11.9c13.8,0 26.2,6.4 33.8,17.2l152.9,152.8a40.6,40.6 0,0 1,-28.6 69.2,40.4 40.4,0 0,1 -28.6,-11.9l-88.7,-88.7 -0.5,218.3a40.8,40.8 0,0 1,-40.6 40.4h-0.1zM498.2,949.9C249.2,949.9 46.5,747.3 46.5,498.2 46.5,249.2 249.2,46.5 498.3,46.5c249.1,0 451.7,202.6 451.7,451.6a40.6,40.6 0,0 1,-81.1 0c0,-204.4 -166.3,-370.6 -370.7,-370.6 -204.4,0 -370.7,166.3 -370.7,370.6 0,204.5 166.3,370.7 370.7,370.7 22.3,0 40.5,18.2 40.5,40.4 0,22.3 -18.2,40.5 -40.5,40.5z"/>
</vector>
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/bg3"> android:background="@drawable/bg3">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#aa000000" />
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar" android:id="@+id/appbar"
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/label_limitlist"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/blackLinght" />
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/sp_limit_list"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/deck_list"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/blackLinght" />
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/sp_ydk_list"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/window2s"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/veil2"
android:paddingBottom="5dp">
<com.google.android.material.tabs.TabLayout
android:id="@+id/deck_manager_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabTextAppearance="@style/wallet_third_tab_layout"
android:layout_gravity="center_horizontal" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/deck_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
\ No newline at end of file
...@@ -21,41 +21,86 @@ ...@@ -21,41 +21,86 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="70dp" android:layout_height="100dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:orientation="horizontal" android:orientation="horizontal">
android:weightSum="1">
<LinearLayout <LinearLayout
android:id="@+id/tv_deckmanger" android:id="@+id/tv_deckmanger"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="@dimen/item_and_text_height" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="vertical" android:orientation="vertical"
android:padding="5dp"> android:padding="5dp">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:shadowColor="@color/black" android:layout_weight="1"
android:shadowDx="1" android:layout_gravity="bottom"
android:shadowDy="1" android:orientation="horizontal">
android:shadowRadius="2"
android:text="@string/deck_name" <TextView
android:textColor="@color/holo_blue_light" android:layout_width="wrap_content"
android:textStyle="bold" /> android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:shadowColor="@color/black"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="2"
android:text="@string/deck_name"
android:textColor="@color/holo_blue_light"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/ll_click_like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@drawable/veil2"
android:orientation="horizontal"
android:visibility="gone">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:src="@drawable/baseline_thumb_up_24" />
<TextView
android:id="@+id/tv_add_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_weight="1"
android:gravity="center"
android:text="@string/like_deck_thumb"
android:textColor="@color/white" />
</LinearLayout>
</LinearLayout>
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_deck" android:id="@+id/tv_deck"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@drawable/button_radius_black_transparents"
android:ellipsize="end" android:ellipsize="end"
android:gravity="center|left"
android:maxLines="1" android:maxLines="1"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:shadowColor="@color/black" android:shadowColor="@color/black"
android:shadowDx="1" android:shadowDx="1"
android:shadowDy="1" android:shadowDy="1"
...@@ -77,7 +122,8 @@ ...@@ -77,7 +122,8 @@
<LinearLayout <LinearLayout
android:id="@+id/nav_list" android:id="@+id/nav_list"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical"> android:orientation="vertical">
<ImageView <ImageView
...@@ -90,7 +136,6 @@ ...@@ -90,7 +136,6 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="bottom|center_horizontal" android:gravity="bottom|center_horizontal"
android:shadowColor="@color/black" android:shadowColor="@color/black"
android:shadowDx="1" android:shadowDx="1"
...@@ -105,7 +150,8 @@ ...@@ -105,7 +150,8 @@
<LinearLayout <LinearLayout
android:id="@+id/nav_search" android:id="@+id/nav_search"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical"> android:orientation="vertical">
<ImageView <ImageView
...@@ -118,7 +164,6 @@ ...@@ -118,7 +164,6 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="bottom|center_horizontal" android:gravity="bottom|center_horizontal"
android:shadowColor="@color/black" android:shadowColor="@color/black"
android:shadowDx="1" android:shadowDx="1"
...@@ -133,7 +178,8 @@ ...@@ -133,7 +178,8 @@
<LinearLayout <LinearLayout
android:id="@+id/deck_menu" android:id="@+id/deck_menu"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginLeft="2dp" android:layout_marginLeft="2dp"
android:layout_marginRight="2dp" android:layout_marginRight="2dp"
android:orientation="vertical"> android:orientation="vertical">
...@@ -161,7 +207,6 @@ ...@@ -161,7 +207,6 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="bottom|center_horizontal" android:gravity="bottom|center_horizontal"
android:shadowColor="@color/black" android:shadowColor="@color/black"
android:shadowDx="1" android:shadowDx="1"
......
...@@ -26,12 +26,12 @@ ...@@ -26,12 +26,12 @@
android:layout_weight="9" android:layout_weight="9"
android:gravity="center" android:gravity="center"
android:hint="@string/intpu_name" android:hint="@string/intpu_name"
android:textColorHint="@color/star_rank"
android:imeOptions="actionSearch" android:imeOptions="actionSearch"
android:inputType="textNoSuggestions" android:inputType="textNoSuggestions"
android:singleLine="true" android:singleLine="true"
android:textSize="15sp" android:textSize="15sp"
android:textColor="@color/holo_blue_bright" android:textColor="@color/holo_blue_bright" />
android:textColorHint="@color/gray" />
<ImageView <ImageView
android:id="@+id/iv_search_deck_name" android:id="@+id/iv_search_deck_name"
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
<com.tubb.smrv.SwipeMenuRecyclerView <com.tubb.smrv.SwipeMenuRecyclerView
android:id="@+id/rv_type" android:id="@+id/rv_type"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:divider="@android:color/transparent" android:divider="@android:color/transparent"
android:dividerHeight="4dp" android:dividerHeight="4dp"
...@@ -192,7 +192,7 @@ ...@@ -192,7 +192,7 @@
<com.tubb.smrv.SwipeMenuRecyclerView <com.tubb.smrv.SwipeMenuRecyclerView
android:id="@+id/rv_deck" android:id="@+id/rv_deck"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_weight="2" android:layout_weight="2"
android:divider="@android:color/transparent" android:divider="@android:color/transparent"
android:dividerHeight="4dp" android:dividerHeight="4dp"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 顶部输入框区域 -->
<LinearLayout
android:id="@+id/top_input_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- 第一个输入框及清空按钮 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/button_radius_black_transparents"
android:layout_marginEnd="2.5dp"
android:layout_weight="1">
<EditText
android:id="@+id/et_deck_square_input_deck_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:hint="@string/intpu_name"
android:imeOptions="actionSearch"
android:inputType="textNoSuggestions"
android:singleLine="true"
android:textColor="@color/holo_blue_bright"
android:textColorHint="@color/star_rank"
android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/btn_clear_deck_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/btn_clear_deck_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="5dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_close_black_24dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 第二个输入框及清空按钮 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="2.5dp"
android:background="@drawable/button_radius_black_transparents"
android:layout_weight="1">
<EditText
android:id="@+id/et_input_contributor_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:hint="@string/input_contributor_name"
android:imeOptions="actionSearch"
android:inputType="textNoSuggestions"
android:singleLine="true"
android:textColor="@color/holo_blue_bright"
android:textColorHint="@color/star_rank"
android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/btn_clear_contributor_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/btn_clear_contributor_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="5dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_close_black_24dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<!-- 列表区域 - 设置底部边距为控制栏留出空间 -->
<com.tubb.smrv.SwipeMenuRecyclerView
android:id="@+id/list_deck_info"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="80dp"
android:divider="@android:color/transparent"
android:dividerHeight="4dp"
android:padding="5dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_input_container" />
<!-- 底部控制栏 - 固定在底部 -->
<LinearLayout
android:id="@+id/ll_page_ctrl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:elevation="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<!-- 页码输入区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@color/holo_blue_light" />
<EditText
android:id="@+id/et_go_to_page"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/veil2"
android:gravity="center"
android:hint="@string/go_to"
android:imeOptions="actionDone"
android:inputType="number"
android:singleLine="true"
android:textSize="14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@color/holo_blue_light" />
<TextView
android:id="@+id/tv_sort_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:textColor="@color/holo_blue_light"
android:gravity="center"
android:textSize="5sp"
android:text="@string/sort_by_time"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@color/holo_blue_light" />
</LinearLayout>
</LinearLayout>
<!-- 按钮控制区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
<ImageButton
android:id="@+id/former_page_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/ic_radius_bg"
android:src="@drawable/baseline_arrow_left_24" />
<ImageButton
android:id="@+id/next_page_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/ic_radius_bg"
android:src="@drawable/baseline_arrow_right_24" />
<ImageButton
android:id="@+id/refresh_data"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/ic_radius_bg"
android:src="@drawable/ic_recommendation_order" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_dialog_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="16dp">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="4dp"
android:src="@drawable/mycard" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/login_mycard"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:orientation="vertical">
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/input_user_name"
android:inputType="text" />
<TextView
android:id="@+id/tv_account_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/account_warning"
android:visibility="gone"
android:textColor="@color/red" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="16dp">
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/input_pwd"
android:inputType="textPassword" />
<TextView
android:id="@+id/tv_pwd_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="@string/pwd_warning"
android:textColor="@color/red" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="@+id/btn_register"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_weight="1"
android:background="@drawable/ic_radius_bg"
android:text="@string/register" />
<Button
android:id="@+id/btn_login"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:background="@drawable/ic_radius_bg"
android:text="@string/login_mycard" />
</LinearLayout>
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_main_ui"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_my_deck_input_deck_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center"
android:hint="@string/intpu_name"
android:imeOptions="actionSearch"
android:inputType="textNoSuggestions"
android:singleLine="true"
android:textColor="@color/holo_blue_bright"
android:textColorHint="@color/star_rank"
android:textSize="15sp" />
<com.tubb.smrv.SwipeMenuRecyclerView
android:id="@+id/list_my_deck_info"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="@android:color/transparent"
android:dividerHeight="4dp"
android:padding="5dp"
android:scrollbars="vertical"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="16dp" />
<LinearLayout
android:id="@+id/ll_mc_logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal"
android:background="@drawable/ic_radius_bg"
android:padding="10dp">
<cn.garymb.ygomobile.ui.mycard.mcchat.view.YuanImage
android:id="@+id/my_deck_avatar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="5dp"
android:src="@drawable/avatar"/>
<TextView
android:id="@+id/tv_mycard_user_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/holo_green_bright"
android:text="mycardUserName"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginEnd="5dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="5dp"
android:src="@drawable/baseline_login_24"
android:background="@color/transparent" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:weightSum="2.3" android:weightSum="2.3"
......
...@@ -15,53 +15,50 @@ ...@@ -15,53 +15,50 @@
android:padding="10dp"> android:padding="10dp">
<LinearLayout <LinearLayout
android:id="@+id/ll_head_login"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/ll_head_login"
android:layout_gravity="right" android:layout_gravity="right"
android:layout_weight="1"
android:orientation="horizontal"> android:orientation="horizontal">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=""
android:textColor="@color/holo_green_bright"
android:textSize="15sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:lines="1"
android:text=""
android:textColor="@color/holo_orange_bright"
android:textSize="10sp"
android:visibility="gone" />
</FrameLayout>
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/img_head" android:id="@+id/img_head"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginLeft="@dimen/dp_10" android:layout_marginLeft="@dimen/dp_10"
android:src="@drawable/avatar" /> android:src="@drawable/avatar" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:text=""
android:textColor="@color/holo_green_bright"
android:textSize="15sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:lines="1"
android:text=""
android:textColor="@color/holo_orange_bright"
android:textSize="10sp"
android:visibility="gone" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/img_logout" android:id="@+id/img_logout"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:src="@drawable/ic_guide_right" /> android:src="@drawable/baseline_login_24" />
</LinearLayout> </LinearLayout>
<androidx.appcompat.widget.AppCompatButton <androidx.appcompat.widget.AppCompatButton
...@@ -102,8 +99,8 @@ ...@@ -102,8 +99,8 @@
android:id="@+id/rl_chat" android:id="@+id/rl_chat"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_weight="1"
android:background="@drawable/list_item_bg" android:background="@drawable/list_item_bg"
android:orientation="vertical" android:orientation="vertical"
android:padding="10dp"> android:padding="10dp">
...@@ -121,19 +118,19 @@ ...@@ -121,19 +118,19 @@
android:id="@+id/pb_chat_loading" android:id="@+id/pb_chat_loading"
android:layout_width="15dp" android:layout_width="15dp"
android:layout_height="15dp" android:layout_height="15dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:visibility="gone" android:layout_toRightOf="@id/tv_message_s"
android:layout_centerVertical="true" android:visibility="gone" />
android:layout_toRightOf="@id/tv_message_s" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_message" android:id="@+id/tv_message"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/dp_10" android:layout_marginLeft="@dimen/dp_10"
android:layout_toRightOf="@id/pb_chat_loading" android:layout_toRightOf="@id/pb_chat_loading"
android:layout_centerVertical="true"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
android:text="@string/login_mycard" android:text="@string/login_mycard"
......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/deck_info_image"
android:layout_width="75dp"
android:layout_height="107dp"
android:layout_marginLeft="18dp"
android:layout_marginTop="13dp"
android:src="@drawable/unknown" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/box"/>
<LinearLayout
android:layout_width="35dp"
android:layout_height="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:background="@drawable/button_radius_black_transparents"
android:orientation="horizontal">
<ImageView
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginLeft="2dp"
android:src="@drawable/baseline_thumb_up_24"/>
<TextView
android:id="@+id/like_count"
android:layout_width="20dp"
android:layout_height="10dp"
android:text="23333"
android:lines="1"
android:gravity="center"
android:textColor="@color/brightgreen"
android:layout_marginLeft="1dp"
android:layout_marginRight="5dp"
android:textSize="6sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_marginLeft="18dp"
android:layout_marginTop="15dp"
android:orientation="vertical">
<TextView
android:id="@+id/deck_contributor"
android:layout_width="wrap_content"
android:layout_height="15dp"
android:layout_gravity="center"
android:textColor="@color/white"
android:gravity="center"
android:lines="1"
android:text="contributor_name"
android:textSize="6sp" />
<TextView
android:id="@+id/deck_info_name"
android:layout_width="57dp"
android:layout_height="17dp"
android:layout_marginTop="70dp"
android:layout_marginLeft="1dp"
android:layout_gravity="center"
android:gravity="center"
android:text="deck_name"
android:textColor="@color/white"
android:textSize="7sp" />
<TextView
android:id="@+id/deck_last_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom"
android:textColor="@color/white"
android:gravity="center"
android:lines="1"
android:text="1900-02-03"
android:textSize="6sp" />
</LinearLayout>
</FrameLayout>
\ No newline at end of file
...@@ -13,104 +13,143 @@ ...@@ -13,104 +13,143 @@
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"> android:layout_marginBottom="5dp">
<ImageView <ImageView
android:id="@+id/card_image" android:id="@+id/card_image"
android:layout_width="match_parent" android:layout_width="24dp"
android:layout_height="match_parent" android:layout_height="32dp"
android:layout_centerInParent="true" android:layout_marginLeft="4dp"
android:layout_gravity="center_vertical" android:layout_marginTop="4dp"
android:scaleType="fitXY" android:scaleType="fitXY"
tools:src="@drawable/unknown" /> tools:src="@drawable/unknown" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/box"/>
</RelativeLayout> </RelativeLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginLeft="10dp" android:orientation="horizontal"
android:orientation="vertical"> android:weightSum="5">
<cn.garymb.ygomobile.ui.widget.AlwaysMarqueeTextView
android:id="@+id/deck_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/white"
tools:text="Deck Name" />
<LinearLayout <LinearLayout
android:id="@+id/deck_info" android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="3dp" android:layout_gravity="center"
android:orientation="horizontal"> android:layout_marginLeft="10dp"
android:layout_weight="4"
<ImageView android:orientation="vertical">
android:id="@+id/prerelease_star"
android:layout_width="15dp" <cn.garymb.ygomobile.ui.widget.AlwaysMarqueeTextView
android:layout_height="15dp" android:id="@+id/deck_name"
android:layout_marginRight="5dp" android:layout_width="match_parent"
android:visibility="visible" android:layout_height="match_parent"
android:background="@drawable/ic_expansions"/> android:maxLines="1"
android:singleLine="true"
<ImageView android:textColor="@color/white"
android:id="@+id/banned_mark" tools:text="Deck Name" />
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginRight="@dimen/dp_10"
android:visibility="visible"
android:background="@drawable/ic_banned"/>
<TextView <TextView
android:id="@+id/count_main" android:id="@+id/onlie_deck_id"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/holo_blue_bright" android:textColor="@color/holo_blue_bright"
android:textSize="10sp" android:textSize="10sp"
android:visibility="gone"
tools:text="40" /> tools:text="40" />
<LinearLayout <LinearLayout
android:id="@+id/ll_extra_n_side" android:id="@+id/deck_info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <ImageView
android:id="@+id/TextExtra" android:id="@+id/prerelease_star"
android:layout_width="wrap_content" android:layout_width="15dp"
android:layout_height="wrap_content" android:layout_height="15dp"
android:text="/" android:layout_marginRight="5dp"
android:textColor="@android:color/holo_green_light" android:background="@drawable/ic_expansions"
android:textSize="10sp" /> android:visibility="visible" />
<TextView <ImageView
android:id="@+id/count_ex" android:id="@+id/banned_mark"
android:layout_width="wrap_content" android:layout_width="15dp"
android:layout_height="wrap_content" android:layout_height="15dp"
android:textColor="@color/holo_blue_bright" android:layout_marginRight="@dimen/dp_10"
android:textSize="10sp" android:background="@drawable/ic_banned"
tools:text="15" /> android:visibility="visible" />
<TextView <TextView
android:id="@+id/TextSide" android:id="@+id/count_main"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="/" android:textColor="@color/holo_blue_bright"
android:textColor="@android:color/holo_green_light" android:textSize="10sp"
android:textSize="10sp" /> tools:text="40" />
<TextView <LinearLayout
android:id="@+id/count_side" android:id="@+id/ll_extra_n_side"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:maxLines="1" android:orientation="horizontal">
android:singleLine="true"
android:textColor="@color/holo_blue_bright" <TextView
android:textSize="10sp" android:id="@+id/TextExtra"
tools:text="15" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/"
android:textColor="@android:color/holo_green_light"
android:textSize="10sp" />
<TextView
android:id="@+id/count_ex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/holo_blue_bright"
android:textSize="10sp"
tools:text="15" />
<TextView
android:id="@+id/TextSide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/"
android:textColor="@android:color/holo_green_light"
android:textSize="10sp" />
<TextView
android:id="@+id/count_side"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/holo_blue_bright"
android:textSize="10sp"
tools:text="15" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_weight="1">
<Button
android:id="@+id/local_deck_upload_btn"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginLeft="@dimen/dp_10"
android:background="@drawable/btn_cloud_upload_bg"
android:gravity="center" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/deck_info_image"
android:layout_width="75dp"
android:layout_height="107dp"
android:layout_marginLeft="18dp"
android:layout_marginTop="13dp"
android:src="@drawable/unknown" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/box" />
<LinearLayout
android:id="@+id/ll_switch_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_gravity="start"
android:background="@drawable/button_radius_n"
android:orientation="horizontal">
<ImageView
android:id="@+id/show_on_deck_square"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="2dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="2dp"
android:background="@drawable/baseline_remove_red_eye_24" />
<TextView
android:id="@+id/change_show_or_hide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="5dp"
android:gravity="center"
android:lines="1"
android:text="@string/in_public"
android:textColor="@color/white"
android:textSize="8sp" />
</LinearLayout>
<ImageView
android:id="@+id/delete_my_online_deck_btn"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_gravity="end"
android:layout_margin="5dp"
android:background="@drawable/button_radius_red"
android:rotation="45"
android:src="@drawable/ic_add_white" />
<LinearLayout
android:id="@+id/btn_download"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_marginLeft="18dp"
android:layout_marginTop="15dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="75dp"
android:background="@drawable/button_radius_red"
android:orientation="horizontal">
<ImageView
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginLeft="5dp"
android:src="@drawable/ic_file_download_black_24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="1dp"
android:layout_marginRight="5dp"
android:lines="1"
android:text="@string/Download"
android:textSize="5sp" />
</LinearLayout>
<TextView
android:id="@+id/my_deck_name"
android:layout_width="57dp"
android:layout_height="18dp"
android:layout_gravity="center"
android:gravity="center"
android:text="deck_name"
android:textColor="@color/white"
android:textSize="7sp" />
<TextView
android:id="@+id/deck_update_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:lines="1"
android:text="1900-02-03"
android:textSize="6sp" />
</LinearLayout>
<!--<TextView
android:id="@+id/my_deck_id"
android:layout_width="72dp"
android:layout_height="15dp"
android:layout_marginLeft="21dp"
android:layout_marginTop="15dp"
android:text="contributor_name"
android:lines="1"
android:gravity="center"
android:textSize="6sp"/> -->
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/preview_card_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:background="@drawable/veil"
android:gravity="top"
android:paddingLeft="8dp"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="12sp"
tools:text="name" />
<TextView
android:id="@+id/preview_card_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:textSize="12sp" />
</LinearLayout>
<!-- <ImageView-->
<!-- android:id="@+id/card_image"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginLeft="1px"-->
<!-- android:layout_marginRight="1px"-->
<!-- android:layout_marginBottom="1px"-->
<!-- tools:src="@drawable/unknown" />-->
<ImageView
android:id="@+id/right_top"
android:layout_width="@dimen/right_size2"
android:layout_height="@dimen/right_size2"
android:layout_alignParentRight="true"
android:visibility="visible"
app:srcCompat="@drawable/ic_close_black_24dp" />
</RelativeLayout>
\ No newline at end of file
...@@ -371,5 +371,21 @@ ...@@ -371,5 +371,21 @@
<string name="about_user_privacy_policy">Explicación de los permisos utilizados por YGOMobile</string> <string name="about_user_privacy_policy">Explicación de los permisos utilizados por YGOMobile</string>
<string name="open">Abrir el Deck</string> <string name="open">Abrir el Deck</string>
<string name="web_warn_save_deck">Abrir el Deck cerrará la página web que estás viendo actualmente. ¿Deseas cerrar la página web y abrir el Deck?</string> <string name="web_warn_save_deck">Abrir el Deck cerrará la página web que estás viendo actualmente. ¿Deseas cerrar la página web y abrir el Deck?</string>
<string name="go_to">pasar a</string>
<string name="local_deck">mis mazos</string>
<string name="in_public">Público</string>
<string name="in_personal_use">En Uso Personal</string>
<string name="register">Registro</string>
<string name="sign_out">Sair</string>
<string name="input_user_name">Introduce el Nombre de Usuario</string>
<string name="input_pwd">Introduce la Contraseña</string>
<string name="deck_square">Plaza de Decks</string>
<string name="my_deck_online">Copia en la Nube</string>
<string name="input_contributor_name">Introduce el Nombre del Compartidor</string>
<string name="sort_by_time">Ordenar por Tiempo</string>
<string name="sort_by_thumb">En el orden recomendado</string>
<string name="account_warning">Por favor, complete su correo electrónico o nombre de usuario!</string>
<string name="pwd_warning">Por favor, introduzca su contraseña!</string>
<string name="like_deck_thumb">Dar un me gusta al deck</string>
</resources> </resources>
...@@ -365,4 +365,20 @@ ...@@ -365,4 +365,20 @@
<string name="about_user_privacy_policy">このアプリが使用する権限についての説明</string> <string name="about_user_privacy_policy">このアプリが使用する権限についての説明</string>
<string name="open">デッキを開く</string> <string name="open">デッキを開く</string>
<string name="web_warn_save_deck">デッキを開くと、現在閲覧しているウェブページが閉じられます。ウェブページを閉じてデッキを開きますか?</string> <string name="web_warn_save_deck">デッキを開くと、現在閲覧しているウェブページが閉じられます。ウェブページを閉じてデッキを開きますか?</string>
<string name="go_to">移る</string>
<string name="local_deck">私のデッキ</string>
<string name="in_public">公開中</string>
<string name="in_personal_use">私用中</string>
<string name="register">登録する</string>
<string name="sign_out">ログアウト</string>
<string name="input_user_name">ユーザー名を入力してください</string>
<string name="input_pwd">パスワードを入力してください</string>
<string name="deck_square">デッキ広場</string>
<string name="my_deck_online">クラウド バックアップ</string>
<string name="input_contributor_name">共有者の名前を入力してください</string>
<string name="sort_by_time">時間順に</string>
<string name="sort_by_thumb">推薦順に</string>
<string name="account_warning">メールアドレスまたはユーザー名を入力してください!</string>
<string name="pwd_warning">パスワードを入力してください!</string>
<string name="like_deck_thumb">デッキに「いいね」をつける</string>
</resources> </resources>
...@@ -366,4 +366,20 @@ ...@@ -366,4 +366,20 @@
<string name="about_user_privacy_policy">이 앱에서 사용하는 권한에 대한 설명</string> <string name="about_user_privacy_policy">이 앱에서 사용하는 권한에 대한 설명</string>
<string name="open">덱을 열기</string> <string name="open">덱을 열기</string>
<string name="web_warn_save_deck">덱을 열면 현재 보고 있는 웹 페이지가 닫힙니다. 웹 페이지를 닫고 덱을 열까요?</string> <string name="web_warn_save_deck">덱을 열면 현재 보고 있는 웹 페이지가 닫힙니다. 웹 페이지를 닫고 덱을 열까요?</string>
<string name="go_to">이동하다 로</string>
<string name="local_deck">내 덱들</string>
<string name="in_public">공개 중</string>
<string name="in_personal_use">개인 사용 중</string>
<string name="register">등록하다</string>
<string name="sign_out">로그아웃</string>
<string name="input_user_name">사용자 이름을 입력하세요</string>
<string name="input_pwd">비밀번호를 입력하세요</string>
<string name="deck_square">덱 공유 광장</string>
<string name="my_deck_online">클라우드 백업</string>
<string name="input_contributor_name">공유자의 이름을 입력하세요</string>
<string name="sort_by_time">시간 순서대로</string>
<string name="sort_by_thumb">추천 순서대로</string>
<string name="account_warning">이메일이나 사용자 이름을 입력해 주세요!</string>
<string name="pwd_warning">비밀번호를 입력해 주세요!</string>
<string name="like_deck_thumb">데ッ크에 좋아요를 누르다</string>
</resources> </resources>
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>
\ No newline at end of file
...@@ -355,5 +355,21 @@ ...@@ -355,5 +355,21 @@
<string name="tip_download_ex">Há novas cartas, venha jogar!</string> <string name="tip_download_ex">Há novas cartas, venha jogar!</string>
<string name="user_privacy_policy">Política de Privacidade do Usuário</string> <string name="user_privacy_policy">Política de Privacidade do Usuário</string>
<string name="about_user_privacy_policy">Explicação das permissões utilizadas pelo YGOMobile</string> <string name="about_user_privacy_policy">Explicação das permissões utilizadas pelo YGOMobile</string>
<string name="go_to">pasar a</string>
<string name="local_deck">meus decks</string>
<string name="in_public">Público</string>
<string name="in_personal_use">Em Uso Personal</string>
<string name="register">Registro</string>
<string name="sign_out">Sair</string>
<string name="input_user_name">Insira o Nome de Usuário</string>
<string name="input_pwd">Insira a Senha</string>
<string name="deck_square">Praça de Decks</string>
<string name="my_deck_online">Backup na Nuvem</string>
<string name="input_contributor_name">Insira o Nome do Compartilhador</string>
<string name="sort_by_time">Ordenar por Tempo</string>
<string name="sort_by_thumb">Na ordem recomendada</string>
<string name="account_warning">Por favor, preencha seu e - mail ou nome de usuário!</string>
<string name="pwd_warning">Por favor, insira sua senha!</string>
<string name="like_deck_thumb">Curtir o deck</string>
</resources> </resources>
<resources>
<dimen name="fab_margin">200dp</dimen>
</resources>
\ No newline at end of file
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>
\ No newline at end of file
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
<string name="quit_tip">退出游戏?</string> <string name="quit_tip">退出游戏?</string>
<string name="back_tip">请再按一次返回键退出</string> <string name="back_tip">请再按一次返回键退出</string>
<string name="string_help_text">当前应用缺少必要权限。\n请点击 设置-权限 打开所需权限。</string> <string name="string_help_text">当前应用缺少必要权限。\n请点击 设置-权限 打开所需权限。</string>
<string name="fetch_online_deck">通过网络获取在线卡组</string>
<string name="fetch_ex_card">通过网络获取先行卡</string> <string name="fetch_ex_card">通过网络获取先行卡</string>
<string name="ex_card_list_title">超先行服☆专用☆</string> <string name="ex_card_list_title">超先行服☆专用☆</string>
<string name="ex_card_log_title">更新日志</string> <string name="ex_card_log_title">更新日志</string>
...@@ -106,7 +109,7 @@ ...@@ -106,7 +109,7 @@
<string name="search_open">过滤</string> <string name="search_open">过滤</string>
<string name="search_close">关闭</string> <string name="search_close">关闭</string>
<string name="reset">重置</string> <string name="reset">重置</string>
<string name="hit_keyword1">关键词(空格隔开)</string> <string name="hit_keyword1">关键词</string>
<string name="hit_atk">ATK</string> <string name="hit_atk">ATK</string>
<string name="hit_def">DEF</string> <string name="hit_def">DEF</string>
<string name="label_race">种族</string> <string name="label_race">种族</string>
...@@ -133,7 +136,7 @@ ...@@ -133,7 +136,7 @@
<string name="last_path">上一级目录</string> <string name="last_path">上一级目录</string>
<string name="create_folder">新建文件夹</string> <string name="create_folder">新建文件夹</string>
<string name="intpu_name">输入卡组名</string> <string name="intpu_name">输入卡组名</string>
<string name="the_name_is_folder">当前文件名是个文件夹</string> <string name="the_name_is_folder">当前文件名是个文件夹</string>
<string name="tab_search">搜索</string> <string name="tab_search">搜索</string>
<string name="tab_result">列表</string> <string name="tab_result">列表</string>
...@@ -364,5 +367,23 @@ ...@@ -364,5 +367,23 @@
<string name="user_privacy_policy">用户隐私政策</string> <string name="user_privacy_policy">用户隐私政策</string>
<string name="about_user_privacy_policy">关于本应用使用的权限进行说明</string> <string name="about_user_privacy_policy">关于本应用使用的权限进行说明</string>
<string name="open">打开</string> <string name="open">打开</string>
<string name="go_to">转到</string>
<string name="web_warn_save_deck">打开卡组将关闭正在浏览的网页,是否关闭网页并打开卡组</string> <string name="web_warn_save_deck">打开卡组将关闭正在浏览的网页,是否关闭网页并打开卡组</string>
<string name="local_deck">我的卡组</string>
<string name="in_public">公开中</string>
<string name="in_personal_use">自用中</string>
<string name="down_complete">下载完成</string>
<string name="upload">上传</string>
<string name="input_user_name">输入用户名</string>
<string name="input_pwd">输入密码</string>
<string name="register">注册萌卡</string>
<string name="sign_out">切换账号</string>
<string name="deck_square">卡组广场</string>
<string name="my_deck_online">云备份</string>
<string name="input_contributor_name">输入共享者名称</string>
<string name="sort_by_time">按时间顺序</string>
<string name="sort_by_thumb">按点赞顺序</string>
<string name="account_warning">请填写你的邮箱或用户名!</string>
<string name="pwd_warning">请填写你的密码!</string>
<string name="like_deck_thumb">为卡组点赞</string>
</resources> </resources>
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
<color name="holo_blue_light">#ff33b5e5</color> <color name="holo_blue_light">#ff33b5e5</color>
<color name="holo_green_bright">#95d389</color> <color name="holo_green_bright">#95d389</color>
<color name="holo_orange_bright">#ff982a</color> <color name="holo_orange_bright">#ff982a</color>
<color name="holo_orange_bright_transparents">#ddff982a</color>
<color name="FallNavy">#11113d</color> <color name="FallNavy">#11113d</color>
<color name="colorMain">#2196F3</color> <color name="colorMain">#2196F3</color>
<color name="background">#ECEFF1</color> <color name="background">#ECEFF1</color>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="StringFormatInvalid"> <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="StringFormatInvalid">
<string name="privacy_policy_content">privacy content</string>
<!--string name="app_name">YGOMobile</string--> <!--string name="app_name">YGOMobile</string-->
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="action_game">Single Game</string> <string name="action_game">Single Game</string>
...@@ -45,6 +47,9 @@ ...@@ -45,6 +47,9 @@
<string name="back_tip">Press back key again to exit.</string> <string name="back_tip">Press back key again to exit.</string>
<string name="string_help_text">The current application lacks the necessary permissions. \n <string name="string_help_text">The current application lacks the necessary permissions. \n
please click Settings - permissions - open the required permissions.</string> please click Settings - permissions - open the required permissions.</string>
<string name="fetch_online_deck">Fetching online decks via web</string>
<string name="fetch_ex_card">Fetching pre-cards via web</string> <string name="fetch_ex_card">Fetching pre-cards via web</string>
<string name="ex_card_list_title">Card List</string> <string name="ex_card_list_title">Card List</string>
<string name="ex_card_log_title">update log</string> <string name="ex_card_log_title">update log</string>
...@@ -293,6 +298,8 @@ ...@@ -293,6 +298,8 @@
<string name="category_pack">Pack</string> <string name="category_pack">Pack</string>
<string name="category_windbot_deck">AI Decks</string> <string name="category_windbot_deck">AI Decks</string>
<string name="category_Uncategorized">Uncategorized</string> <string name="category_Uncategorized">Uncategorized</string>
<string name="category_online_deck">Online Deck</string>
<string name="category_my_online_deck">My Online Deck</string>
<string name="please_input_category_name">please input category name</string> <string name="please_input_category_name">please input category name</string>
<string name="invalid_category_name">invalid category name</string> <string name="invalid_category_name">invalid category name</string>
<string name="please_select_target_category">please select target category</string> <string name="please_select_target_category">please select target category</string>
...@@ -383,4 +390,27 @@ ...@@ -383,4 +390,27 @@
<string name="about_user_privacy_policy">Explanation of the permissions used by YGOMObile</string> <string name="about_user_privacy_policy">Explanation of the permissions used by YGOMObile</string>
<string name="open">Open the deck</string> <string name="open">Open the deck</string>
<string name="web_warn_save_deck">Opening the deck will close the webpage you are currently viewing. Do you want to close the webpage and open the deck</string> <string name="web_warn_save_deck">Opening the deck will close the webpage you are currently viewing. Do you want to close the webpage and open the deck</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="down_complete">download complete</string>
<string name="upload">upload</string>
<string name="go_to">go to</string>
<string name="local_deck">my decks</string>
<string name="in_public">in Public</string>
<string name="in_personal_use">in Personal Use</string>
<string name="register">Register</string>
<string name="sign_out">Sign out</string>
<string name="input_user_name">Enter Username</string>
<string name="input_pwd">Enter Password</string>
<string name="deck_square">Deck Plaza</string>
<string name="my_deck_online">Cloud Backup</string>
<string name="input_contributor_name">Enter the Sharer\'s Name</string>
<string name="sort_by_time">Sort by Time</string>
<string name="sort_by_thumb">Sort by Thumb</string>
<string name="account_warning">Please fill in your email or username!</string>
<string name="pwd_warning">Please enter your password!</string>
<string name="like_deck_thumb">Like the deck</string>
</resources> </resources>
...@@ -117,5 +117,9 @@ ...@@ -117,5 +117,9 @@
<style name="itemSpinnerStyle" parent="Widget.AppCompat.DropDownItem.Spinner"> <style name="itemSpinnerStyle" parent="Widget.AppCompat.DropDownItem.Spinner">
</style> </style>
<style name="wallet_third_tab_layout">
<item name="android:textSize">8sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/selector_text_color_white_gold</item>
</style>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment