Commit 163faab0 authored by fallenstardust's avatar fallenstardust Committed by GitHub

Merge pull request #193 from zhuhongbozhuhongbo/master

卡组广场进一步调试&修复
parents d834fdb6 badb8041
......@@ -32,7 +32,7 @@ public class DeckFile extends TextSelect {
this.setName(name);
this.fileFullName = null;
this.path = path;
this.firstCode = -1;
this.firstCode = DeckUtil.getFirstCardCode(path.getAbsolutePath());
setObject(this);
}
......
......@@ -20,14 +20,11 @@ import java.nio.charset.StandardCharsets;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.bean.Deck;
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.DeckUtils;
import cn.garymb.ygomobile.utils.IOUtils;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.hutool.core.util.ArrayUtil;
import ocgcore.data.Card;
import ocgcore.data.LimitList;
public class DeckLoader {
private static Boolean isChanged;
......
package cn.garymb.ygomobile.ui.adapters;
import static cn.garymb.ygomobile.Constants.DEBUG;
import static cn.garymb.ygomobile.utils.YGOUtil.convertMillisToIsoString;
import static cn.garymb.ygomobile.ui.cards.deck_square.DeckSquareFileUtil.convertToGMTDate;
import android.annotation.SuppressLint;
import android.content.Context;
......@@ -22,13 +21,12 @@ import cn.garymb.ygomobile.bean.Deck;
import cn.garymb.ygomobile.bean.DeckInfo;
import cn.garymb.ygomobile.bean.TextSelect;
import cn.garymb.ygomobile.bean.events.DeckFile;
import cn.garymb.ygomobile.deck_square.DeckSquareListAdapter;
import cn.garymb.ygomobile.ui.cards.deck_square.DeckSquareListAdapter;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.CardLoader;
import cn.garymb.ygomobile.loader.DeckLoader;
import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.utils.YGOUtil;
import cn.hutool.poi.excel.cell.CellSetter;
import ocgcore.DataManager;
import ocgcore.data.LimitList;
......@@ -112,12 +110,7 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
holder.side.setText("-");
holder.side.setTextColor(Color.RED);
}
holder.file_time.setText(convertMillisToIsoString(deckFile.getDate()));
if (DEBUG) {
holder.ll_deck_date.setVisibility(View.VISIBLE);
} else {
holder.ll_deck_date.setVisibility(View.GONE);
}
holder.file_time.setText(convertToGMTDate(deckFile.getDate()));
if (deckFile.getTypeName().equals(YGOUtil.s(R.string.category_pack)) || deckFile.getPath().contains("cacheDeck")) {
//卡包展示时不显示额外和副卡组数量文本
holder.ll_extra_n_side.setVisibility(View.GONE);
......@@ -255,7 +248,6 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
TextView extra;
TextView side;
TextView file_time;
LinearLayout ll_deck_date;
LinearLayout ll_extra_n_side;
View item_deck_list;
View deck_info;
......@@ -270,7 +262,6 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
main = findView(R.id.count_main);
extra = findView(R.id.count_ex);
side = findView(R.id.count_side);
ll_deck_date = findView(R.id.ll_deck_date);
file_time = findView(R.id.file_time);
ll_extra_n_side = findView(R.id.ll_extra_n_side);
prerelease_star = findView(R.id.prerelease_star);
......
......@@ -2,9 +2,9 @@ package cn.garymb.ygomobile.ui.cards;
import static android.content.Context.CLIPBOARD_SERVICE;
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.core.IrrlichtBridge.ACTION_SHARE_FILE;
import static cn.garymb.ygomobile.ui.cards.deck_square.DeckSquareFileUtil.convertToUnixTimestamp;
import android.content.ClipData;
import android.content.ClipboardManager;
......@@ -63,7 +63,6 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
......@@ -78,15 +77,6 @@ import cn.garymb.ygomobile.bean.DeckType;
import cn.garymb.ygomobile.bean.events.CardInfoEvent;
import cn.garymb.ygomobile.bean.events.DeckFile;
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.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.CardLoader;
import cn.garymb.ygomobile.loader.CardSearchInfo;
......@@ -100,6 +90,14 @@ import cn.garymb.ygomobile.ui.cards.deck.DeckItem;
import cn.garymb.ygomobile.ui.cards.deck.DeckItemTouchHelper;
import cn.garymb.ygomobile.ui.cards.deck.DeckItemType;
import cn.garymb.ygomobile.ui.cards.deck.DeckLayoutManager;
import cn.garymb.ygomobile.ui.cards.deck_square.DeckManageDialog;
import cn.garymb.ygomobile.ui.cards.deck_square.DeckSquareApiUtil;
import cn.garymb.ygomobile.ui.cards.deck_square.DeckSquareFileUtil;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.DownloadDeckResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.LoginToken;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.MyOnlineDeckDetail;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushSingleDeckResponse;
import cn.garymb.ygomobile.ui.home.HomeActivity;
import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil;
import cn.garymb.ygomobile.ui.plus.AOnGestureListener;
......@@ -129,7 +127,7 @@ import ocgcore.enums.LimitType;
* 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 = "seesee";
protected DrawerLayout mDrawerLayout;
protected RecyclerView mListView;
protected CardLoader mCardLoader;
......@@ -253,9 +251,12 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
mContext = (BaseActivity) getActivity();
/** 自动同步 */
if (SharedPreferenceUtil.getServerToken() != null) {
VUiKit.defer().when(DeckSquareApiUtil::synchronizeDecks).fail((e) -> {
VUiKit.defer().when(() -> {
return DeckSquareApiUtil.synchronizeDecks();
}).fail((e) -> {
LogUtil.i(TAG, "sync deck fail" + e.getMessage());
}).done((result) -> {
LogUtil.i(TAG, "sync deck success");
});
}
}
......@@ -277,6 +278,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
/**
* 传入外部ydk文件的路径,临时在本页面中打开该ydk的内容,用于后续的保存
*
* @param preLoadFilePath 外部ydk文件的路径
*/
public void preLoadFile(String preLoadFilePath) {
......@@ -915,44 +917,13 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
builder.setLeftButtonListener((dlg, rs) -> {
if (mDeckAdapater.getYdkFile() != null) {
FileUtils.deleteFile(mDeckAdapater.getYdkFile());
//统一调用批量删除在线卡组(这里只有1个)
List<DeckFile> deckFileList = new ArrayList<>();
deckFileList.add(new DeckFile(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;
}
}
});
}
onDeckDel(deckFileList);
YGOUtil.showTextToast(R.string.done);
dlg.dismiss();
File file = getFirstYdk();
loadDeckFromFile(file);
......@@ -1350,10 +1321,10 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
if (deckData != null) {
mDeckId = deckData.getDeckId();
deckData.getDeckYdk();
String fileFullName = deckData.getDeckName() + ".ydk";
String fileFullName = deckData.getDeckName() + YDK_FILE_EX;
File dir = new File(getActivity().getApplicationInfo().dataDir, "cache");
//将卡组存到cache缓存目录中
boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk(), Long.valueOf(deckData.getDeckUpdateDate()));
boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk(), convertToUnixTimestamp(deckData.getDeckUpdateDate()));
if (result) {//存储成功,使用预加载功能
LogUtil.i(TAG, "square deck detail done");
//File file = new File(dir, fileFullName);
......@@ -1391,6 +1362,9 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
return;
}
}
//删除在线的同名卡组们
DeckSquareApiUtil.deleteDecks(deckFileList);
YGOUtil.showTextToast(R.string.done);
}
@Override
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square;
import static cn.garymb.ygomobile.Constants.TAG;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
......@@ -19,8 +17,6 @@ import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
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;
public class DeckManageDialog extends DialogFragment implements YGODeckDialogUtil.OnDeckDialogListener {
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square;
import android.content.Context;
import android.content.DialogInterface;
......@@ -21,6 +21,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.FastScrollLinearLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelper;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemLongClickListener;
......@@ -34,9 +35,9 @@ 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.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.ui.cards.deck_square.api_response.LoginToken;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.MyOnlineDeckDetail;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushSingleDeckResponse;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.lite.databinding.FragmentDeckSelectBinding;
import cn.garymb.ygomobile.ui.adapters.DeckListAdapter;
......@@ -52,6 +53,7 @@ import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
import cn.garymb.ygomobile.utils.recyclerview.DeckTypeTouchHelperCallback;
//在dialog中卡组选择的Fragment,选中页面中某项后,在卡组编辑页面中显示卡片
public class DeckSelectFragment extends Fragment {
......@@ -365,41 +367,6 @@ public class DeckSelectFragment extends Fragment {
for (DeckFile deckFile : selectDeckList) {
deckFile.getPathFile().delete();
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;
}
}
});
}
}
dialogPlus.dismiss();
onDeckMenuListener.onDeckDel(selectDeckList);
......@@ -416,25 +383,32 @@ public class DeckSelectFragment extends Fragment {
}
});
//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;
// }
// });
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new DeckTypeTouchHelperCallback(new YGODeckDialogUtil.OnDeckTypeListener() {
@Override
public void onDeckTypeListener(int positon) {
File file = new File(typeList.get(positon).getPath());
File[] files = file.listFiles();
List<DeckFile> deckFileList = new ArrayList<>();
if (files != null) {
for (File file1 : files) {
deckFileList.add(new DeckFile(file1));
}
}
IOUtils.delete(file);
onDeckMenuListener.onDeckDel(deckFileList);
typeAdp.remove(positon);
if (typeAdp.getSelectPosition() == positon) {
typeAdp.setSelectPosition(2);
typeAdp.notifyItemChanged(2);
}
clearDeckSelect();
deckList.clear();
deckList.addAll(DeckUtil.getDeckList(typeList.get(2).getPath()));
deckAdp.notifyDataSetChanged();
}
}));
itemTouchHelper.attachToRecyclerView(binding.rvType);
}
return binding.getRoot();
}
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square;
import androidx.annotation.Nullable;
import android.os.Build;
import java.io.BufferedReader;
import java.io.File;
......@@ -9,12 +9,21 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import cn.garymb.ygomobile.AppsSettings;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.ui.cards.deck_square.bo.MyDeckItem;
import cn.garymb.ygomobile.utils.IOUtils;
import cn.garymb.ygomobile.utils.LogUtil;
import ocgcore.CardManager;
......@@ -23,7 +32,8 @@ import ocgcore.data.Card;
public class DeckSquareFileUtil {
//
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private static final String TAG = "decksquareApiUtil";
//private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
// public static List<String> readLastLinesWithNIO(File file, int numLines) {
// try {
......@@ -54,7 +64,7 @@ public class DeckSquareFileUtil {
String line = null;
while ((line = reader.readLine()) != null) {
LogUtil.i(TAG, line);
// LogUtil.i(TAG, line);
if (line.startsWith("###")) {//注意,先判断###,后判断##。因为###会包括##的情况
try {
String data = line.replace("#", "");
......@@ -86,6 +96,7 @@ public class DeckSquareFileUtil {
/**
* 查询卡组目录下的所有ydk文件(包含子文件夹)
*
* @return 包含所有ydk文件的File数组
*/
public static File[] getAllYdk() {
......@@ -103,7 +114,8 @@ public class DeckSquareFileUtil {
/**
* 递归查找指定目录下的所有YDK文件
* @param dir 当前查找的目录
*
* @param dir 当前查找的目录
* @param ydkFiles 存储找到的YDK文件
*/
private static void findYdkFiles(File dir, ArrayList<File> ydkFiles) {
......@@ -134,15 +146,14 @@ public class DeckSquareFileUtil {
for (File file : files) {
String deckId = getId(file);
MyDeckItem item = new MyDeckItem();
item.deckName = file.getName();
item.setUpdateDate(String.valueOf(file.lastModified()));
item.setDeckSouce(0);
item.setDeckName(file.getName());
item.setUpdateTimestamp(file.lastModified());
item.setDeckPath(file.getPath());
if (deckId != null) {
item.deckId = deckId;
item.idUploaded = 2;
item.setDeckId(deckId);
item.setIdUploaded(2);
} else {
item.idUploaded = 0;
item.setIdUploaded(0);
}
result.add(item);
}
......@@ -201,37 +212,65 @@ public class DeckSquareFileUtil {
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 saveFile(File file, String content, long modificationTime) {
FileOutputStream fos = null;
try {
// 创建文件对象
File file = new File(path, fileName);
fos = new FileOutputStream(file);
// 创建文件输出流
try (FileOutputStream fos = new FileOutputStream(file)) {
// 写入内容
fos.write(content.getBytes());
fos.flush();
}
// 写入内容
fos.write(content.getBytes());
fos.flush();
// 设置指定的最后修改时间
boolean timeSet = file.setLastModified(modificationTime);
if (!timeSet) {
LogUtil.w(TAG, "设置文件修改时间失败: " + file.getPath());
}
} else {
return true;
} catch (IOException e) {
LogUtil.w(TAG, "设置文件修改时间成功: " + file.getPath());
}
} catch (Exception e) {
LogUtil.e(TAG, "保存文件失败", e);
e.printStackTrace();
return false;
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
}
}
}
return true;
}
/**
*
* @param fileFullPath 文件的完整路径
* @param content
* @param modificationTime
* @return
*/
public static boolean saveFileToPath(String fileFullPath, String content, long modificationTime) {
File file = new File(fileFullPath);
return saveFile(file, content, modificationTime);
}
/**
* 保存文件到指定路径,并设置指定的最后修改时间
*
* @param fileParentPath 保存文件的父目录路径
* @param fileName 文件名
* @param content 文件内容
* @param modificationTime 最后修改时间(毫秒时间戳)
* @return 保存是否成功
*/
public static boolean saveFileToPath(String fileParentPath, String fileName, String content, long modificationTime) {
File file = new File(fileParentPath, fileName);
return saveFile(file, content, modificationTime);
}
......@@ -258,4 +297,45 @@ public class DeckSquareFileUtil {
}
return cardList;
}
public static long convertToUnixTimestamp(String DateTime) {
try {
//DateTime 格式为 ""yyyy-MM-dd'T'HH:mm:ss""
DateTimeFormatter formatter = null;
// 解析为本地时间,再关联到 UTC+8 时区
LocalDateTime localDateTime = null;
ZonedDateTime zonedDateTime = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
localDateTime = LocalDateTime.parse(DateTime, formatter);
zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
return zonedDateTime.toInstant().toEpochMilli();
}
} catch (Exception e) {
e.printStackTrace();
return 0;
}
return 0;
}
/**
* 将 Unix 时间戳转换为 GMT 格式的日期字符串
* @param timestamp 时间戳(毫秒)
* @return GMT 格式的日期字符串(例如:Thu, 04 Jul 2025 08:00:55 GMT)
*/
public static String convertToGMTDate(long timestamp) {
try {
// 创建格式化器并设置时区为 GMT
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.CHINA);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
// 格式化时间戳
return sdf.format(new Date(timestamp));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.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;
......@@ -16,7 +15,7 @@ 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.ui.cards.deck_square.api_response.OnlineDeckDetail;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.lite.databinding.FragmentDeckSquareBinding;
import cn.garymb.ygomobile.utils.YGODeckDialogUtil;
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square;
import android.util.Log;
......@@ -7,11 +7,9 @@ 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.ui.cards.deck_square.api_response.GetSquareDeckCondition;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.OnlineDeckDetail;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.SquareDeckResponse;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square;
import android.os.Bundle;
import android.text.Editable;
......@@ -8,15 +8,16 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Toast;
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.cards.deck_square.api_response.LoginResponse;
import cn.garymb.ygomobile.ui.mycard.MyCard;
import cn.garymb.ygomobile.ui.mycard.bean.McUser;
import cn.garymb.ygomobile.ui.mycard.mcchat.ChatMessage;
......@@ -33,7 +34,7 @@ import cn.garymb.ygomobile.utils.glide.GlideCompat;
//之后读取平台上的卡组,与本地卡组列表做比较。
public class DeckSquareMyDeckFragment extends Fragment {
private static final String TAG = DeckSquareListAdapter.class.getSimpleName();
private static final String TAG = "seesee";
private FragmentDeckSquareMyDeckBinding binding;
private MyDeckListAdapter deckListAdapter;
private String keyWord;
......@@ -57,7 +58,7 @@ public class DeckSquareMyDeckFragment extends Fragment {
binding.tvMycardUserName.setText(SharedPreferenceUtil.getMyCardUserName());
GlideCompat.with(getActivity()).load(ChatMessage.getAvatarUrl(SharedPreferenceUtil.getMyCardUserName())).into(binding.myDeckAvatar);//刷新头像图片
}
//DeckSquareApiUtil.synchronizeDecks();
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, onDeckMenuListener, mDialogListener);
......@@ -194,9 +195,17 @@ public class DeckSquareMyDeckFragment extends Fragment {
});
/** 自动同步 */
VUiKit.defer().when(() -> {return DeckSquareApiUtil.synchronizeDecks();}).fail((e) -> {
LogUtil.i(TAG, "Sync deck fail: " + e.getMessage());
}).done((result) -> {});
//DeckSquareApiUtil.synchronizeDecks();
VUiKit.defer().when(() -> {
return DeckSquareApiUtil.synchronizeDecks();
}).fail((e) -> {
YGOUtil.showTextToast("Sync decks fail", Toast.LENGTH_LONG);
LogUtil.i(TAG, "Sync decks fail" + e.getMessage());
}).done((result) -> {
String info = "sync decks: upload " + result.syncUpload.size() + ", download " + result.newDownload.size();
YGOUtil.showTextToast(info, Toast.LENGTH_LONG);
});
}
}
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square;
import android.util.Log;
import android.widget.ImageView;
......@@ -11,11 +11,12 @@ 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.ui.cards.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.LoginToken;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.MyDeckResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.MyOnlineDeckDetail;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushSingleDeckResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.bo.MyDeckItem;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.ui.plus.DialogPlus;
......@@ -74,7 +75,6 @@ public class MyDeckListAdapter extends BaseQuickAdapter<MyDeckItem, BaseViewHold
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());
......@@ -132,7 +132,7 @@ public class MyDeckListAdapter extends BaseQuickAdapter<MyDeckItem, BaseViewHold
}
VUiKit.defer().when(() -> {
PushDeckResponse result = DeckSquareApiUtil.deleteDeck(item.getDeckId(), loginToken);
PushSingleDeckResponse result = DeckSquareApiUtil.deleteDeck(item.getDeckId(), loginToken);
return result;
}).fail(e -> {
LogUtil.i(TAG, "square deck detail fail" + e.getMessage());
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class BasicResponse {
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
......
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class DeckMultiIdResponse {
@Expose
public int code;
@Expose
public String message;
@Expose
@SerializedName("data")
public List<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 List<String> getDeckId() {
return deckId;
}
public void setDeckId(List<String> deckId) {
this.deckId = deckId;
}
@Override
public String toString() {
return "DeckMultiIdResponse{" +
"code=" + code +
", message='" + message + '\'' +
", deckId=" + deckId +
'}';
}
}
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class DeleteCardJson {
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class DownloadDeckResponse {
private Integer code;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class GetSquareDeckCondition {
Integer page;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class LoginRequest {
public String account;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class LoginResponse {
public String token;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class LoginToken {
Integer userId;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import java.util.List;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import android.os.Parcel;
import android.os.Parcelable;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import android.os.Parcel;
import android.os.Parcelable;
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class PushDeckPublicState {
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import java.util.List;
import cn.garymb.ygomobile.deck_square.api_response.PushSingleDeck.DeckData;
/*卡组同步请求类*/
public class PushMultiDeck {
private String deckContributor;
......
package cn.garymb.ygomobile.deck_square.api_response;
/* 同步卡组响应体类*/
public class SyncDecksResponse {
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class PushMultiResponse {
private Integer code;
private String message;
//!!!!注意,本字段是integer,与PushSingleDeckResponse的不同!
private Integer data;
public SyncDecksResponse(Integer code, String message, Integer data) {
this.code = code;
this.message = message;
this.data = data;
}
// getters and setters
public Integer getCode() {
return code;
}
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
public class PushSingleDeck {
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
//将卡组上传后,返回的响应
//对应接口http://rarnu.xyz:38383/api/mdpro3/sync/single
public class PushDeckResponse {
public class PushSingleDeckResponse {
private Integer code;
private String message;
//!!!!注意,本字段是boolean,与PushMultiDeckResponse的不同!
private boolean data;//服务器的执行结果,true代表卡组上传成功。false代表卡组上传失败
public Integer getCode() {
......
package cn.garymb.ygomobile.deck_square.api_response;
package cn.garymb.ygomobile.ui.cards.deck_square.api_response;
import java.util.List;
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square.bo;
import android.os.Parcel;
import android.os.Parcelable;
......
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square.bo;
public class MyDeckItem {
//0代表未推到服务器,3代表包含deckId,1代表服务器存在可下载到本地,2代表已同步
public int idUploaded;
private int idUploaded;
public int userId;
public String deckName;
private int userId;
private String deckName;
public String deckId;
private String deckId;
public String updateDate;
private String updateDate;
private long updateTimestamp;
public int deckSouce;//卡组来源,0代表来自本地,1代表来自服务器
private String deckPath;//本地卡组时,存储卡组路径
public String deckPath;//本地卡组时,存储卡组路径
private int deckCoverCard1;
public int deckCoverCard1;
public Boolean isPublic;
private Boolean isPublic;
public int getIdUploaded() {
return idUploaded;
......@@ -59,12 +58,12 @@ public class MyDeckItem {
this.updateDate = updateDate;
}
public int getDeckSouce() {
return deckSouce;
public long getUpdateTimestamp() {
return updateTimestamp;
}
public void setDeckSouce(int deckSouce) {
this.deckSouce = deckSouce;
public void setUpdateTimestamp(long updateTimestamp) {
this.updateTimestamp = updateTimestamp;
}
public int getDeckCoverCard1() {
......@@ -100,7 +99,7 @@ public class MyDeckItem {
", deckName='" + deckName + '\'' +
", deckId='" + deckId + '\'' +
", updateDate='" + updateDate + '\'' +
", deckSouce=" + deckSouce +
", updateTimestamp=" + updateTimestamp +
", deckPath='" + deckPath + '\'' +
", deckCoverCard1=" + deckCoverCard1 +
", isPublic=" + isPublic +
......
package cn.garymb.ygomobile.ui.cards.deck_square.bo;
import java.util.ArrayList;
import java.util.List;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.MyOnlineDeckDetail;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushMultiResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushSingleDeckResponse;
public class SyncMutliDeckResult {
boolean flag = false;
String info = null;
public PushMultiResponse pushResponse;
public List<MyDeckItem> syncUpload;//用于记录已推送的卡组
public List<MyDeckItem> newUpload;//用于记录第一次推送到云的卡组
public List<MyDeckItem> syncDownload;//用于记录已推送的卡组
public List<MyOnlineDeckDetail> newDownload;
public List<DownloadResult> downloadResponse;
public static class DownloadResult {
boolean flag;
String deckId;
String info;
public DownloadResult(boolean flag, String deckId) {
this.flag = flag;
this.deckId = deckId;
}
public DownloadResult(boolean flag, String deckId, String info) {
this.flag = flag;
this.deckId = deckId;
this.info = info;
}
}
public SyncMutliDeckResult() {
flag = true;
downloadResponse = new ArrayList<>();
newDownload = new ArrayList<>();
syncUpload = new ArrayList<>();
newUpload = new ArrayList<>();
syncDownload = new ArrayList<>();
}
public SyncMutliDeckResult(boolean flag, String info) {
this.flag = flag;
this.info = info;
downloadResponse = new ArrayList<>();
newDownload = new ArrayList<>();
syncUpload = new ArrayList<>();
newUpload = new ArrayList<>();
syncDownload = new ArrayList<>();
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getMessage() {
String info = "sync decks: " + syncUpload.size() + ", push new:" + newUpload.size() + ", download " + newDownload.size();
return info;
}
}
package cn.garymb.ygomobile.deck_square;
package cn.garymb.ygomobile.ui.cards.deck_square.bo;
import java.util.List;
......
......@@ -3,7 +3,6 @@ package cn.garymb.ygomobile.utils;
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
......@@ -11,11 +10,11 @@ import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.ConnectionPool;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
......@@ -23,68 +22,15 @@ import okhttp3.Response;
public class OkhttpUtil {
private static OkHttpClient okHttpClient;
public static void put(String address, Map<String, Object> map, String cookie, Callback callback) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
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 (map != null)
request.put(builder1.build());
else
request.put(okhttp3.internal.Util.EMPTY_REQUEST);
// Log.e("OkhttpUtil","post请求:"+builder1.build().toString());
if (!TextUtils.isEmpty(cookie)) {
request.addHeader("cookie", cookie);
}
client.build().newCall(request.build()).enqueue(callback);
}
// private static OkHttpClient okHttpClient;
private static final OkHttpClient client = new OkHttpClient.Builder()
// customize timeouts as needed
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
// keep-alive and connection pool defaults
.connectionPool(new ConnectionPool(2, 40, TimeUnit.SECONDS))
.build();
public static void get(String address, Callback callback) {
......@@ -96,7 +42,6 @@ public class OkhttpUtil {
}
public static void get(String address, Map<String, Object> map, String cookie, Callback callback) {
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder httpBuilder = HttpUrl.parse(address).newBuilder();
if (map != null) {
......@@ -115,7 +60,6 @@ public class OkhttpUtil {
}
public static Response synchronousGet(String address, Map<String, Object> paramMap, Map<String, String> headers) throws IOException {
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder httpBuilder = HttpUrl.parse(address).newBuilder();
if (paramMap != null) {
......@@ -139,7 +83,6 @@ public class OkhttpUtil {
}
public static void del(String address, Map<String, Object> map, String cookie, Callback callback) {
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder httpBuilder = HttpUrl.parse(address).newBuilder();
if (map != null) {
......@@ -174,7 +117,6 @@ public class OkhttpUtil {
}
public static void post(String url, String json, String cookie, Callback callback) {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json);
Request.Builder request = new Request.Builder().url(url);//请求的url
if (TextUtils.isEmpty(json))
......@@ -184,16 +126,16 @@ public class OkhttpUtil {
if (!TextUtils.isEmpty(cookie)) {
request.addHeader("cookie", cookie);
}
okHttpClient.newCall(request.build()).enqueue(callback);
client.newCall(request.build()).enqueue(callback);
}
public static void cancelTag(Object tag) {
for (Call call : okHttpClient.dispatcher().queuedCalls()) {
for (Call call : client.dispatcher().queuedCalls()) {
if (tag.equals(call.request().tag())) {
call.cancel();
}
}
for (Call call : okHttpClient.dispatcher().runningCalls()) {
for (Call call : client.dispatcher().runningCalls()) {
if (tag.equals(call.request().tag())) {
call.cancel();
}
......@@ -206,16 +148,8 @@ public class OkhttpUtil {
* @param url
* @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();
if (timeout != 0)
okHttpClient = okHttpClient.newBuilder().connectTimeout(timeout, TimeUnit.SECONDS)//设置连接超时时间
.readTimeout(timeout, TimeUnit.SECONDS)//设置读取超时时间
.build();
public static Response postJson(String url, String json, Map<String, String> headers) throws IOException {
Request.Builder request = new Request.Builder().url(url);//请求的url
if (json == null || TextUtils.isEmpty(json)) {
......@@ -233,7 +167,7 @@ public class OkhttpUtil {
}
Log.e("OkhttpUtil", json + " 状态 " + request.build());
return okHttpClient.newCall(request.build()).execute();
return client.newCall(request.build()).execute();
}
/**
......
......@@ -498,7 +498,6 @@ public class YGODeckDialogUtil {
deckFile.getPathFile().delete();
deckList.remove(deckFile);
}
YGOUtil.showTextToast(context.getString(R.string.done));
dialogPlus.dismiss();
onDeckMenuListener.onDeckDel(selectDeckList);
clearDeckSelect();
......@@ -544,7 +543,7 @@ public class YGODeckDialogUtil {
}
}
IOUtils.delete(file);
YGOUtil.showTextToast(context.getString(R.string.done));
onDeckMenuListener.onDeckDel(deckFileList);
typeAdp.remove(positon);
if (typeAdp.getSelectPosition() == positon) {
......
......@@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/veil2"
android:background="@drawable/button_radius_black_transparents"
android:paddingBottom="5dp">
<com.google.android.material.tabs.TabLayout
......
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