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 android.annotation.SuppressLint;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
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.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.MyOnlineDeckDetail;
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.PushMultiDeck;
import cn.garymb.ygomobile.deck_square.api_response.PushSingleDeck;
import cn.garymb.ygomobile.deck_square.api_response.SquareDeckResponse;
import cn.garymb.ygomobile.deck_square.api_response.SyncDecksResponse;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.BasicResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.DeckIdResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.DeckMultiIdResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.DownloadDeckResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.GetSquareDeckCondition;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.LoginRequest;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.LoginResponse;
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.PushDeckPublicState;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushMultiDeck;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushMultiResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushSingleDeck;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.PushSingleDeckResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.api_response.SquareDeckResponse;
import cn.garymb.ygomobile.ui.cards.deck_square.bo.MyDeckItem;
import cn.garymb.ygomobile.ui.cards.deck_square.bo.SyncMutliDeckResult;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.DeckUtil;
import cn.garymb.ygomobile.utils.LogUtil;
......@@ -53,7 +47,7 @@ import okhttp3.Response;
public class DeckSquareApiUtil {
private static final String TAG = "decksquareApiUtil";
private static final String TAG = "seesee";
public static boolean needLogin() {
......@@ -76,7 +70,7 @@ public class DeckSquareApiUtil {
Integer serverUserId = SharedPreferenceUtil.getServerUserId();
if (serverToken == null || serverUserId == -1) {
YGOUtil.showTextToast(R.string.login_mycard);
YGOUtil.showTextToast("Please login first!");
return null;
}
return new LoginToken(serverUserId, serverToken);
......@@ -97,7 +91,7 @@ public class DeckSquareApiUtil {
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/list";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("ReqSource", "YGOMobile");
Map<String, Object> paramMap = new HashMap<>();
......@@ -134,7 +128,7 @@ public class DeckSquareApiUtil {
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
Response response = OkhttpUtil.synchronousGet(url, null, headers);
......@@ -161,7 +155,7 @@ public class DeckSquareApiUtil {
String url = "http://rarnu.xyz:38383/api/mdpro3/deck/" + deckId;
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("ReqSource", "YGOMobile");
Response response = OkhttpUtil.synchronousGet(url, null, headers);
String responseBodyString = response.body().string();
......@@ -178,6 +172,83 @@ public class DeckSquareApiUtil {
}
/**
* 阻塞方法,将对应于deckId、deckName的卡组内容json推送到服务器。
* 如果在服务器存在deckId相同的记录,则更新卡组,deckName会覆盖服务器上的卡组名
* 如果在服务器存在deckName相同、deckId不同的记录,则更新失败
*
* @param deckfile
* @param loginToken
* @param deckId
* @return
* @throws IOException
*/
private static PushSingleDeckResponse pushDeck(DeckFile deckfile, LoginToken loginToken, String deckId) throws IOException {
String deckContent = DeckSquareFileUtil.setDeckId(deckfile.getPath(), loginToken.getUserId(), deckId);
PushSingleDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/sync/single";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
PushSingleDeck pushSingleDeck = new PushSingleDeck();
pushSingleDeck.setDeckContributor(loginToken.getUserId().toString());
pushSingleDeck.setUserId(loginToken.getUserId());
PushSingleDeck.DeckData deckData = new PushSingleDeck.DeckData();
deckData.setDeckId(deckId);
deckData.setDeckName(deckfile.getName());
deckData.setDeckCoverCard1(deckfile.getFirstCode());
deckData.setDelete(false);
deckData.setDeckYdk(deckContent);
pushSingleDeck.setDeck(deckData);
String json = gson.toJson(pushSingleDeck);
Response response = OkhttpUtil.postJson(url, json, headers);
String responseBodyString = response.body().string();
result = gson.fromJson(responseBodyString, PushSingleDeckResponse.class);
LogUtil.i(TAG, "push deck response:" + responseBodyString);
return result;
}
/**
* 阻塞方法,将对应于deckDataList、deckIdList的卡组内容json推送到服务器。
* 如果在服务器存在deckId相同的记录,则更新卡组,deckName会覆盖服务器上的卡组名
* 如果在服务器存在deckName相同、deckId不同的记录,则更新失败
*
* @param deckDataList
* @param loginToken
* @param deckIdList
* @return
* @throws IOException
*/
private static PushMultiResponse pushDecks(List<MyDeckItem> deckDataList, LoginToken loginToken, List<String> deckIdList) throws IOException {
List<PushMultiDeck.DeckData> decks = new ArrayList<>();
if (deckDataList.size() != deckIdList.size()) {
return null;
}
for (int i = 0; i < deckDataList.size(); i++) {
MyDeckItem myDeckItem = deckDataList.get(i);
String deckContent = DeckSquareFileUtil.setDeckId(myDeckItem.getDeckPath(), loginToken.getUserId(), deckIdList.get(i));
PushMultiDeck.DeckData data = new PushMultiDeck.DeckData();
data.setDeckYdk(deckContent);
data.setDeckName(myDeckItem.getDeckName());
data.setDeckCoverCard1(myDeckItem.getDeckCoverCard1());
data.setDeckId(deckIdList.get(i));
decks.add(data);
}
return pushMultiDecks(decks, loginToken);
}
/**
* 阻塞方法,推送新卡组的内容时使用。首先从服务器请求一个新的卡组id,之后将卡组上传到服务器
* 首先调用服务端api获取卡组id,之后将卡组id设置到ydk中,之后调用服务器api将卡组上传
......@@ -185,7 +256,7 @@ public class DeckSquareApiUtil {
* @param deckFile
* @param loginToken
*/
public static PushDeckResponse requestIdAndPushDeck(DeckFile deckFile, LoginToken loginToken) throws IOException {
public static PushSingleDeckResponse requestIdAndPushNewDeck(DeckFile deckFile, LoginToken loginToken) throws IOException {
if (loginToken == null) {
return null;
......@@ -194,7 +265,7 @@ public class DeckSquareApiUtil {
String getDeckIdUrl = "http://rarnu.xyz:38383/api/mdpro3/deck/deckId";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
......@@ -221,75 +292,98 @@ public class DeckSquareApiUtil {
}
/**
* 阻塞方法,将对应于deckId、deckName的卡组内容json推送到服务器。
* 如果在服务器上不存在deckId、deckName对应的记录,则创建新卡组
* 如果在服务器存在deckId相同的记录,则更新卡组,deckName会覆盖服务器上的卡组名
* 如果在服务器存在deckName相同、deckId不同的记录,则更新失败
* 阻塞方法,推送新卡组的内容时使用。首先从服务器请求一个新的卡组id,之后将卡组上传到服务器
* 首先调用服务端api获取卡组id,之后将卡组id设置到ydk中,之后调用服务器api将卡组上传
* 首先获取卡组id,之后上传新卡组
*
* @param deckfile
* @param deckDataList
* @param loginToken
* @param deckId
* @return
* @throws IOException
*/
public static PushDeckResponse pushDeck(DeckFile deckfile, LoginToken loginToken, String deckId) throws IOException {
String deckContent = DeckSquareFileUtil.setDeckId(deckfile.getPath(), loginToken.getUserId(), deckId);
public static PushMultiResponse requestIdAndPushNewDecks(List<MyDeckItem> deckDataList, LoginToken loginToken) throws IOException {
if (loginToken == null) {
return null;
}
if (deckDataList == null || deckDataList.isEmpty()) {
return null;
}
Gson gson = new Gson();
String getDeckIdUrl = "http://rarnu.xyz:38383/api/mdpro3/deck/deckIds";
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("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("count", deckDataList.size());
Response response = OkhttpUtil.synchronousGet(getDeckIdUrl, paramMap, headers);
DeckMultiIdResponse deckIdResult = gson.fromJson(response.body().string(), DeckMultiIdResponse.class);
Gson gson = new Gson();
PushSingleDeck pushSingleDeck = new PushSingleDeck();
pushSingleDeck.setDeckContributor(loginToken.getUserId().toString());
pushSingleDeck.setUserId(loginToken.getUserId());
PushSingleDeck.DeckData deckData = new PushSingleDeck.DeckData();
deckData.setDeckId(deckId);
deckData.setDeckName(deckfile.getName());
deckData.setDeckCoverCard1(deckfile.getFirstCode());
deckData.setDelete(false);
deckData.setDeckYdk(deckContent);
pushSingleDeck.setDeck(deckData);
String json = gson.toJson(pushSingleDeck);
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);
if (deckIdResult == null) {
return null;
}
List<String> deckId = deckIdResult.getDeckId();//从服务器获取
if (deckId == null) {
return null;
}
return result;
return pushDecks(deckDataList, loginToken, deckId);
}
/**
* @param deckDataList
* 批量上传已经在云上存在的卡组
*
* @param deckItems
* @param loginToken
* @return
* @throws IOException
*/
public static SyncDecksResponse syncDecks(List<PushMultiDeck.DeckData> deckDataList, LoginToken loginToken) throws IOException {
SyncDecksResponse result = null;
public static PushMultiResponse syncMyDecks(List<MyDeckItem> deckItems, LoginToken loginToken) throws IOException {
if (deckItems == null || deckItems.isEmpty()) {
return null;
}
/* 构造json */
List<PushMultiDeck.DeckData> dataList = new ArrayList<>();
for (MyDeckItem item : deckItems) {
PushMultiDeck.DeckData data = new PushMultiDeck.DeckData();
data.setDeckId(item.getDeckId());
data.setDeckName(item.getDeckName());
data.setDeckCoverCard1(item.getDeckCoverCard1());
String deckContent = DeckSquareFileUtil.setDeckId(item.getDeckPath(), loginToken.getUserId(), item.getDeckId());
data.setDeckYdk(deckContent);
dataList.add(data);
}
return pushMultiDecks(dataList, loginToken);
}
public static PushMultiResponse pushMultiDecks(List<PushMultiDeck.DeckData> dataList, LoginToken loginToken) throws IOException {
if (dataList.isEmpty()) {
return null;
}
String url = "http://rarnu.xyz:38383/api/mdpro3/sync/multi";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
PushMultiResponse result = null;
Gson gson = new Gson();
PushMultiDeck pushMultiDeck = new PushMultiDeck();
pushMultiDeck.setDeckContributor(loginToken.getUserId().toString());
pushMultiDeck.setUserId(loginToken.getUserId());
pushMultiDeck.setDecks(deckDataList);
pushMultiDeck.setDecks(dataList);
String json = gson.toJson(pushMultiDeck);
Response response = OkhttpUtil.postJson(url, json, headers, 1000);
Response response = OkhttpUtil.postJson(url, json, headers);
String responseBodyString = response.body().string();
result = gson.fromJson(responseBodyString, SyncDecksResponse.class);
LogUtil.i(TAG, "push deck response:" + responseBodyString);
result = gson.fromJson(responseBodyString, PushMultiResponse.class);
LogUtil.i(TAG, "pushMultiDecks response:" + responseBodyString);
return result;
}
......@@ -305,8 +399,8 @@ public class DeckSquareApiUtil {
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);
headers.put("ReqSource", "YGOMobile");
Response response = OkhttpUtil.postJson(url, null, headers);
String responseBodyString = response.body().string();
Gson gson = new Gson();
......@@ -323,13 +417,14 @@ public class DeckSquareApiUtil {
*
* @param deckId
*/
public static BasicResponse setDeckPublic(String deckId, LoginToken loginToken, boolean publicState) throws IOException {
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("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
Gson gson = new Gson();
......@@ -341,7 +436,7 @@ public class DeckSquareApiUtil {
String json = gson.toJson(pushData);
Response response = OkhttpUtil.postJson(url, json, headers, 1000);
Response response = OkhttpUtil.postJson(url, json, headers);
String responseBodyString = response.body().string();
result = gson.fromJson(responseBodyString, BasicResponse.class);
......@@ -395,11 +490,54 @@ public class DeckSquareApiUtil {
}
public static PushDeckResponse deleteDeck(String deckId, LoginToken loginToken) throws IOException {
PushDeckResponse result = null;
public static void deleteDecks(List<DeckFile> deckFileList) {
if (SharedPreferenceUtil.getServerToken() != null) {
LoginToken loginToken = new LoginToken(
SharedPreferenceUtil.getServerUserId(),
SharedPreferenceUtil.getServerToken()
);
// 创建一个局部变量来持有deckFileList的引用,因为有时候异步执行会导致获取不到传参的deckFileList
final List<DeckFile> localDeckFileList = new ArrayList<>(deckFileList);
// 获取在线卡组列表(异步处理)
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) {
for (DeckFile deckFile : localDeckFileList) {
if (onlineDeck.getDeckName().equals(deckFile.getName())) {
// 删除在线卡组(异步处理)
VUiKit.defer().when(() -> {
PushSingleDeckResponse 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");
}
});
break;
}
}
}
});
}
}
public static PushSingleDeckResponse deleteDeck(String deckId, LoginToken loginToken) throws
IOException {
PushSingleDeckResponse result = null;
String url = "http://rarnu.xyz:38383/api/mdpro3/sync/single";
Map<String, String> headers = new HashMap<>();
headers.put("ReqSource", "MDPro3");
headers.put("ReqSource", "YGOMobile");
headers.put("token", loginToken.getServerToken());
......@@ -416,11 +554,11 @@ public class DeckSquareApiUtil {
String json = gson.toJson(pushSingleDeck);
Response response = OkhttpUtil.postJson(url, json, headers, 1000);
Response response = OkhttpUtil.postJson(url, json, headers);
String responseBodyString = response.body().string();
// Convert JSON to Java object using Gson
result = gson.fromJson(responseBodyString, PushDeckResponse.class);
result = gson.fromJson(responseBodyString, PushSingleDeckResponse.class);
LogUtil.i(TAG, "push deck response:" + responseBodyString);
......@@ -436,11 +574,14 @@ public class DeckSquareApiUtil {
}
public static boolean synchronizeDecks() throws IOException {
public static SyncMutliDeckResult synchronizeDecksV2() throws IOException {
SyncMutliDeckResult autoSyncResult = new SyncMutliDeckResult();
// 检查用户是否登录
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
return false;
autoSyncResult.setFlag(false);
autoSyncResult.setInfo("need login");
return autoSyncResult;
}
// 获取本地卡组列表
......@@ -448,54 +589,53 @@ public class DeckSquareApiUtil {
// 获取在线卡组列表
MyDeckResponse onlineDecksResponse = DeckSquareApiUtil.getUserDecks(loginToken);
if (onlineDecksResponse == null || onlineDecksResponse.getData() == null) {
return false;
autoSyncResult.setFlag(false);
autoSyncResult.setInfo("no online decks");
return autoSyncResult;
}
List<MyOnlineDeckDetail> onlineDecks = onlineDecksResponse.getData();
// 用于标记在线卡组是否在本地有对应
Map<String, Boolean> onlineDeckProcessed = new HashMap<>();
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
onlineDeckProcessed.put(onlineDeck.getDeckName(), false);
}
// 用于标记本地卡组是否在在线有对应
Map<String, Boolean> localDeckProcessed = new HashMap<>();
for (MyDeckItem localDeck : localDecks) {
String deckName = localDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
localDeckProcessed.put(deckName, false);
}
List<MyDeckItem> syncUploadDecks = new ArrayList<>();
List<MyDeckItem> newPushDecks = new ArrayList<>();
// 遍历本地卡组,处理同名卡组的情况
for (MyDeckItem localDeck : localDecks) {
String localDeckName = localDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
localDeck.setDeckName(localDeckName);//移除.ydk扩展名后需要修改lockDeck记录的卡组名,以防上传时候把.ydk带进去
boolean foundOnlineDeck = false;
String localDeckName = localDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
String onlineDeckName = onlineDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
if (localDeckName.equals(onlineDeckName)) {
String onLineDeckName = onlineDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
if (localDeckName.equals(onLineDeckName)) {
// 标记该在线卡组已处理
onlineDeckProcessed.put(onlineDeck.getDeckName(), true);
onlineDeckProcessed.put(onLineDeckName, true);
// 标记该本地卡组已处理
localDeckProcessed.put(localDeckName, true);
foundOnlineDeck = true;
// 比对更新时间
String localUpdateDate = localDeck.getUpdateDate();
String onlineUpdateDate = "";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
LocalDateTime dateTime = LocalDateTime.parse(onlineDeck.getDeckUpdateDate());
onlineUpdateDate = String.valueOf(dateTime.toInstant(ZoneOffset.UTC).toEpochMilli());
}
if (onlineUpdateDate != null && onlineUpdateDate.compareTo(localUpdateDate) > 0) {
long localUpdateDate = localDeck.getUpdateTimestamp();
long onlineUpdateDate = DeckSquareFileUtil.convertToUnixTimestamp(onlineDeck.getDeckUpdateDate());//todo 这里应该把2025-05-19T06:11:17转成毫秒,onlineDeck.getDeckUpdateDate();
LogUtil.d("seesee 本地和在线时间差", localDeckName + ": " + (localUpdateDate - onlineUpdateDate > 0 ? "本地的-新" : "在线的-新"));
LogUtil.d("seesee 差多少", localDeckName + ": " + (localUpdateDate - onlineUpdateDate));
if (onlineUpdateDate > localUpdateDate) {
// 在线卡组更新时间更晚,下载在线卡组覆盖本地卡组
LogUtil.w("seesee下载", localDeckName+"//"+onlineDeckName);
String localPath = localDeck.getDeckPath().replace(localDeckName + Constants.YDK_FILE_EX, "");//直接传入localDeck.getDeckPath()会包含卡组名.ydk,会导致和onlinedeck.getDeckName重复拼接文件路径
downloadOnlineDeck(onlineDeck, localPath, Long.valueOf(onlineDeck.getDeckUpdateDate()));
LogUtil.w(TAG, "seesee *下载* " + localDeck.getDeckPath());
autoSyncResult.syncDownload.add(localDeck);
downloadOnlineDeck(onlineDeck, localDeck.getDeckPath(), onlineUpdateDate);
} else if (onlineUpdateDate == localUpdateDate) {
LogUtil.w(TAG, "seesee 不需要同步: " + localDeck.getDeckName());
//时间戳相同,不需要更新
} else {
LogUtil.w("seesee上传", localDeckName + "//" + onlineDeckName);
// 本地卡组更新时间更晚,上传本地卡组覆盖在线卡组
uploadLocalDeck(localDeck, onlineDeck.getDeckId(), loginToken);
localDeck.setDeckName(localDeck.getDeckName().replace(Constants.YDK_FILE_EX, ""));//TODO 上版本很多人已经传了带.ydk的云备份,姑且只在这次再次上传时去掉.ydk
localDeck.setDeckCoverCard1(DeckUtil.getFirstCardCode(localDeck.getDeckPath()));
localDeck.setDeckId(onlineDeck.getDeckId());
LogUtil.w(TAG, "seesee -上传-" + localDeck.getDeckName());
syncUploadDecks.add(localDeck);
autoSyncResult.syncUpload.add(localDeck);
}
break;
}
......@@ -503,40 +643,152 @@ public class DeckSquareApiUtil {
// 本地卡组在在线列表中不存在,则需要获取新的deckid来直接上传
if (!foundOnlineDeck) {
DeckFile deckFile = new DeckFile(localDeckName, new File(localDeck.getDeckPath()), DeckType.ServerType.MY_SQUARE, localDeck.getDeckId());
deckFile.setName(localDeckName);
deckFile.setFirstCode(DeckUtil.getFirstCardCode(localDeck.getDeckPath()));
requestIdAndPushDeck(deckFile, loginToken);
localDeck.setDeckName(localDeck.getDeckName().replace(Constants.YDK_FILE_EX, ""));
localDeck.setDeckCoverCard1(DeckUtil.getFirstCardCode(localDeck.getDeckPath()));
LogUtil.w(TAG, "seesee upload deck new: " + localDeck.getDeckName() + "、封面id:" + localDeck.getDeckCoverCard1());
newPushDecks.add(localDeck);
autoSyncResult.newUpload.add(localDeck);
}
}
LogUtil.w(TAG, "before syncMyDecks-unpload syncUploadDecks size(): " + syncUploadDecks.size());
if (!syncUploadDecks.isEmpty()) {
PushMultiResponse response = syncMyDecks(syncUploadDecks, loginToken);
autoSyncResult.pushResponse = response;
LogUtil.w(TAG, "after syncMyDecks-upload");
}
LogUtil.w(TAG, "newPushDecks size " + newPushDecks.size());
if (!newPushDecks.isEmpty()) {
LogUtil.w(TAG, "before new decks-upload");
PushMultiResponse pushNewRes = requestIdAndPushNewDecks(newPushDecks, loginToken);
LogUtil.w(TAG, "after new decks-upload");
}
LogUtil.w(TAG, "before download online decks " + onlineDecks.size());
// 处理只存在于在线的卡组(即本地没有同名卡组)
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
String onLineDeckName = onlineDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
if (!onlineDeckProcessed.get(onLineDeckName)) {
autoSyncResult.newDownload.add(onlineDeck);
LogUtil.w(TAG, "sync-download new deck: " + onlineDeck.getDeckName());
SyncMutliDeckResult.DownloadResult downloadResult = downloadMissingDeckToLocal(onlineDeck, DeckSquareFileUtil.convertToUnixTimestamp(onlineDeck.getDeckUpdateDate()));
autoSyncResult.downloadResponse.add(downloadResult);
}
}
return autoSyncResult;
}
public static SyncMutliDeckResult synchronizeDecks() throws IOException {
SyncMutliDeckResult autoSyncResult = new SyncMutliDeckResult();
// 检查用户是否登录
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
autoSyncResult.setFlag(false);
autoSyncResult.setInfo("need login");
return autoSyncResult;
}
// 获取本地卡组列表
List<MyDeckItem> localDecks = DeckSquareFileUtil.getMyDeckItem();
// 获取在线卡组列表
MyDeckResponse onlineDecksResponse = DeckSquareApiUtil.getUserDecks(loginToken);
if (onlineDecksResponse == null || onlineDecksResponse.getData() == null) {
autoSyncResult.setFlag(false);
autoSyncResult.setInfo("no online decks");
return autoSyncResult;
}
List<MyOnlineDeckDetail> onlineDecks = onlineDecksResponse.getData();
// 用于标记在线卡组是否在本地有对应
Map<String, Boolean> onlineDeckProcessed = new HashMap<>();
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
onlineDeckProcessed.put(onlineDeck.getDeckName(), false);
}
List<MyDeckItem> syncUploadDecks = new ArrayList<>();
List<MyDeckItem> newPushDecks = new ArrayList<>();
// 遍历本地卡组,处理同名卡组的情况
for (MyDeckItem localDeck : localDecks) {
boolean foundOnlineDeck = false;
String localDeckName = localDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
String onLineDeckName = onlineDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
if (localDeckName.equals(onLineDeckName)) {
// 标记该在线卡组已处理
onlineDeckProcessed.put(onLineDeckName, true);
// 标记该本地卡组已处理
foundOnlineDeck = true;
// 将每个本地卡组作为数组元素添加入syncUploadDecks
localDeck.setDeckName(localDeck.getDeckName().replace(Constants.YDK_FILE_EX, ""));//TODO 上版本很多人已经传了带.ydk的云备份,姑且只在这次再次上传时去掉.ydk
localDeck.setDeckCoverCard1(DeckUtil.getFirstCardCode(localDeck.getDeckPath()));
localDeck.setDeckId(onlineDeck.getDeckId());
syncUploadDecks.add(localDeck);
autoSyncResult.syncUpload.add(localDeck);
break;
}
}
// 本地卡组在在线列表中不存在,则需要获取新的deckid来直接上传
if (!foundOnlineDeck) {
localDeck.setDeckName(localDeck.getDeckName().replace(Constants.YDK_FILE_EX, ""));
localDeck.setDeckCoverCard1(DeckUtil.getFirstCardCode(localDeck.getDeckPath()));
newPushDecks.add(localDeck);
autoSyncResult.newUpload.add(localDeck);
}
}
if (!newPushDecks.isEmpty()) {
LogUtil.w(TAG, "seesee +要上传的 本地卡组: " + newPushDecks);
requestIdAndPushNewDecks(newPushDecks, loginToken);
}
// 处理只存在于在线的卡组(即本地没有同名卡组)
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
if (!onlineDeckProcessed.get(onlineDeck.getDeckName())) {
downloadMissingDeckToLocal(onlineDeck, Long.valueOf(onlineDeck.getDeckUploadDate()));
String onLineDeckName = onlineDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
if (!onlineDeckProcessed.get(onLineDeckName)) {
autoSyncResult.newDownload.add(onlineDeck);
LogUtil.w(TAG, "seesee sync-download new deck: " + onlineDeck.getDeckName());
SyncMutliDeckResult.DownloadResult downloadResult = downloadMissingDeckToLocal(onlineDeck, DeckSquareFileUtil.convertToUnixTimestamp(onlineDeck.getDeckUpdateDate()));
autoSyncResult.downloadResponse.add(downloadResult);
}
}
return true;
// 上传本地卡组覆盖在线卡组
PushMultiResponse response = syncMyDecks(syncUploadDecks, loginToken);//TODO 一定要最后执行这行,否则会直接终止后续执行
autoSyncResult.pushResponse = response;
return autoSyncResult;
}
private static boolean downloadMissingDeckToLocal(MyOnlineDeckDetail onlineDeck, Long onlineUpdateDate) {
private static SyncMutliDeckResult.DownloadResult downloadMissingDeckToLocal(MyOnlineDeckDetail onlineDeck, Long onlineUpdateDate) {
try {
// 根据卡组ID查询在线卡组详情
DownloadDeckResponse deckResponse = DeckSquareApiUtil.getDeckById(onlineDeck.getDeckId());
if (deckResponse == null || deckResponse.getData() == null) {
LogUtil.e(TAG, "Failed to get deck details for: " + onlineDeck.getDeckName());
return false;
LogUtil.e(TAG, "seesee Failed to get deck details for: " + onlineDeck.getDeckName());
return new SyncMutliDeckResult.DownloadResult(false, onlineDeck.getDeckId(), "Failed to get deck details for: " + onlineDeck.getDeckName());
}
// 构建本地文件路径
String deckDirectory = AppsSettings.get().getDeckDir();
File dir = new File(deckDirectory);
if (!dir.exists()) {
boolean created = dir.mkdirs();
if (!created) {
LogUtil.e(TAG, "Failed to create directory: " + deckDirectory);
return false;
LogUtil.e(TAG, "seesee Failed to create directory: " + deckDirectory);
return new SyncMutliDeckResult.DownloadResult(false, onlineDeck.getDeckId(), "Failed to create directory: " + deckDirectory);
}
}
......@@ -546,33 +798,26 @@ public class DeckSquareApiUtil {
fileName += Constants.YDK_FILE_EX;
}
String filePath = deckDirectory + "/" + fileName;
String fileFullPath = deckDirectory + "/" + fileName;
// 保存在线卡组到本地
boolean saved = DeckSquareFileUtil.saveFileToPath(deckDirectory, fileName, deckResponse.getData().getDeckYdk(), onlineUpdateDate);
boolean saved = DeckSquareFileUtil.saveFileToPath(fileFullPath, deckResponse.getData().getDeckYdk(), onlineUpdateDate);
if (!saved) {
LogUtil.e(TAG, "downloadMissingDeckToLocal-Failed to save deck file: " + filePath);
return false;
LogUtil.e(TAG, "seesee Failed to save deck file: " + fileFullPath);
return new SyncMutliDeckResult.DownloadResult(false, onlineDeck.getDeckId(), "Failed to save deck file: " + fileFullPath);
}
LogUtil.i(TAG, "downloadMissingDeckToLocal-Deck saved to: " + filePath);
// 更新本地卡组列表
MyDeckItem newLocalDeck = new MyDeckItem();
newLocalDeck.setDeckName(fileName);
newLocalDeck.setDeckPath(filePath);
newLocalDeck.setDeckId(onlineDeck.getDeckId());
newLocalDeck.setIdUploaded(2); // 已上传状态
newLocalDeck.setUpdateDate(onlineDeck.getDeckUpdateDate());
LogUtil.i(TAG, "seesee Deck saved to: " + fileFullPath);
return true;
return new SyncMutliDeckResult.DownloadResult(true, onlineDeck.getDeckId());
} catch (Exception e) {
LogUtil.e(TAG, "Error downloading missing deck: " + e.getMessage());
return false;
LogUtil.e(TAG, "seesee Error downloading missing deck: " + e.getMessage());
e.printStackTrace();
return new SyncMutliDeckResult.DownloadResult(false, onlineDeck.getDeckId(), "Error downloading missing deck: " + e.getMessage());
}
}
private static boolean downloadOnlineDeck(MyOnlineDeckDetail onlineDeck, String localPath, Long onlineUpdateDate) {
private static boolean downloadOnlineDeck(MyOnlineDeckDetail onlineDeck, String fileFullPath, Long onlineUpdateDate) {
try {
// 根据卡组ID查询在线卡组详情
DownloadDeckResponse deckResponse = DeckSquareApiUtil.getDeckById(onlineDeck.getDeckId());
......@@ -581,15 +826,16 @@ public class DeckSquareApiUtil {
return false;
}
MyOnlineDeckDetail deckDetail = deckResponse.getData();
String deckContent = deckDetail.getDeckYdk();
// 保存在线卡组到本地
String fileName = onlineDeck.getDeckName() + Constants.YDK_FILE_EX;
boolean saved = DeckSquareFileUtil.saveFileToPath(localPath, fileName, deckResponse.getData().getDeckYdk(), onlineUpdateDate);
boolean saved = DeckSquareFileUtil.saveFileToPath(fileFullPath, deckContent, onlineUpdateDate);
if (!saved) {
LogUtil.e(TAG, "downloadOnlineDeck-Failed to save deck file: " + fileName);
LogUtil.e(TAG, "Failed to save deck file: " + fileFullPath);
return false;
}
LogUtil.i(TAG, "Deck updated: " + fileName);
LogUtil.i(TAG, "Deck updated: " + fileFullPath);
return true;
} catch (Exception e) {
LogUtil.e(TAG, "Error downloading deck: " + e.getMessage());
......@@ -598,13 +844,23 @@ public class DeckSquareApiUtil {
}
}
private static boolean uploadLocalDeck(MyDeckItem localDeck, String onlineDeckId, LoginToken loginToken) {
/**
* 将MyDeckItem调用单卡组同步接口推送到服务器
*
* @param localDeck
* @param onlineDeckId
* @param loginToken
* @return
*/
private static boolean uploadLocalDeck(MyDeckItem localDeck, String
onlineDeckId, LoginToken loginToken) {
try {
DeckFile deckFile = new DeckFile(localDeck.getDeckName(), new File(localDeck.getDeckPath()), DeckType.ServerType.MY_SQUARE, localDeck.getDeckId());
DeckFile deckFile = new DeckFile(localDeck.getDeckPath(), DeckType.ServerType.MY_SQUARE);
deckFile.setName(localDeck.getDeckName());
deckFile.setFirstCode(DeckUtil.getFirstCardCode(localDeck.getDeckPath()));
deckFile.setFirstCode(localDeck.getDeckCoverCard1());
// 上传本地卡组,使用在线卡组的deckId
PushDeckResponse response = DeckSquareApiUtil.pushDeck(deckFile, loginToken, onlineDeckId);
PushSingleDeckResponse response = DeckSquareApiUtil.pushDeck(deckFile, loginToken, onlineDeckId);
if (response == null || !response.isData()) {
LogUtil.e(TAG, "Failed to upload deck: " + localDeck.getDeckName());
return false;
......
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