Commit 47920094 authored by wangfugui's avatar wangfugui

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	mobile/src/main/java/cn/garymb/ygomobile/deck_square/DeckSquareApiUtil.java
#	mobile/src/main/java/cn/garymb/ygomobile/deck_square/DeckSquareFileUtil.java
#	mobile/src/main/java/cn/garymb/ygomobile/deck_square/DeckSquareMyDeckFragment.java
parents 1cd609fa c101d738
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
8.通过萌卡账号登录可以进行云备份管理; 8.通过萌卡账号登录可以进行云备份管理;
9.登录萌卡专页时自动登录云备份; 9.登录萌卡专页时自动登录云备份;
10.可以将云备份的卡组公开到卡组广场或者隐藏; 10.可以将云备份的卡组公开到卡组广场或者隐藏;
11.登录账号后定期同步本地和云备份卡组;
</pre> </pre>
<h3 style="color:#ff0000">注意</h3> <h3 style="color:#ff0000">注意</h3>
......
...@@ -9,8 +9,8 @@ android { ...@@ -9,8 +9,8 @@ android {
minSdkVersion 25 minSdkVersion 25
//noinspection ExpiredTargetSdkVersion //noinspection ExpiredTargetSdkVersion
targetSdkVersion 29 targetSdkVersion 29
versionCode 312000005 versionCode 312000006
versionName "3.12.4" versionName "3.12.4fix1"
flavorDimensions "versionCode" flavorDimensions "versionCode"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
ndkVersion "21.3.6528147" ndkVersion "21.3.6528147"
......
...@@ -26,13 +26,12 @@ public class DeckFile extends TextSelect { ...@@ -26,13 +26,12 @@ public class DeckFile extends TextSelect {
this.onServer = onServer; this.onServer = onServer;
} }
public DeckFile(String name, String typeName, DeckType.ServerType onServer, String deckId) { public DeckFile(String name, File path, DeckType.ServerType onServer, String deckId) {
this.typeName = typeName;
this.onServer = onServer; this.onServer = onServer;
this.deckId = deckId; this.deckId = deckId;
this.setName(name); this.setName(name);
this.fileFullName = null; this.fileFullName = null;
this.path = null; this.path = path;
this.firstCode = -1; this.firstCode = -1;
setObject(this); setObject(this);
} }
......
package cn.garymb.ygomobile.deck_square; package cn.garymb.ygomobile.deck_square;
import static cn.garymb.ygomobile.Constants.TAG;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
...@@ -17,6 +19,8 @@ import com.google.android.material.tabs.TabLayout; ...@@ -17,6 +19,8 @@ import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator; import com.google.android.material.tabs.TabLayoutMediator;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil; import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
public class DeckManageDialog extends DialogFragment implements YGODeckDialogUtil.OnDeckDialogListener { public class DeckManageDialog extends DialogFragment implements YGODeckDialogUtil.OnDeckDialogListener {
......
...@@ -34,6 +34,9 @@ import cn.garymb.ygomobile.AppsSettings; ...@@ -34,6 +34,9 @@ import cn.garymb.ygomobile.AppsSettings;
import cn.garymb.ygomobile.Constants; import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.bean.DeckType; import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.events.DeckFile; import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.deck_square.api_response.LoginToken;
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.lite.R;
import cn.garymb.ygomobile.lite.databinding.FragmentDeckSelectBinding; import cn.garymb.ygomobile.lite.databinding.FragmentDeckSelectBinding;
import cn.garymb.ygomobile.ui.adapters.DeckListAdapter; import cn.garymb.ygomobile.ui.adapters.DeckListAdapter;
...@@ -41,9 +44,12 @@ import cn.garymb.ygomobile.ui.adapters.SimpleListAdapter; ...@@ -41,9 +44,12 @@ import cn.garymb.ygomobile.ui.adapters.SimpleListAdapter;
import cn.garymb.ygomobile.ui.adapters.TextSelectAdapter; import cn.garymb.ygomobile.ui.adapters.TextSelectAdapter;
import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil; 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.ui.plus.VUiKit;
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.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil; import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
import cn.garymb.ygomobile.utils.YGOUtil; import cn.garymb.ygomobile.utils.YGOUtil;
...@@ -359,8 +365,42 @@ public class DeckSelectFragment extends Fragment { ...@@ -359,8 +365,42 @@ public class DeckSelectFragment extends Fragment {
for (DeckFile deckFile : selectDeckList) { for (DeckFile deckFile : selectDeckList) {
deckFile.getPathFile().delete(); deckFile.getPathFile().delete();
deckList.remove(deckFile); deckList.remove(deckFile);
if (SharedPreferenceUtil.getServerToken() != null) {
LoginToken loginToken = new LoginToken(SharedPreferenceUtil.getServerUserId(), SharedPreferenceUtil.getServerToken());
// 获取在线卡组列表(异步处理)
VUiKit.defer().when(() -> {
return DeckSquareApiUtil.getUserDecks(loginToken);
}).fail((e) -> {
LogUtil.e(TAG, "getUserDecks failed: " + e);
}).done((result) -> {
if (result == null || result.getData() == null) {
return;
}
List<MyOnlineDeckDetail> onlineDecks = result.getData();
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
if (onlineDeck.getDeckName().equals(deckFile.getName())) {
// 删除在线卡组(异步处理)
VUiKit.defer().when(() -> {
PushDeckResponse deckResponse = DeckSquareApiUtil.deleteDeck(onlineDeck.getDeckId(), loginToken);
return deckResponse;
}).fail((deleteError) -> {
LogUtil.e(TAG, "Delete Online Deck failed: " + deleteError);
}).done((deleteSuccess) -> {
if (deleteSuccess.isData()) {
YGOUtil.showTextToast(getContext().getString(R.string.done));
LogUtil.i(TAG, "Online deck deleted successfully");
}
});
break;
}
}
});
}
} }
YGOUtil.showTextToast(getContext().getString(R.string.done));
dialogPlus.dismiss(); dialogPlus.dismiss();
onDeckMenuListener.onDeckDel(selectDeckList); onDeckMenuListener.onDeckDel(selectDeckList);
clearDeckSelect(); clearDeckSelect();
......
package cn.garymb.ygomobile.deck_square; package cn.garymb.ygomobile.deck_square;
import androidx.annotation.Nullable;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
...@@ -87,12 +89,47 @@ public class DeckSquareFileUtil { ...@@ -87,12 +89,47 @@ public class DeckSquareFileUtil {
return deckId; return deckId;
} }
//查询卡组目录下的所有ydk文件,返回File[] /**
* 查询卡组目录下的所有ydk文件(包含子文件夹)
* @return 包含所有ydk文件的File数组
*/
public static File[] getAllYdk() { public static File[] getAllYdk() {
File dir = new File(AppsSettings.get().getResourcePath(), Constants.CORE_DECK_PATH); 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)); if (!dir.exists() || !dir.isDirectory()) {
return new File[0];
}
// 使用ArrayList存储结果,方便动态添加
ArrayList<File> ydkFiles = new ArrayList<>();
// 递归遍历目录和子目录
findYdkFiles(dir, ydkFiles);
// 将ArrayList转换为File数组
return ydkFiles.toArray(new File[0]);
}
/**
* 递归查找指定目录下的所有YDK文件
* @param dir 当前查找的目录
* @param ydkFiles 存储找到的YDK文件
*/
private static void findYdkFiles(File dir, ArrayList<File> ydkFiles) {
// 获取目录下的所有文件和子目录
File[] files = dir.listFiles();
if (files == null) {
return; // 目录不可访问或为空
}
return files; for (File file : files) {
if (file.isDirectory()) {
// 如果是子目录,递归查找
findYdkFiles(file, ydkFiles);
} else {
// 如果是文件,检查是否为YDK文件
String fileName = file.getName().toLowerCase(Locale.US);
if (fileName.endsWith(Constants.YDK_FILE_EX)) {
ydkFiles.add(file);
}
}
}
} }
//读取卡组目录下的所有ydk文件,解析ydk文件(包括从ydk文件内容中读取deckId),生成List<MyDeckItem>解析结果 //读取卡组目录下的所有ydk文件,解析ydk文件(包括从ydk文件内容中读取deckId),生成List<MyDeckItem>解析结果
...@@ -170,6 +207,15 @@ public class DeckSquareFileUtil { ...@@ -170,6 +207,15 @@ public class DeckSquareFileUtil {
return content; return content;
} }
/**
* 保存文件到指定路径,并设置指定的最后修改时间
* @param path 保存路径
* @param fileName 文件名
* @param content 文件内容
* @param modificationTime 期望的最后修改时间(毫秒时间戳)
* @return 保存是否成功
*/
public static boolean saveFileToPath(String path, String fileName, String content, long modificationTime) {
public static boolean saveFileToPath(String path, String fileName, String content) { public static boolean saveFileToPath(String path, String fileName, String content) {
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
......
...@@ -8,7 +8,6 @@ import android.view.LayoutInflater; ...@@ -8,7 +8,6 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
......
...@@ -5,7 +5,6 @@ import android.content.Context; ...@@ -5,7 +5,6 @@ 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;
...@@ -13,44 +12,40 @@ import android.widget.TextView; ...@@ -13,44 +12,40 @@ import android.widget.TextView;
import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener; import com.chad.library.adapter.base.listener.OnItemClickListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
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.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;
public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, DeckViewHolder> { public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, DeckViewHolder> {
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private final ImageLoader imageLoader; private final ImageLoader imageLoader;
private final Context mContext; private final Context mContext;
private LimitList mLimitList;
private final CardLoader mCardLoader; private final CardLoader mCardLoader;
private final DeckLoader mDeckLoader; private final DeckLoader mDeckLoader;
private final boolean isSelect;
private final List<T> selectList;
private LimitList mLimitList;
private DeckInfo deckInfo; private DeckInfo deckInfo;
private DeckFile deckFile; private DeckFile deckFile;
private OnItemSelectListener onItemSelectListener; private OnItemSelectListener onItemSelectListener;
private int selectPosition; private int selectPosition;
private final boolean isSelect;
private boolean isManySelect;//标志位,是否选中多个卡组 private boolean isManySelect;//标志位,是否选中多个卡组
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);
...@@ -77,39 +72,17 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -77,39 +72,17 @@ 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("卡组上传失败!");
}
});
});
} }
/**
* 将时间戳转换为 ISO 8601 格式的时间字符串
*/
@SuppressLint("SimpleDateFormat")
public static String convertMillisToIsoString(long timeMillis) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.CHINA);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf.format(new Date(timeMillis));
}
@SuppressLint("ResourceType") @SuppressLint("ResourceType")
@Override @Override
...@@ -149,6 +122,7 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -149,6 +122,7 @@ 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);
} }
holder.file_time.setText(convertMillisToIsoString(deckFile.getDate()));
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);
...@@ -222,18 +196,6 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -222,18 +196,6 @@ 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) {
this.selectPosition = selectPosition;
} }
public boolean isSelect() { public boolean isSelect() {
...@@ -244,13 +206,6 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -244,13 +206,6 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
return isManySelect; return isManySelect;
} }
public void addManySelect(T t) {
if (selectList.contains(t))
selectList.remove(t);
else
selectList.add(t);
}
/** /**
* 内部维护了selectList,用于存储当前选中的卡组 * 内部维护了selectList,用于存储当前选中的卡组
* DeckListAdapter支持多选,传入false清除已选中的卡组,并更新adapter。传入true将标志位置1 * DeckListAdapter支持多选,传入false清除已选中的卡组,并更新adapter。传入true将标志位置1
...@@ -265,6 +220,13 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -265,6 +220,13 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
} }
} }
public void addManySelect(T t) {
if (selectList.contains(t))
selectList.remove(t);
else
selectList.add(t);
}
public List<T> getSelectList() { public List<T> getSelectList() {
return selectList; return selectList;
} }
...@@ -273,6 +235,10 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D ...@@ -273,6 +235,10 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
return selectPosition; return selectPosition;
} }
public void setSelectPosition(int selectPosition) {
this.selectPosition = selectPosition;
}
public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) {
this.onItemSelectListener = onItemSelectListener; this.onItemSelectListener = onItemSelectListener;
} }
...@@ -293,10 +259,10 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo ...@@ -293,10 +259,10 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
TextView main; TextView main;
TextView extra; TextView extra;
TextView side; TextView side;
TextView file_time;
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);
...@@ -308,10 +274,10 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo ...@@ -308,10 +274,10 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
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);
file_time =findView(R.id.file_time);
ll_extra_n_side = findView(R.id.ll_extra_n_side); ll_extra_n_side = findView(R.id.ll_extra_n_side);
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
...@@ -2,6 +2,7 @@ package cn.garymb.ygomobile.ui.cards; ...@@ -2,6 +2,7 @@ package cn.garymb.ygomobile.ui.cards;
import static android.content.Context.CLIPBOARD_SERVICE; import static android.content.Context.CLIPBOARD_SERVICE;
import static cn.garymb.ygomobile.Constants.ORI_DECK; import static cn.garymb.ygomobile.Constants.ORI_DECK;
import static cn.garymb.ygomobile.Constants.TAG;
import static cn.garymb.ygomobile.Constants.YDK_FILE_EX; import static cn.garymb.ygomobile.Constants.YDK_FILE_EX;
import static cn.garymb.ygomobile.core.IrrlichtBridge.ACTION_SHARE_FILE; import static cn.garymb.ygomobile.core.IrrlichtBridge.ACTION_SHARE_FILE;
...@@ -62,6 +63,7 @@ import org.greenrobot.eventbus.Subscribe; ...@@ -62,6 +63,7 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; import org.greenrobot.eventbus.ThreadMode;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -81,6 +83,10 @@ import cn.garymb.ygomobile.deck_square.DeckSquareApiUtil; ...@@ -81,6 +83,10 @@ import cn.garymb.ygomobile.deck_square.DeckSquareApiUtil;
import cn.garymb.ygomobile.deck_square.DeckSquareFileUtil; import cn.garymb.ygomobile.deck_square.DeckSquareFileUtil;
import cn.garymb.ygomobile.deck_square.api_response.BasicResponse; import cn.garymb.ygomobile.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.deck_square.api_response.DownloadDeckResponse; import cn.garymb.ygomobile.deck_square.api_response.DownloadDeckResponse;
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.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;
...@@ -106,6 +112,7 @@ import cn.garymb.ygomobile.utils.FileUtils; ...@@ -106,6 +112,7 @@ 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.LogUtil;
import cn.garymb.ygomobile.utils.ShareUtil; import cn.garymb.ygomobile.utils.ShareUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil; 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;
...@@ -232,7 +239,10 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -232,7 +239,10 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} else { } else {
YGOUtil.showTextToast(data != null ? data.getMessage() : "点赞失败"); YGOUtil.showTextToast(data != null ? data.getMessage() : "点赞失败");
} }
mDeckId = null;
}); });
} else {
ll_click_like.setVisibility(View.GONE);
} }
}); });
tv_deck.setOnClickListener(v -> { tv_deck.setOnClickListener(v -> {
...@@ -241,6 +251,13 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -241,6 +251,13 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
}); });
// YGODeckDialogUtil.dialogDeckSelect(getActivity(), AppsSettings.get().getLastDeckPath(), this)); // YGODeckDialogUtil.dialogDeckSelect(getActivity(), AppsSettings.get().getLastDeckPath(), this));
mContext = (BaseActivity) getActivity(); mContext = (BaseActivity) getActivity();
/** 自动同步 */
if (SharedPreferenceUtil.getServerToken() != null) {
VUiKit.defer().when(DeckSquareApiUtil::synchronizeDecks).fail((e) -> {
LogUtil.i(TAG, "sync deck fail" + e.getMessage());
}).done((result) -> {
});
}
} }
...@@ -896,9 +913,46 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -896,9 +913,46 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
builder.setMessage(R.string.question_delete_deck); builder.setMessage(R.string.question_delete_deck);
builder.setMessageGravity(Gravity.CENTER_HORIZONTAL); builder.setMessageGravity(Gravity.CENTER_HORIZONTAL);
builder.setLeftButtonListener((dlg, rs) -> { builder.setLeftButtonListener((dlg, rs) -> {
if (mDeckAdapater.getYdkFile() != null) { if (mDeckAdapater.getYdkFile() != null) {
FileUtils.deleteFile(mDeckAdapater.getYdkFile()); FileUtils.deleteFile(mDeckAdapater.getYdkFile());
if (SharedPreferenceUtil.getServerToken() != null) {
LoginToken loginToken = new LoginToken(
SharedPreferenceUtil.getServerUserId(),
SharedPreferenceUtil.getServerToken()
);
// 获取在线卡组列表(异步处理)
VUiKit.defer().when(() -> {
return DeckSquareApiUtil.getUserDecks(loginToken);
}).fail((e) -> {
LogUtil.e(TAG, "getUserDecks failed: " + e);
}).done((result) -> {
if (result == null || result.getData() == null) {
return;
}
List<MyOnlineDeckDetail> onlineDecks = result.getData();
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
if (onlineDeck.getDeckName().equals(mDeckAdapater.getYdkFile().getName())) {
// 删除在线卡组(异步处理)
VUiKit.defer().when(() -> {
PushDeckResponse deckResponse = DeckSquareApiUtil.deleteDeck(onlineDeck.getDeckId(), loginToken);
return deckResponse;
}).fail((deleteError) -> {
LogUtil.e(TAG, "Delete Online Deck failed: " + deleteError);
}).done((deleteSuccess) -> {
if (deleteSuccess.isData()) {
LogUtil.i(TAG, "Online deck deleted successfully");
YGOUtil.showTextToast(getContext().getString(R.string.done));
}
});
break;
}
}
});
}
dlg.dismiss(); dlg.dismiss();
File file = getFirstYdk(); File file = getFirstYdk();
loadDeckFromFile(file); loadDeckFromFile(file);
...@@ -1295,12 +1349,11 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -1295,12 +1349,11 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
}).done((deckData) -> { }).done((deckData) -> {
if (deckData != null) { if (deckData != null) {
mDeckId = deckData.getDeckId(); mDeckId = deckData.getDeckId();
Log.w("seesee mDeckId", mDeckId);
deckData.getDeckYdk(); deckData.getDeckYdk();
String fileFullName = deckData.getDeckName() + ".ydk"; String fileFullName = deckData.getDeckName() + ".ydk";
File dir = new File(getActivity().getApplicationInfo().dataDir, "cache"); File dir = new File(getActivity().getApplicationInfo().dataDir, "cache");
//将卡组存到cache缓存目录中 //将卡组存到cache缓存目录中
boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk()); boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk(), Long.valueOf(deckData.getDeckUpdateDate()));
if (result) {//存储成功,使用预加载功能 if (result) {//存储成功,使用预加载功能
LogUtil.i(TAG, "square deck detail done"); LogUtil.i(TAG, "square deck detail done");
//File file = new File(dir, fileFullName); //File file = new File(dir, fileFullName);
...@@ -1313,6 +1366,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -1313,6 +1366,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
} else { } else {
loadDeckFromFile(deckFile.getPathFile()); loadDeckFromFile(deckFile.getPathFile());
ll_click_like.setVisibility(View.GONE);
} }
} }
......
...@@ -145,7 +145,7 @@ public class PackManager implements Closeable { ...@@ -145,7 +145,7 @@ public class PackManager implements Closeable {
public List<Integer> getAllIdsById(Integer id) { public List<Integer> getAllIdsById(Integer id) {
String packName = findPackNameById(id); String packName = findPackNameById(id);
if (packName == null) { if (packName == null) {
Log.w("seesee", "No pack found for ID: " + id); Log.w(TAG, "No pack found for ID: " + id);
return new ArrayList<>(); return new ArrayList<>();
} }
return findIdsByPackName(packName); return findIdsByPackName(packName);
......
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#91BF03" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M10,8l0,6l4.7,2.9l0.8,-1.2l-4,-2.4l0,-5.3z"/>
<path android:fillColor="@android:color/white" android:pathData="M17.92,12c0.05,0.33 0.08,0.66 0.08,1c0,3.9 -3.1,7 -7,7s-7,-3.1 -7,-7c0,-3.9 3.1,-7 7,-7c0.7,0 1.37,0.1 2,0.29V4.23C12.36,4.08 11.69,4 11,4c-5,0 -9,4 -9,9s4,9 9,9s9,-4 9,-9c0,-0.34 -0.02,-0.67 -0.06,-1H17.92z"/>
<path android:fillColor="@android:color/white" android:pathData="M20,5l0,-3l-2,0l0,3l-3,0l0,2l3,0l0,3l2,0l0,-3l3,0l0,-2z"/>
</vector>
...@@ -81,7 +81,13 @@ ...@@ -81,7 +81,13 @@
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:layout_weight="1" android:layout_weight="1"
android:textSize="10sp"
android:maxLines="1"
android:gravity="center" android:gravity="center"
android:shadowColor="@color/black"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="2"
android:text="@string/like_deck_thumb" android:text="@string/like_deck_thumb"
android:textColor="@color/white" /> android:textColor="@color/white" />
</LinearLayout> </LinearLayout>
......
...@@ -34,11 +34,10 @@ ...@@ -34,11 +34,10 @@
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:orientation="horizontal" android:orientation="horizontal">
android:weightSum="5">
<LinearLayout <LinearLayout
android:layout_width="0dp" 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:layout_marginLeft="10dp"
...@@ -133,23 +132,26 @@ ...@@ -133,23 +132,26 @@
android:textColor="@color/holo_blue_bright" android:textColor="@color/holo_blue_bright"
android:textSize="10sp" android:textSize="10sp"
tools:text="15" /> tools:text="15" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:src="@drawable/baseline_more_time_24"/>
<TextView
android:id="@+id/file_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/holo_blue_bright"
android:textSize="7sp"
tools:text="2025-07-03T19:47:26" />
</LinearLayout> </LinearLayout>
</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>
\ No newline at end of file
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
android:layout_marginLeft="1dp" android:layout_marginLeft="1dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:lines="1" android:lines="1"
android:text="@string/Download" android:text="@string/pre_view"
android:textSize="5sp" /> android:textSize="5sp" />
</LinearLayout> </LinearLayout>
......
...@@ -387,5 +387,6 @@ ...@@ -387,5 +387,6 @@
<string name="account_warning">Por favor, complete su correo electrónico o nombre de usuario!</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="pwd_warning">Por favor, introduzca su contraseña!</string>
<string name="like_deck_thumb">Dar un me gusta al deck</string> <string name="like_deck_thumb">Dar un me gusta al deck</string>
<string name="pre_view">Vista Previa</string>
</resources> </resources>
...@@ -381,4 +381,5 @@ ...@@ -381,4 +381,5 @@
<string name="account_warning">メールアドレスまたはユーザー名を入力してください!</string> <string name="account_warning">メールアドレスまたはユーザー名を入力してください!</string>
<string name="pwd_warning">パスワードを入力してください!</string> <string name="pwd_warning">パスワードを入力してください!</string>
<string name="like_deck_thumb">デッキに「いいね」をつける</string> <string name="like_deck_thumb">デッキに「いいね」をつける</string>
<string name="pre_view">プレビュー</string>
</resources> </resources>
...@@ -382,4 +382,5 @@ ...@@ -382,4 +382,5 @@
<string name="account_warning">이메일이나 사용자 이름을 입력해 주세요!</string> <string name="account_warning">이메일이나 사용자 이름을 입력해 주세요!</string>
<string name="pwd_warning">비밀번호를 입력해 주세요!</string> <string name="pwd_warning">비밀번호를 입력해 주세요!</string>
<string name="like_deck_thumb">데ッ크에 좋아요를 누르다</string> <string name="like_deck_thumb">데ッ크에 좋아요를 누르다</string>
<string name="pre_view">미리 보기</string>
</resources> </resources>
...@@ -371,5 +371,6 @@ ...@@ -371,5 +371,6 @@
<string name="account_warning">Por favor, preencha seu e - mail ou nome de usuário!</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="pwd_warning">Por favor, insira sua senha!</string>
<string name="like_deck_thumb">Curtir o deck</string> <string name="like_deck_thumb">Curtir o deck</string>
<string name="pre_view">Prévia</string>
</resources> </resources>
...@@ -386,4 +386,5 @@ ...@@ -386,4 +386,5 @@
<string name="account_warning">请填写你的邮箱或用户名!</string> <string name="account_warning">请填写你的邮箱或用户名!</string>
<string name="pwd_warning">请填写你的密码!</string> <string name="pwd_warning">请填写你的密码!</string>
<string name="like_deck_thumb">为卡组点赞</string> <string name="like_deck_thumb">为卡组点赞</string>
<string name="pre_view">预览</string>
</resources> </resources>
...@@ -413,4 +413,5 @@ ...@@ -413,4 +413,5 @@
<string name="account_warning">Please fill in your email or username!</string> <string name="account_warning">Please fill in your email or username!</string>
<string name="pwd_warning">Please enter your password!</string> <string name="pwd_warning">Please enter your password!</string>
<string name="like_deck_thumb">Like the deck</string> <string name="like_deck_thumb">Like the deck</string>
<string name="pre_view">pre view</string>
</resources> </resources>
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