Commit 62a97201 authored by Dark Zane's avatar Dark Zane Committed by GitHub

Merge branch 'fallenstardust:master' into YGOMOBILE-1

parents 307b6333 c101d738
......@@ -9,8 +9,8 @@ android {
minSdkVersion 25
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 29
versionCode 312000005
versionName "3.12.4"
versionCode 312000006
versionName "3.12.4fix1"
flavorDimensions "versionCode"
vectorDrawables.useSupportLibrary = true
ndkVersion "21.3.6528147"
......
package cn.garymb.ygomobile.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.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;
......@@ -461,7 +468,7 @@ public class DeckSquareApiUtil {
// 遍历本地卡组,处理同名卡组的情况
for (MyDeckItem localDeck : localDecks) {
String localDeckName = localDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
localDeck.setDeckName(localDeckName);//移除.ydk扩展名后需要修改lockDeck记录的卡组名,以防上传时候把.ydk带进去
boolean foundOnlineDeck = false;
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
String onlineDeckName = onlineDeck.getDeckName().replace(Constants.YDK_FILE_EX, "");
......@@ -483,10 +490,10 @@ public class DeckSquareApiUtil {
if (onlineUpdateDate != null && onlineUpdateDate.compareTo(localUpdateDate) > 0) {
// 在线卡组更新时间更晚,下载在线卡组覆盖本地卡组
LogUtil.w("seesee下载", localDeckName+"//"+onlineDeckName);
onlineDeck.setDeckName(onlineDeckName);
downloadOnlineDeck(onlineDeck, localDeck.getDeckPath());
String localPath = localDeck.getDeckPath().replace(localDeckName + Constants.YDK_FILE_EX, "");//直接传入localDeck.getDeckPath()会包含卡组名.ydk,会导致和onlinedeck.getDeckName重复拼接文件路径
downloadOnlineDeck(onlineDeck, localPath, Long.valueOf(onlineDeck.getDeckUpdateDate()));
} else {
LogUtil.w("seesee上传", localDeckName+"//"+onlineDeckName);
LogUtil.w("seesee上传", localDeckName + "//" + onlineDeckName);
// 本地卡组更新时间更晚,上传本地卡组覆盖在线卡组
uploadLocalDeck(localDeck, onlineDeck.getDeckId(), loginToken);
}
......@@ -494,7 +501,7 @@ public class DeckSquareApiUtil {
}
}
// 本地卡组在在线列表中不存在,直接上传
// 本地卡组在在线列表中不存在,则需要获取新的deckid来直接上传
if (!foundOnlineDeck) {
DeckFile deckFile = new DeckFile(localDeckName, new File(localDeck.getDeckPath()), DeckType.ServerType.MY_SQUARE, localDeck.getDeckId());
deckFile.setName(localDeckName);
......@@ -506,14 +513,14 @@ public class DeckSquareApiUtil {
// 处理只存在于在线的卡组(即本地没有同名卡组)
for (MyOnlineDeckDetail onlineDeck : onlineDecks) {
if (!onlineDeckProcessed.get(onlineDeck.getDeckName())) {
downloadMissingDeckToLocal(onlineDeck);
downloadMissingDeckToLocal(onlineDeck, Long.valueOf(onlineDeck.getDeckUploadDate()));
}
}
return true;
}
private static boolean downloadMissingDeckToLocal(MyOnlineDeckDetail onlineDeck) {
private static boolean downloadMissingDeckToLocal(MyOnlineDeckDetail onlineDeck, Long onlineUpdateDate) {
try {
// 根据卡组ID查询在线卡组详情
DownloadDeckResponse deckResponse = DeckSquareApiUtil.getDeckById(onlineDeck.getDeckId());
......@@ -542,7 +549,7 @@ public class DeckSquareApiUtil {
String filePath = deckDirectory + "/" + fileName;
// 保存在线卡组到本地
boolean saved = DeckSquareFileUtil.saveFileToPath(deckDirectory, fileName, deckResponse.getData().getDeckYdk());
boolean saved = DeckSquareFileUtil.saveFileToPath(deckDirectory, fileName, deckResponse.getData().getDeckYdk(), onlineUpdateDate);
if (!saved) {
LogUtil.e(TAG, "downloadMissingDeckToLocal-Failed to save deck file: " + filePath);
return false;
......@@ -566,7 +573,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());
......@@ -577,13 +584,14 @@ public class DeckSquareApiUtil {
// 保存在线卡组到本地
boolean saved = DeckSquareFileUtil.saveFileToPath(localPath, onlineDeck.getDeckName(), deckResponse.getData().getDeckYdk());
String fileName = onlineDeck.getDeckName() + Constants.YDK_FILE_EX;
boolean saved = DeckSquareFileUtil.saveFileToPath(localPath, fileName, deckResponse.getData().getDeckYdk(), onlineUpdateDate);
if (!saved) {
LogUtil.e(TAG, "downloadOnlineDeck-Failed to save deck file: " + localPath);
LogUtil.e(TAG, "downloadOnlineDeck-Failed to save deck file: " + fileName);
return false;
}
LogUtil.i(TAG, "Deck updated: " + localPath);
LogUtil.i(TAG, "Deck updated: " + fileName);
return true;
} catch (Exception e) {
LogUtil.e(TAG, "Error downloading deck: " + e.getMessage());
......
package cn.garymb.ygomobile.deck_square;
import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
......@@ -82,12 +84,47 @@ public class DeckSquareFileUtil {
return deckId;
}
//查询卡组目录下的所有ydk文件,返回File[]
/**
* 查询卡组目录下的所有ydk文件(包含子文件夹)
* @return 包含所有ydk文件的File数组
*/
public static File[] getAllYdk() {
File dir = new File(AppsSettings.get().getResourcePath(), Constants.CORE_DECK_PATH);
File[] files = dir.listFiles((file, s) -> s.toLowerCase(Locale.US).endsWith(Constants.YDK_FILE_EX));
if (!dir.exists() || !dir.isDirectory()) {
return new File[0];
}
// 使用ArrayList存储结果,方便动态添加
ArrayList<File> ydkFiles = new ArrayList<>();
// 递归遍历目录和子目录
findYdkFiles(dir, ydkFiles);
// 将ArrayList转换为File数组
return ydkFiles.toArray(new File[0]);
}
/**
* 递归查找指定目录下的所有YDK文件
* @param dir 当前查找的目录
* @param ydkFiles 存储找到的YDK文件
*/
private static void findYdkFiles(File dir, ArrayList<File> ydkFiles) {
// 获取目录下的所有文件和子目录
File[] files = dir.listFiles();
if (files == null) {
return; // 目录不可访问或为空
}
return files;
for (File file : files) {
if (file.isDirectory()) {
// 如果是子目录,递归查找
findYdkFiles(file, ydkFiles);
} else {
// 如果是文件,检查是否为YDK文件
String fileName = file.getName().toLowerCase(Locale.US);
if (fileName.endsWith(Constants.YDK_FILE_EX)) {
ydkFiles.add(file);
}
}
}
}
//读取卡组目录下的所有ydk文件,解析ydk文件(包括从ydk文件内容中读取deckId),生成List<MyDeckItem>解析结果
......@@ -98,9 +135,6 @@ public class DeckSquareFileUtil {
String deckId = getId(file);
MyDeckItem item = new MyDeckItem();
item.deckName = file.getName();
item.setUpdateDate(String.valueOf(file.lastModified()));
item.setDeckSouce(0);
item.setDeckPath(file.getPath());
......@@ -167,23 +201,37 @@ public class DeckSquareFileUtil {
return content;
}
public static boolean saveFileToPath(String path, String fileName, String content) {
/**
* 保存文件到指定路径,并设置指定的最后修改时间
* @param path 保存路径
* @param fileName 文件名
* @param content 文件内容
* @param modificationTime 期望的最后修改时间(毫秒时间戳)
* @return 保存是否成功
*/
public static boolean saveFileToPath(String path, String fileName, String content, long modificationTime) {
try {
// Create file object
// 创建文件对象
File file = new File(path, fileName);
// Create file output stream
FileOutputStream fos = new FileOutputStream(file);
// 创建文件输出流
try (FileOutputStream fos = new FileOutputStream(file)) {
// 写入内容
fos.write(content.getBytes());
fos.flush();
}
// 设置指定的最后修改时间
boolean timeSet = file.setLastModified(modificationTime);
if (!timeSet) {
LogUtil.w(TAG, "设置文件修改时间失败: " + file.getPath());
}
// Write content
fos.write(content.getBytes());
fos.flush();
fos.close();
return true;
} catch (IOException e) {
e.printStackTrace();
LogUtil.e(TAG, "保存文件失败", e);
return false;
}
return true;
}
......
......@@ -12,8 +12,12 @@ import android.widget.TextView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import cn.garymb.ygomobile.bean.Deck;
import cn.garymb.ygomobile.bean.DeckInfo;
......@@ -70,6 +74,15 @@ public class DeckListAdapter<T extends TextSelect> extends BaseQuickAdapter<T, D
mContext = context;
}
/**
* 将时间戳转换为 ISO 8601 格式的时间字符串
*/
@SuppressLint("SimpleDateFormat")
public static String convertMillisToIsoString(long timeMillis) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.CHINA);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf.format(new Date(timeMillis));
}
@SuppressLint("ResourceType")
@Override
......@@ -109,6 +122,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 (deckFile.getTypeName().equals(YGOUtil.s(R.string.category_pack)) || deckFile.getPath().contains("cacheDeck")) {
//卡包展示时不显示额外和副卡组数量文本
holder.ll_extra_n_side.setVisibility(View.GONE);
......@@ -245,6 +259,7 @@ class DeckViewHolder extends com.chad.library.adapter.base.viewholder.BaseViewHo
TextView main;
TextView extra;
TextView side;
TextView file_time;
LinearLayout ll_extra_n_side;
View item_deck_list;
View deck_info;
......@@ -259,6 +274,7 @@ 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);
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);
banned_mark = findView(R.id.banned_mark);
......
......@@ -1353,7 +1353,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
String fileFullName = deckData.getDeckName() + ".ydk";
File dir = new File(getActivity().getApplicationInfo().dataDir, "cache");
//将卡组存到cache缓存目录中
boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk());
boolean result = DeckSquareFileUtil.saveFileToPath(dir.getPath(), fileFullName, deckData.getDeckYdk(), Long.valueOf(deckData.getDeckUpdateDate()));
if (result) {//存储成功,使用预加载功能
LogUtil.i(TAG, "square deck detail done");
//File file = new File(dir, fileFullName);
......
......@@ -145,7 +145,7 @@ public class PackManager implements Closeable {
public List<Integer> getAllIdsById(Integer id) {
String packName = findPackNameById(id);
if (packName == null) {
Log.w("seesee", "No pack found for ID: " + id);
Log.w(TAG, "No pack found for ID: " + id);
return new ArrayList<>();
}
return findIdsByPackName(packName);
......
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#91BF03" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M10,8l0,6l4.7,2.9l0.8,-1.2l-4,-2.4l0,-5.3z"/>
<path android:fillColor="@android:color/white" android:pathData="M17.92,12c0.05,0.33 0.08,0.66 0.08,1c0,3.9 -3.1,7 -7,7s-7,-3.1 -7,-7c0,-3.9 3.1,-7 7,-7c0.7,0 1.37,0.1 2,0.29V4.23C12.36,4.08 11.69,4 11,4c-5,0 -9,4 -9,9s4,9 9,9s9,-4 9,-9c0,-0.34 -0.02,-0.67 -0.06,-1H17.92z"/>
<path android:fillColor="@android:color/white" android:pathData="M20,5l0,-3l-2,0l0,3l-3,0l0,2l3,0l0,3l2,0l0,-3l3,0l0,-2z"/>
</vector>
......@@ -132,6 +132,23 @@
android:textColor="@color/holo_blue_bright"
android:textSize="10sp"
tools:text="15" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:src="@drawable/baseline_more_time_24"/>
<TextView
android:id="@+id/file_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/holo_blue_bright"
android:textSize="7sp"
tools:text="2025-07-03T19:47:26" />
</LinearLayout>
</LinearLayout>
......
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