Commit b38428bf authored by wangfugui's avatar wangfugui

卡组自动同步功能api修改

parent 47920094
......@@ -35,7 +35,6 @@ import cn.garymb.ygomobile.deck_square.api_response.SquareDeckResponse;
import cn.garymb.ygomobile.deck_square.api_response.SyncDecksResponse;
import cn.garymb.ygomobile.deck_square.bo.MyDeckItem;
import cn.garymb.ygomobile.deck_square.bo.SyncMutliDeckResult;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.OkhttpUtil;
import cn.garymb.ygomobile.utils.SharedPreferenceUtil;
......@@ -523,10 +522,10 @@ public class DeckSquareApiUtil {
long onlineUpdateDate = convertToUnixTimestamp(onlineDeck.getDeckUpdateDate());//todo 这里应该把2025-05-19T06:11:17转成毫秒,onlineDeck.getDeckUpdateDate();
if (onlineUpdateDate > localUpdateDate){
if (onlineUpdateDate > localUpdateDate) {
// 在线卡组更新时间更晚,下载在线卡组覆盖本地卡组
downloadOnlineDeck(onlineDeck, localDeck.getDeckPath());
} else{
downloadOnlineDeck(onlineDeck, localDeck.getDeckPath(), onlineUpdateDate);
} else {
// 本地卡组更新时间更晚,上传本地卡组覆盖在线卡组
// uploadLocalDeck(localDeck, onlineDeck.getDeckId(), loginToken);
......@@ -545,7 +544,7 @@ public class DeckSquareApiUtil {
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
result.download.add(onlineDeck);
if (!onlineDeckProcessed.get(onlineDeck.getDeckName())) {
SyncMutliDeckResult.DownloadResult downloadResult = downloadMissingDeckToLocal(onlineDeck);
SyncMutliDeckResult.DownloadResult downloadResult = downloadMissingDeckToLocal(onlineDeck, convertToUnixTimestamp(onlineDeck.getDeckUpdateDate()));
result.downloadResponse.add(downloadResult);
}
}
......@@ -554,95 +553,13 @@ public class DeckSquareApiUtil {
}
public static void synchronizeDecks() {
// 检查用户是否登录
LoginToken loginToken = DeckSquareApiUtil.getLoginData();
if (loginToken == null) {
return;
}
// 在后台线程执行网络操作
VUiKit.defer().when(() -> {
try {
// 获取本地卡组列表
List<MyDeckItem> localDecks = DeckSquareFileUtil.getMyDeckItem();
// 获取在线卡组列表
MyDeckResponse onlineDecksResponse = DeckSquareApiUtil.getUserDecks(loginToken);
if (onlineDecksResponse == null || onlineDecksResponse.getData() == null) {
return null;
}
// 创建同步结果对象
SyncResult result = new SyncResult();
result.localDecks = localDecks;
result.onlineDecks = onlineDecksResponse.getData();
return result;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}).done((result) -> {
if (result != null) {
// 在后台线程处理同步逻辑
try {
List<MyDeckItem> localDecks = result.localDecks;
List<MyOnlineDeckDetail> onlineDecks = result.onlineDecks;
// 用于标记在线卡组是否在本地有对应
Map<String, Boolean> onlineDeckProcessed = new HashMap<>();
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
onlineDeckProcessed.put(onlineDeck.getDeckName(), false);
}
// 遍历本地卡组,处理同名卡组的情况
for (MyDeckItem localDeck : localDecks) {
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
if (localDeck.getDeckName().equals(onlineDeck.getDeckName())) {
// 标记该在线卡组已处理
onlineDeckProcessed.put(onlineDeck.getDeckName(), true);
// 比对更新时间
String localUpdateDate = localDeck.getUpdateDate();
String onlineUpdateDate = onlineDeck.getDeckUpdateDate();
if (onlineUpdateDate != null && (localUpdateDate == null || onlineUpdateDate.compareTo(localUpdateDate) > 0)) {
// 在线卡组更新时间更晚,下载在线卡组覆盖本地卡组
downloadOnlineDeck(onlineDeck, localDeck.getDeckPath());
} else {
// 本地卡组更新时间更晚,上传本地卡组覆盖在线卡组
uploadLocalDeck(localDeck, onlineDeck.getDeckId(), loginToken);
}
break;
}
}
}
// 处理只存在于在线的卡组(即本地没有同名卡组)
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
if (!onlineDeckProcessed.get(onlineDeck.getDeckName())) {
downloadMissingDeckToLocal(onlineDeck);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).fail((e) -> {
e.printStackTrace();
// 处理错误,可以在主线程显示错误提示
VUiKit.post(() -> {
// 显示错误提示的代码
});
});
}
// 内部类用于传递同步结果
private static class SyncResult {
List<MyDeckItem> localDecks;
List<MyOnlineDeckDetail> onlineDecks;
}
private static SyncMutliDeckResult.DownloadResult downloadMissingDeckToLocal(MyOnlineDeckDetail onlineDeck) {
private static SyncMutliDeckResult.DownloadResult downloadMissingDeckToLocal(MyOnlineDeckDetail onlineDeck, Long onlineUpdateDate) {
try {
// 根据卡组ID查询在线卡组详情
DownloadDeckResponse deckResponse = DeckSquareApiUtil.getDeckById(onlineDeck.getDeckId());
......@@ -655,7 +572,7 @@ public class DeckSquareApiUtil {
String deckContent = deckDetail.getDeckYdk();
// 构建本地文件路径
String deckDirectory = AppsSettings.get().getResourcePath() + Constants.CORE_DECK_PATH;
String deckDirectory = AppsSettings.get().getDeckDir();
File dir = new File(deckDirectory);
if (!dir.exists()) {
boolean created = dir.mkdirs();
......@@ -674,7 +591,7 @@ public class DeckSquareApiUtil {
String filePath = deckDirectory + "/" + fileName;
// 保存在线卡组到本地
boolean saved = DeckSquareFileUtil.saveFileToPath(filePath, onlineDeck.getDeckName(), deckContent);
boolean saved = DeckSquareFileUtil.saveFileToPath(deckDirectory, fileName, deckResponse.getData().getDeckYdk(), onlineUpdateDate);
if (!saved) {
LogUtil.e(TAG, "Failed to save deck file: " + filePath);
return new SyncMutliDeckResult.DownloadResult(false, onlineDeck.getDeckId(), "Failed to save deck file: " + filePath);
......@@ -698,7 +615,7 @@ public class DeckSquareApiUtil {
}
}
private static boolean downloadOnlineDeck(MyOnlineDeckDetail onlineDeck, String localPath) {
private static boolean downloadOnlineDeck(MyOnlineDeckDetail onlineDeck, String localPath, Long onlineUpdateDate) {
try {
// 根据卡组ID查询在线卡组详情
DownloadDeckResponse deckResponse = DeckSquareApiUtil.getDeckById(onlineDeck.getDeckId());
......@@ -711,7 +628,7 @@ public class DeckSquareApiUtil {
String deckContent = deckDetail.getDeckYdk();
// 保存在线卡组到本地
boolean saved = DeckSquareFileUtil.saveFileToPath(localPath, onlineDeck.getDeckName(), deckContent);
boolean saved = DeckSquareFileUtil.saveFileToPath(localPath, onlineDeck.getDeckName(), deckContent, onlineUpdateDate);
if (!saved) {
LogUtil.e(TAG, "Failed to save deck file: " + localPath);
return false;
......
package cn.garymb.ygomobile.deck_square;
import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
......@@ -89,47 +87,12 @@ public class DeckSquareFileUtil {
return deckId;
}
/**
* 查询卡组目录下的所有ydk文件(包含子文件夹)
* @return 包含所有ydk文件的File数组
*/
//查询卡组目录下的所有ydk文件,返回File[]
public static File[] getAllYdk() {
File dir = new File(AppsSettings.get().getResourcePath(), Constants.CORE_DECK_PATH);
if (!dir.exists() || !dir.isDirectory()) {
return new File[0];
}
// 使用ArrayList存储结果,方便动态添加
ArrayList<File> ydkFiles = new ArrayList<>();
// 递归遍历目录和子目录
findYdkFiles(dir, ydkFiles);
// 将ArrayList转换为File数组
return ydkFiles.toArray(new File[0]);
}
File[] files = dir.listFiles((file, s) -> s.toLowerCase(Locale.US).endsWith(Constants.YDK_FILE_EX));
/**
* 递归查找指定目录下的所有YDK文件
* @param dir 当前查找的目录
* @param ydkFiles 存储找到的YDK文件
*/
private static void findYdkFiles(File dir, ArrayList<File> ydkFiles) {
// 获取目录下的所有文件和子目录
File[] files = dir.listFiles();
if (files == null) {
return; // 目录不可访问或为空
}
for (File file : files) {
if (file.isDirectory()) {
// 如果是子目录,递归查找
findYdkFiles(file, ydkFiles);
} else {
// 如果是文件,检查是否为YDK文件
String fileName = file.getName().toLowerCase(Locale.US);
if (fileName.endsWith(Constants.YDK_FILE_EX)) {
ydkFiles.add(file);
}
}
}
return files;
}
//读取卡组目录下的所有ydk文件,解析ydk文件(包括从ydk文件内容中读取deckId),生成List<MyDeckItem>解析结果
......@@ -207,33 +170,25 @@ 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 saveFileToPath(String path, String fileName, String content) {
FileOutputStream fos = null;
try {
// Create file object
// 创建文件对象
File file = new File(path, fileName);
// Create file output stream
fos = new FileOutputStream(file);
// Write content
// 创建文件输出流
// 写入内容
fos.write(content.getBytes());
fos.flush();
// Update timestamp (works on all Android versions)
if (!file.setLastModified(System.currentTimeMillis())) {
LogUtil.w(TAG, "Timestamp update failed for: " + file);
// 设置指定的最后修改时间
boolean timeSet = file.setLastModified(modificationTime);
if (!timeSet) {
LogUtil.w(TAG, "设置文件修改时间失败: " + file.getPath());
}
} catch (Exception e) {
LogUtil.e(TAG, "保存文件失败", e);
e.printStackTrace();
return false;
} finally {
......
......@@ -8,6 +8,7 @@ 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;
......
......@@ -2,7 +2,6 @@ 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;
......@@ -63,7 +62,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;
......@@ -84,7 +82,6 @@ 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;
......@@ -253,7 +250,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
mContext = (BaseActivity) getActivity();
/** 自动同步 */
if (SharedPreferenceUtil.getServerToken() != null) {
VUiKit.defer().when(DeckSquareApiUtil::synchronizeDecks).fail((e) -> {
VUiKit.defer().when(DeckSquareApiUtil::synchronizeDecksV2).fail((e) -> {
LogUtil.i(TAG, "sync deck fail" + e.getMessage());
}).done((result) -> {
});
......@@ -277,6 +274,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
/**
* 传入外部ydk文件的路径,临时在本页面中打开该ydk的内容,用于后续的保存
*
* @param preLoadFilePath 外部ydk文件的路径
*/
public void preLoadFile(String preLoadFilePath) {
......
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