功能添加
This commit is contained in:
parent
27727eaff0
commit
73e2478168
@ -9,7 +9,6 @@ import com.auto.clicker.autoclicker.room.entity.Solution;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
// 这个 POJO 用于表示一个方案,以及该方案下的所有事件及其关联的坐标点
|
|
||||||
public class SolutionWithEventsAndPoints {
|
public class SolutionWithEventsAndPoints {
|
||||||
@Embedded
|
@Embedded
|
||||||
public Solution solution;
|
public Solution solution;
|
||||||
@ -19,9 +18,8 @@ public class SolutionWithEventsAndPoints {
|
|||||||
entityColumn = "solution_id",
|
entityColumn = "solution_id",
|
||||||
entity = EventEntity.class
|
entity = EventEntity.class
|
||||||
)
|
)
|
||||||
public List<EventWithPoints> events; // 注意这里我们用 EventWithPoints
|
public List<EventWithPoints> events;
|
||||||
|
|
||||||
// 内部类,用于表示一个事件以及它关联的起点和终点
|
|
||||||
public static class EventWithPoints {
|
public static class EventWithPoints {
|
||||||
@Embedded
|
@Embedded
|
||||||
public EventEntity eventEntity;
|
public EventEntity eventEntity;
|
||||||
@ -31,20 +29,20 @@ public class SolutionWithEventsAndPoints {
|
|||||||
entityColumn = "pointId",
|
entityColumn = "pointId",
|
||||||
entity = TouchPoint.class
|
entity = TouchPoint.class
|
||||||
)
|
)
|
||||||
public TouchPoint clickTouchPoint; // 单击事件的点
|
public TouchPoint clickTouchPoint;
|
||||||
|
|
||||||
@Relation(
|
@Relation(
|
||||||
parentColumn = "slide_start_point_id",
|
parentColumn = "slide_start_point_id",
|
||||||
entityColumn = "pointId",
|
entityColumn = "pointId",
|
||||||
entity = TouchPoint.class
|
entity = TouchPoint.class
|
||||||
)
|
)
|
||||||
public TouchPoint slideStartTouchPoint; // 滑动事件的起点
|
public TouchPoint slideStartTouchPoint;
|
||||||
|
|
||||||
@Relation(
|
@Relation(
|
||||||
parentColumn = "slide_end_point_id",
|
parentColumn = "slide_end_point_id",
|
||||||
entityColumn = "pointId",
|
entityColumn = "pointId",
|
||||||
entity = TouchPoint.class
|
entity = TouchPoint.class
|
||||||
)
|
)
|
||||||
public TouchPoint slideEndTouchPoint; // 滑动事件的终点
|
public TouchPoint slideEndTouchPoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import java.util.List;
|
|||||||
@Dao
|
@Dao
|
||||||
public interface SolutionDao {
|
public interface SolutionDao {
|
||||||
@Insert
|
@Insert
|
||||||
long insertSolution(Solution solution); // 返回新插入的 solutionId
|
long insertSolution(Solution solution);
|
||||||
|
|
||||||
@Query("SELECT * FROM solutions")
|
@Query("SELECT * FROM solutions")
|
||||||
List<Solution> getAllSolutions();
|
List<Solution> getAllSolutions();
|
||||||
@ -27,18 +27,22 @@ public interface SolutionDao {
|
|||||||
Solution getSolutionByName(String solutionName);
|
Solution getSolutionByName(String solutionName);
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
int deleteSolution(Solution solution); // 返回删除的行数
|
int deleteSolution(Solution solution);
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
int updateSolution(Solution solution); // 返回更新的行数
|
int updateSolution(Solution solution);
|
||||||
|
|
||||||
// 在 SolutionDao 中添加
|
@Transaction
|
||||||
@Transaction // 表示这是一个事务操作,确保数据一致性
|
|
||||||
@Query("SELECT * FROM solutions WHERE solutionId = :solutionId LIMIT 1")
|
@Query("SELECT * FROM solutions WHERE solutionId = :solutionId LIMIT 1")
|
||||||
SolutionWithEventsAndPoints getSolutionWithEventsAndPoints(long solutionId);
|
SolutionWithEventsAndPoints getSolutionWithEventsAndPoints(long solutionId);
|
||||||
|
|
||||||
// 也可以获取所有方案及其事件
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM solutions")
|
@Query("SELECT * FROM solutions")
|
||||||
List<SolutionWithEventsAndPoints> getAllSolutionsWithEventsAndPoints();
|
List<SolutionWithEventsAndPoints> getAllSolutionsWithEventsAndPoints();
|
||||||
|
|
||||||
|
@Query("UPDATE solutions SET solution_name = :newName WHERE solutionId = :solutionId")
|
||||||
|
int updateSolutionName(long solutionId, String newName);
|
||||||
|
|
||||||
|
@Query("DELETE FROM solutions WHERE solutionId = :solutionId")
|
||||||
|
void deleteSolutionById(long solutionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import androidx.room.Entity;
|
|||||||
import androidx.room.ForeignKey;
|
import androidx.room.ForeignKey;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
@Entity(tableName = "events",
|
@Entity(tableName = "events",
|
||||||
foreignKeys = {
|
foreignKeys = {
|
||||||
@ForeignKey(entity = Solution.class,
|
@ForeignKey(entity = Solution.class,
|
||||||
@ -27,27 +29,35 @@ import androidx.room.PrimaryKey;
|
|||||||
onDelete = CASCADE)
|
onDelete = CASCADE)
|
||||||
})
|
})
|
||||||
public class EventEntity {
|
public class EventEntity {
|
||||||
|
@Expose
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
public long eventId;
|
public long eventId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "solution_id")
|
@ColumnInfo(name = "solution_id")
|
||||||
public long solutionId;
|
public long solutionId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "event_type")
|
@ColumnInfo(name = "event_type")
|
||||||
public String eventType;
|
public String eventType;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "order_in_solution")
|
@ColumnInfo(name = "order_in_solution")
|
||||||
public int orderInSolution;
|
public int orderInSolution;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "click_point_id")
|
@ColumnInfo(name = "click_point_id")
|
||||||
public Long clickPointId;
|
public Long clickPointId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "slide_start_point_id")
|
@ColumnInfo(name = "slide_start_point_id")
|
||||||
public Long slideStartPointId;
|
public Long slideStartPointId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "slide_end_point_id")
|
@ColumnInfo(name = "slide_end_point_id")
|
||||||
public Long slideEndPointId;
|
public Long slideEndPointId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "duration")
|
@ColumnInfo(name = "duration")
|
||||||
public long duration;
|
public long duration;
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,20 @@ import androidx.room.ColumnInfo;
|
|||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
@Entity(tableName = "solutions")
|
@Entity(tableName = "solutions")
|
||||||
public class Solution {
|
public class Solution {
|
||||||
|
|
||||||
|
@Expose
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
public long solutionId;
|
public long solutionId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "solution_name")
|
@ColumnInfo(name = "solution_name")
|
||||||
public String solutionName;
|
public String solutionName;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "mode")
|
@ColumnInfo(name = "mode")
|
||||||
public int mode;
|
public int mode;
|
||||||
|
|
||||||
|
|||||||
@ -4,16 +4,21 @@ import androidx.room.ColumnInfo;
|
|||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
|
|
||||||
@Entity(tableName = "touchPoints")
|
@Entity(tableName = "touchPoints")
|
||||||
public class TouchPoint {
|
public class TouchPoint {
|
||||||
|
|
||||||
|
@Expose
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
public long pointId;
|
public long pointId;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "x_coordinate")
|
@ColumnInfo(name = "x_coordinate")
|
||||||
public int x;
|
public int x;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(name = "y_coordinate")
|
@ColumnInfo(name = "y_coordinate")
|
||||||
public int y;
|
public int y;
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package com.auto.clicker.autoclicker.room.repository;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.room.Transaction;
|
||||||
|
|
||||||
import com.auto.clicker.autoclicker.data.Event;
|
import com.auto.clicker.autoclicker.data.Event;
|
||||||
import com.auto.clicker.autoclicker.data.EventWrapper;
|
import com.auto.clicker.autoclicker.data.EventWrapper;
|
||||||
import com.auto.clicker.autoclicker.data.PointEvent;
|
import com.auto.clicker.autoclicker.data.PointEvent;
|
||||||
@ -15,6 +17,8 @@ import com.auto.clicker.autoclicker.room.dao.TouchPointDao;
|
|||||||
import com.auto.clicker.autoclicker.room.entity.EventEntity;
|
import com.auto.clicker.autoclicker.room.entity.EventEntity;
|
||||||
import com.auto.clicker.autoclicker.room.entity.Solution;
|
import com.auto.clicker.autoclicker.room.entity.Solution;
|
||||||
import com.auto.clicker.autoclicker.room.entity.TouchPoint;
|
import com.auto.clicker.autoclicker.room.entity.TouchPoint;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -27,30 +31,27 @@ public class EventRepository {
|
|||||||
private final ExecutorService databaseWriteExecutor;
|
private final ExecutorService databaseWriteExecutor;
|
||||||
|
|
||||||
public EventRepository(Context context) {
|
public EventRepository(Context context) {
|
||||||
AppDatabase db = AppDatabase.getInstance(context); // Updated to getInstance
|
AppDatabase db = AppDatabase.getInstance(context);
|
||||||
this.solutionDao = db.solutionDao();
|
this.solutionDao = db.solutionDao();
|
||||||
this.touchPointDao = db.pointDao();
|
this.touchPointDao = db.pointDao();
|
||||||
this.eventEntityDao = db.eventEntityDao();
|
this.eventEntityDao = db.eventEntityDao();
|
||||||
this.databaseWriteExecutor = Executors.newFixedThreadPool(2);
|
this.databaseWriteExecutor = Executors.newFixedThreadPool(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 插入操作 ---
|
|
||||||
public void insertSolutionWithEvents(Solution solution, List<EventWrapper> runtimeEvents, RepositoryCallback<Long> callback) {
|
public void insertSolutionWithEvents(Solution solution, List<EventWrapper> runtimeEvents, RepositoryCallback<Long> callback) {
|
||||||
databaseWriteExecutor.execute(() -> {
|
databaseWriteExecutor.execute(() -> {
|
||||||
long solutionId = -1; // Initialize solutionId outside try-catch for broader scope
|
long solutionId = -1;
|
||||||
try {
|
try {
|
||||||
// 1. 插入 Solution
|
|
||||||
solutionId = solutionDao.insertSolution(solution);
|
solutionId = solutionDao.insertSolution(solution);
|
||||||
if (solutionId == -1) {
|
if (solutionId == -1) {
|
||||||
throw new RuntimeException("Failed to insert solution.");
|
throw new RuntimeException("Failed to insert solution.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 遍历 runtimeEvents,插入 TouchPoint 和 EventEntity
|
|
||||||
for (EventWrapper wrapper : runtimeEvents) {
|
for (EventWrapper wrapper : runtimeEvents) {
|
||||||
Event event = wrapper.getEvent();
|
Event event = wrapper.getEvent();
|
||||||
int order = wrapper.getOrder(); // Using order from EventWrapper
|
int order = wrapper.getOrder();
|
||||||
|
|
||||||
long eventEntityId = -1; // To store the result of event entity insertion
|
long eventEntityId;
|
||||||
|
|
||||||
if (wrapper.getType() == EventWrapper.EventType.POINT && event instanceof PointEvent) {
|
if (wrapper.getType() == EventWrapper.EventType.POINT && event instanceof PointEvent) {
|
||||||
PointEvent pointEvent = (PointEvent) event;
|
PointEvent pointEvent = (PointEvent) event;
|
||||||
@ -59,15 +60,14 @@ public class EventRepository {
|
|||||||
if (pointId == -1)
|
if (pointId == -1)
|
||||||
throw new RuntimeException("Failed to insert touch point for PointEvent.");
|
throw new RuntimeException("Failed to insert touch point for PointEvent.");
|
||||||
|
|
||||||
// 调用 EventEntity 的唯一构造函数,将滑动相关字段设为 null 或默认值
|
|
||||||
EventEntity eventEntity = new EventEntity(
|
EventEntity eventEntity = new EventEntity(
|
||||||
(int) solutionId, // Ensure type compatibility if solutionId is long
|
solutionId, // 使用 long 类型的 solutionId
|
||||||
wrapper.getType().name(),
|
wrapper.getType().name(),
|
||||||
order,
|
order,
|
||||||
pointId, // clickPointId
|
pointId,
|
||||||
null, // slideStartPointId (null for point event)
|
null,
|
||||||
null, // slideEndPointId (null for point event)
|
null,
|
||||||
0 // duration (0 for point event)
|
0
|
||||||
);
|
);
|
||||||
eventEntityId = eventEntityDao.insertEventEntity(eventEntity);
|
eventEntityId = eventEntityDao.insertEventEntity(eventEntity);
|
||||||
if (eventEntityId == -1)
|
if (eventEntityId == -1)
|
||||||
@ -85,15 +85,14 @@ public class EventRepository {
|
|||||||
if (endPointId == -1)
|
if (endPointId == -1)
|
||||||
throw new RuntimeException("Failed to insert end touch point for SlideEvent.");
|
throw new RuntimeException("Failed to insert end touch point for SlideEvent.");
|
||||||
|
|
||||||
// 调用 EventEntity 的唯一构造函数,将点击相关字段设为 null
|
|
||||||
EventEntity eventEntity = new EventEntity(
|
EventEntity eventEntity = new EventEntity(
|
||||||
(int) solutionId,
|
solutionId, // 使用 long 类型的 solutionId
|
||||||
wrapper.getType().name(),
|
wrapper.getType().name(),
|
||||||
order,
|
order,
|
||||||
null,
|
null,
|
||||||
startPointId,
|
startPointId,
|
||||||
endPointId,
|
endPointId,
|
||||||
0
|
0 // duration for slide events, you might want to get this from SlideEvent
|
||||||
);
|
);
|
||||||
eventEntityId = eventEntityDao.insertEventEntity(eventEntity);
|
eventEntityId = eventEntityDao.insertEventEntity(eventEntity);
|
||||||
if (eventEntityId == -1)
|
if (eventEntityId == -1)
|
||||||
@ -101,13 +100,10 @@ public class EventRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
// Post the result back to the main thread if needed for UI updates
|
|
||||||
// For simplicity, directly calling callback here; in a real app, use Handler or LiveData
|
|
||||||
callback.onComplete(solutionId);
|
callback.onComplete(solutionId);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("EventRepository", "Error inserting solution with events: " + e.getMessage(), e);
|
Log.e("EventRepository", "Error inserting solution with events: " + e.getMessage(), e);
|
||||||
// Consider rolling back the transaction if any part fails
|
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onError(e);
|
callback.onError(e);
|
||||||
}
|
}
|
||||||
@ -115,7 +111,6 @@ public class EventRepository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 查询操作 ---
|
|
||||||
public void getAllSolutions(RepositoryCallback<List<Solution>> callback) {
|
public void getAllSolutions(RepositoryCallback<List<Solution>> callback) {
|
||||||
databaseWriteExecutor.execute(() -> {
|
databaseWriteExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
@ -128,6 +123,35 @@ public class EventRepository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateSolutionName(long solutionId, String newName, RepositoryCallback<Void> callback) {
|
||||||
|
databaseWriteExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
int updatedRows = solutionDao.updateSolutionName(solutionId, newName);
|
||||||
|
if (updatedRows > 0) {
|
||||||
|
if (callback != null) callback.onComplete(null);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Failed to update solution name, solution not found.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("EventRepository", "Error updating solution name: " + e.getMessage(), e);
|
||||||
|
if (callback != null) callback.onError(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
public void deleteSolution(long solutionId, RepositoryCallback<Void> callback) {
|
||||||
|
databaseWriteExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
solutionDao.deleteSolutionById(solutionId);
|
||||||
|
if (callback != null) callback.onComplete(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("EventRepository", "Error deleting solution: " + e.getMessage(), e);
|
||||||
|
if (callback != null) callback.onError(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void getSolutionWithEventsAndPoints(long solutionId, RepositoryCallback<SolutionWithEventsAndPoints> callback) {
|
public void getSolutionWithEventsAndPoints(long solutionId, RepositoryCallback<SolutionWithEventsAndPoints> callback) {
|
||||||
databaseWriteExecutor.execute(() -> {
|
databaseWriteExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
@ -140,34 +164,69 @@ public class EventRepository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void deleteSolution(Solution solution, RepositoryCallback<Integer> callback) {
|
@Transaction
|
||||||
// databaseWriteExecutor.execute(() -> {
|
public void saveDuplicateSolution(SolutionWithEventsAndPoints originalData, RepositoryCallback<Void> callback) {
|
||||||
// try {
|
databaseWriteExecutor.execute(() -> {
|
||||||
// int rowsAffected = solutionDao.deleteSolution(solution);
|
try {
|
||||||
// if (callback != null) callback.onComplete(rowsAffected);
|
// 创建新的 Solution 实例
|
||||||
// } catch (Exception e) {
|
Solution newSolution = new Solution(originalData.solution.solutionName + " (1)", originalData.solution.mode);
|
||||||
// Log.e("EventRepository", "Error deleting solution: " + e.getMessage(), e);
|
long newSolutionId = solutionDao.insertSolution(newSolution);
|
||||||
// if (callback != null) callback.onError(e);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void updateSolutionName(long solutionId, String newName, RepositoryCallback<Void> callback) {
|
|
||||||
|
|
||||||
|
if (newSolutionId == -1) {
|
||||||
|
throw new RuntimeException("Failed to duplicate solution: Could not insert new Solution.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteSolution(long solutionId, RepositoryCallback<Void> callback) {
|
for (SolutionWithEventsAndPoints.EventWithPoints eventWithPoints : originalData.events) {
|
||||||
|
Long newClickPointId = null;
|
||||||
|
if (eventWithPoints.clickTouchPoint != null) {
|
||||||
|
TouchPoint newClickPoint = new TouchPoint(eventWithPoints.clickTouchPoint.x, eventWithPoints.clickTouchPoint.y);
|
||||||
|
newClickPointId = touchPointDao.insertPoint(newClickPoint);
|
||||||
|
if (newClickPointId == -1)
|
||||||
|
throw new RuntimeException("Failed to duplicate click point.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用于复制方案,需要保存一个新的方案以及其关联的事件和点
|
Long newSlideStartPointId = null;
|
||||||
public void saveSolutionWithEventsAndPoints(Solution solution, List<SolutionWithEventsAndPoints.EventWithPoints> eventsWithPoints, RepositoryCallback<Void> callback) {
|
if (eventWithPoints.slideStartTouchPoint != null) {
|
||||||
|
TouchPoint newSlideStartPoint = new TouchPoint(eventWithPoints.slideStartTouchPoint.x, eventWithPoints.slideStartTouchPoint.y);
|
||||||
|
newSlideStartPointId = touchPointDao.insertPoint(newSlideStartPoint);
|
||||||
|
if (newSlideStartPointId == -1)
|
||||||
|
throw new RuntimeException("Failed to duplicate slide start point.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取某个方案及其所有事件和点的数据
|
Long newSlideEndPointId = null;
|
||||||
public void getSolutionWithEventsAndPoints(String solutionId, RepositoryCallback<SolutionWithEventsAndPoints> callback) {
|
if (eventWithPoints.slideEndTouchPoint != null) {
|
||||||
|
TouchPoint newSlideEndPoint = new TouchPoint(eventWithPoints.slideEndTouchPoint.x, eventWithPoints.slideEndTouchPoint.y);
|
||||||
|
newSlideEndPointId = touchPointDao.insertPoint(newSlideEndPoint);
|
||||||
|
if (newSlideEndPointId == -1)
|
||||||
|
throw new RuntimeException("Failed to duplicate slide end point.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新的 EventEntity 实例
|
||||||
|
EventEntity newEventEntity = new EventEntity(
|
||||||
|
newSolutionId,
|
||||||
|
eventWithPoints.eventEntity.eventType,
|
||||||
|
eventWithPoints.eventEntity.orderInSolution,
|
||||||
|
newClickPointId,
|
||||||
|
newSlideStartPointId,
|
||||||
|
newSlideEndPointId,
|
||||||
|
eventWithPoints.eventEntity.duration
|
||||||
|
);
|
||||||
|
long newEventEntityId = eventEntityDao.insertEventEntity(newEventEntity);
|
||||||
|
if (newEventEntityId == -1) {
|
||||||
|
throw new RuntimeException("Failed to duplicate event entity.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (callback != null) callback.onComplete(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("EventRepository", "Error duplicating solution: " + e.getMessage(), e);
|
||||||
|
if (callback != null) callback.onError(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String exportSolutionToJson(SolutionWithEventsAndPoints data) {
|
||||||
|
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
|
||||||
|
return gson.toJson(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface RepositoryCallback<T> {
|
public interface RepositoryCallback<T> {
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.auto.clicker.autoclicker.ui.activity.menu;
|
package com.auto.clicker.autoclicker.ui.activity.menu;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -12,6 +11,8 @@ import android.widget.EditText;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
@ -21,28 +22,24 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||||||
import com.auto.clicker.autoclicker.R;
|
import com.auto.clicker.autoclicker.R;
|
||||||
import com.auto.clicker.autoclicker.databinding.ActivityScriptsBinding;
|
import com.auto.clicker.autoclicker.databinding.ActivityScriptsBinding;
|
||||||
import com.auto.clicker.autoclicker.room.SolutionWithEventsAndPoints;
|
import com.auto.clicker.autoclicker.room.SolutionWithEventsAndPoints;
|
||||||
import com.auto.clicker.autoclicker.room.entity.EventEntity;
|
|
||||||
import com.auto.clicker.autoclicker.room.entity.Solution;
|
import com.auto.clicker.autoclicker.room.entity.Solution;
|
||||||
import com.auto.clicker.autoclicker.room.entity.TouchPoint;
|
|
||||||
import com.auto.clicker.autoclicker.room.repository.EventRepository;
|
import com.auto.clicker.autoclicker.room.repository.EventRepository;
|
||||||
import com.auto.clicker.autoclicker.ui.adapter.floating.SolutionAdapter;
|
import com.auto.clicker.autoclicker.ui.adapter.floating.SolutionAdapter;
|
||||||
import com.auto.clicker.autoclicker.ui.dialog.CreateModeSelectionDialog;
|
import com.auto.clicker.autoclicker.ui.dialog.CreateModeSelectionDialog;
|
||||||
import com.auto.clicker.autoclicker.view.FloatingViewManager;
|
import com.auto.clicker.autoclicker.view.FloatingViewManager;
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class ScriptsActivity extends AppCompatActivity implements SolutionAdapter.OnOptionMenuClickListener {
|
public class ScriptsActivity extends AppCompatActivity implements SolutionAdapter.OnOptionMenuClickListener {
|
||||||
private ActivityScriptsBinding binding;
|
private ActivityScriptsBinding binding;
|
||||||
private SolutionAdapter solutionsAdapter;
|
private SolutionAdapter solutionsAdapter;
|
||||||
private FloatingViewManager floatingViewManager;
|
private FloatingViewManager floatingViewManager;
|
||||||
|
private String tempExportJson;
|
||||||
|
|
||||||
private static final String TAG = "ScriptsActivity";
|
private static final String TAG = "ScriptsActivity";
|
||||||
private static final int CREATE_FILE_REQUEST_CODE = 1; // 用于导出文件的请求码
|
private static final int CREATE_FILE_REQUEST_CODE = 1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -57,11 +54,12 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
});
|
});
|
||||||
|
|
||||||
binding.scriptsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
binding.scriptsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
// 传入 this 作为 OnOptionMenuClickListener 的实现
|
// 将 this 作为 OnSolutionClickListener 和 OnOptionMenuClickListener 传入
|
||||||
solutionsAdapter = new SolutionAdapter(new ArrayList<>(), this::onSolutionSelected, this);
|
solutionsAdapter = new SolutionAdapter(new ArrayList<>(), this::onSolutionSelected, this);
|
||||||
binding.scriptsRecyclerView.setAdapter(solutionsAdapter);
|
binding.scriptsRecyclerView.setAdapter(solutionsAdapter);
|
||||||
|
|
||||||
floatingViewManager = new FloatingViewManager(this);
|
// 确保 FloatingViewManager 在 Activity 创建时被初始化
|
||||||
|
floatingViewManager = new FloatingViewManager(this); // 如果 FloatingViewManager 依赖 Context,这里需要传递
|
||||||
|
|
||||||
binding.btnBack.setOnClickListener(v -> finish());
|
binding.btnBack.setOnClickListener(v -> finish());
|
||||||
|
|
||||||
@ -97,7 +95,9 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
floatingViewManager.getAllSolutions(new EventRepository.RepositoryCallback<List<Solution>>() {
|
// 确保 FloatingViewManager 能够提供 EventRepository 实例
|
||||||
|
// 假设 FloatingViewManager 内部管理着 EventRepository
|
||||||
|
floatingViewManager.getEventRepository().getAllSolutions(new EventRepository.RepositoryCallback<List<Solution>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(List<Solution> solutions) {
|
public void onComplete(List<Solution> solutions) {
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
@ -116,7 +116,7 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
Log.e(TAG, "加载方案列表失败: " + e.getMessage(), e);
|
Log.e(TAG, "加载方案列表失败: " + e.getMessage(), e);
|
||||||
Toast.makeText(ScriptsActivity.this, "加载方案列表失败。", Toast.LENGTH_SHORT).show();
|
Toast.makeText(ScriptsActivity.this, "加载方案列表失败。", Toast.LENGTH_SHORT).show();
|
||||||
updateLayout(true); // 加载失败也显示无方案视图
|
updateLayout(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -145,29 +145,23 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 实现 SolutionAdapter.OnOptionMenuClickListener 接口的方法 ---
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRenameClick(Solution solution) {
|
public void onRenameClick(Solution solution) {
|
||||||
// 实现重命名逻辑
|
|
||||||
showRenameDialog(solution);
|
showRenameDialog(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDuplicateClick(Solution solution) {
|
public void onDuplicateClick(Solution solution) {
|
||||||
// 实现复制逻辑
|
|
||||||
duplicateSolution(solution);
|
duplicateSolution(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeleteClick(Solution solution) {
|
public void onDeleteClick(Solution solution) {
|
||||||
// 实现删除逻辑
|
|
||||||
showDeleteConfirmationDialog(solution);
|
showDeleteConfirmationDialog(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onExportClick(Solution solution) {
|
public void onExportClick(Solution solution) {
|
||||||
// 实现导出逻辑
|
|
||||||
exportSolution(solution);
|
exportSolution(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +176,6 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
builder.setPositiveButton("确定", (dialog, which) -> {
|
builder.setPositiveButton("确定", (dialog, which) -> {
|
||||||
String newName = input.getText().toString().trim();
|
String newName = input.getText().toString().trim();
|
||||||
if (!newName.isEmpty() && !newName.equals(solution.getSolutionName())) {
|
if (!newName.isEmpty() && !newName.equals(solution.getSolutionName())) {
|
||||||
// 调用 EventRepository 更新方案名称
|
|
||||||
floatingViewManager.getEventRepository().updateSolutionName(solution.getSolutionId(), newName, new EventRepository.RepositoryCallback<Void>() {
|
floatingViewManager.getEventRepository().updateSolutionName(solution.getSolutionId(), newName, new EventRepository.RepositoryCallback<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(Void result) {
|
public void onComplete(Void result) {
|
||||||
@ -202,6 +195,8 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
});
|
});
|
||||||
} else if (newName.isEmpty()) {
|
} else if (newName.isEmpty()) {
|
||||||
Toast.makeText(ScriptsActivity.this, "方案名称不能为空。", Toast.LENGTH_SHORT).show();
|
Toast.makeText(ScriptsActivity.this, "方案名称不能为空。", Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(ScriptsActivity.this, "新名称与原名称相同。", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setNegativeButton("取消", (dialog, which) -> dialog.cancel());
|
builder.setNegativeButton("取消", (dialog, which) -> dialog.cancel());
|
||||||
@ -212,60 +207,12 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
floatingViewManager.getEventRepository().getSolutionWithEventsAndPoints(originalSolution.getSolutionId(), new EventRepository.RepositoryCallback<SolutionWithEventsAndPoints>() {
|
floatingViewManager.getEventRepository().getSolutionWithEventsAndPoints(originalSolution.getSolutionId(), new EventRepository.RepositoryCallback<SolutionWithEventsAndPoints>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(SolutionWithEventsAndPoints originalData) {
|
public void onComplete(SolutionWithEventsAndPoints originalData) {
|
||||||
if (originalData != null && originalData.solution != null) {
|
if (originalData != null) {
|
||||||
// 创建新的 Solution 对象
|
floatingViewManager.getEventRepository().saveDuplicateSolution(originalData, new EventRepository.RepositoryCallback<Void>() {
|
||||||
Solution newSolution = new Solution();
|
|
||||||
newSolution.setSolutionId(UUID.randomUUID().toString()); // 生成新的ID
|
|
||||||
newSolution.setSolutionName(originalSolution.getSolutionName() + " (1)");
|
|
||||||
newSolution.setMode(originalSolution.getMode());
|
|
||||||
|
|
||||||
// 复制事件和点(深拷贝)
|
|
||||||
List<SolutionWithEventsAndPoints.EventWithPoints> newEventsWithPoints = new ArrayList<>();
|
|
||||||
if (originalData.events != null) {
|
|
||||||
for (SolutionWithEventsAndPoints.EventWithPoints originalEvent : originalData.events) {
|
|
||||||
SolutionWithEventsAndPoints.EventWithPoints newEvent = new SolutionWithEventsAndPoints.EventWithPoints();
|
|
||||||
// 复制 EventEntity
|
|
||||||
newEvent.eventEntity = new EventEntity();
|
|
||||||
newEvent.eventEntity.eventId = UUID.randomUUID().toString(); // 新的事件ID
|
|
||||||
newEvent.eventEntity.solutionId = newSolution.getSolutionId(); // 关联新的方案ID
|
|
||||||
newEvent.eventEntity.eventType = originalEvent.eventEntity.eventType;
|
|
||||||
newEvent.eventEntity.orderInSolution = originalEvent.eventEntity.orderInSolution;
|
|
||||||
|
|
||||||
// 复制 TouchPoint
|
|
||||||
if (originalEvent.clickTouchPoint != null) {
|
|
||||||
newEvent.clickTouchPoint = new TouchPoint();
|
|
||||||
newEvent.clickTouchPoint.pointId = UUID.randomUUID().toString(); // 新的点ID
|
|
||||||
newEvent.clickTouchPoint.eventId = newEvent.eventEntity.eventId; // 关联新的事件ID
|
|
||||||
newEvent.clickTouchPoint.x = originalEvent.clickTouchPoint.x;
|
|
||||||
newEvent.clickTouchPoint.y = originalEvent.clickTouchPoint.y;
|
|
||||||
newEvent.clickTouchPoint.pointOrder = originalEvent.clickTouchPoint.pointOrder;
|
|
||||||
}
|
|
||||||
if (originalEvent.slideStartTouchPoint != null) {
|
|
||||||
newEvent.slideStartTouchPoint = new TouchPoint();
|
|
||||||
newEvent.slideStartTouchPoint.pointId = UUID.randomUUID().toString(); // 新的点ID
|
|
||||||
newEvent.slideStartTouchPoint.eventId = newEvent.eventEntity.eventId; // 关联新的事件ID
|
|
||||||
newEvent.slideStartTouchPoint.x = originalEvent.slideStartTouchPoint.x;
|
|
||||||
newEvent.slideStartTouchPoint.y = originalEvent.slideStartTouchPoint.y;
|
|
||||||
newEvent.slideStartTouchPoint.pointOrder = originalEvent.slideStartTouchPoint.pointOrder;
|
|
||||||
}
|
|
||||||
if (originalEvent.slideEndTouchPoint != null) {
|
|
||||||
newEvent.slideEndTouchPoint = new TouchPoint();
|
|
||||||
newEvent.slideEndTouchPoint.pointId = UUID.randomUUID().toString(); // 新的点ID
|
|
||||||
newEvent.slideEndTouchPoint.eventId = newEvent.eventEntity.eventId; // 关联新的事件ID
|
|
||||||
newEvent.slideEndTouchPoint.x = originalEvent.slideEndTouchPoint.x;
|
|
||||||
newEvent.slideEndTouchPoint.y = originalEvent.slideEndTouchPoint.y;
|
|
||||||
newEvent.slideEndTouchPoint.pointOrder = originalEvent.slideEndTouchPoint.pointOrder;
|
|
||||||
}
|
|
||||||
newEventsWithPoints.add(newEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存新的方案及其事件和点
|
|
||||||
floatingViewManager.getEventRepository().saveSolutionWithEventsAndPoints(newSolution, newEventsWithPoints, new EventRepository.RepositoryCallback<Void>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(Void result) {
|
public void onComplete(Void result) {
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
Toast.makeText(ScriptsActivity.this, "方案 '" + originalSolution.getSolutionName() + "' 已复制为 '" + newSolution.getSolutionName() + "'", Toast.LENGTH_SHORT).show();
|
Toast.makeText(ScriptsActivity.this, "方案 '" + originalSolution.getSolutionName() + "' 已复制成功!", Toast.LENGTH_SHORT).show();
|
||||||
loadSolutions(); // 刷新列表
|
loadSolutions(); // 刷新列表
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -279,9 +226,9 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
new Handler(Looper.getMainLooper()).post(() ->
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
Toast.makeText(ScriptsActivity.this, "无法获取原始方案数据。", Toast.LENGTH_SHORT).show()
|
Toast.makeText(ScriptsActivity.this, "无法找到原始方案数据进行复制。", Toast.LENGTH_SHORT).show();
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,17 +236,16 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
public void onError(Exception e) {
|
public void onError(Exception e) {
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
Log.e(TAG, "获取原始方案数据失败: " + e.getMessage(), e);
|
Log.e(TAG, "获取原始方案数据失败: " + e.getMessage(), e);
|
||||||
Toast.makeText(ScriptsActivity.this, "复制方案失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(ScriptsActivity.this, "获取原始方案数据失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showDeleteConfirmationDialog(final Solution solution) {
|
private void showDeleteConfirmationDialog(final Solution solution) {
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle("删除方案")
|
.setTitle("删除方案")
|
||||||
.setMessage("确定要删除方案 '" + solution.getSolutionName() + "' 吗?")
|
.setMessage("确定要删除方案 '" + solution.getSolutionName() + "' 吗?\n此操作不可撤销!")
|
||||||
.setPositiveButton("删除", (dialog, which) -> deleteSolution(solution))
|
.setPositiveButton("删除", (dialog, which) -> deleteSolution(solution))
|
||||||
.setNegativeButton("取消", null)
|
.setNegativeButton("取消", null)
|
||||||
.show();
|
.show();
|
||||||
@ -328,26 +274,20 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
private void exportSolution(final Solution solution) {
|
private void exportSolution(final Solution solution) {
|
||||||
floatingViewManager.getEventRepository().getSolutionWithEventsAndPoints(solution.getSolutionId(), new EventRepository.RepositoryCallback<SolutionWithEventsAndPoints>() {
|
floatingViewManager.getEventRepository().getSolutionWithEventsAndPoints(solution.getSolutionId(), new EventRepository.RepositoryCallback<SolutionWithEventsAndPoints>() {
|
||||||
@Override
|
@Override
|
||||||
public void onComplete(SolutionWithEventsAndPoints solutionData) {
|
public void onComplete(SolutionWithEventsAndPoints data) {
|
||||||
if (solutionData != null) {
|
if (data != null) {
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
tempExportJson = floatingViewManager.getEventRepository().exportSolutionToJson(data);
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
if (tempExportJson != null && !tempExportJson.isEmpty()) {
|
||||||
String jsonString = gson.toJson(solutionData);
|
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
intent.setType("application/json"); // 导出为 JSON 文件
|
intent.setType("application/json");
|
||||||
intent.putExtra(Intent.EXTRA_TITLE, solution.getSolutionName() + ".json");
|
intent.putExtra(Intent.EXTRA_TITLE, solution.getSolutionName() + ".json");
|
||||||
startActivityForResult(intent, CREATE_FILE_REQUEST_CODE);
|
startActivityForResult(intent, CREATE_FILE_REQUEST_CODE);
|
||||||
|
|
||||||
// 将 JSON 字符串保存到临时变量或直接传递
|
|
||||||
// 在 onActivityResult 中处理保存
|
|
||||||
tempExportJson = jsonString; // 临时保存待导出的JSON数据
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
new Handler(Looper.getMainLooper()).post(() ->
|
Toast.makeText(ScriptsActivity.this, "无法生成导出数据。", Toast.LENGTH_SHORT).show();
|
||||||
Toast.makeText(ScriptsActivity.this, "获取方案数据失败,无法导出。", Toast.LENGTH_SHORT).show()
|
}
|
||||||
);
|
} else {
|
||||||
|
Toast.makeText(ScriptsActivity.this, "无法获取方案数据进行导出。", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,17 +295,14 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
public void onError(Exception e) {
|
public void onError(Exception e) {
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
Log.e(TAG, "获取方案数据失败: " + e.getMessage(), e);
|
Log.e(TAG, "获取方案数据失败: " + e.getMessage(), e);
|
||||||
Toast.makeText(ScriptsActivity.this, "导出方案失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(ScriptsActivity.this, "获取方案数据失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 临时变量,用于存储待导出的JSON数据
|
|
||||||
private String tempExportJson;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (requestCode == CREATE_FILE_REQUEST_CODE && resultCode == RESULT_OK) {
|
if (requestCode == CREATE_FILE_REQUEST_CODE && resultCode == RESULT_OK) {
|
||||||
if (data != null && data.getData() != null) {
|
if (data != null && data.getData() != null) {
|
||||||
@ -385,6 +322,8 @@ public class ScriptsActivity extends AppCompatActivity implements SolutionAdapte
|
|||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "没有可导出的数据。", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "没有可导出的数据。", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "文件创建操作被取消或数据无效。", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,14 @@ public class SolutionAdapter extends RecyclerView.Adapter<SolutionAdapter.Soluti
|
|||||||
public SolutionAdapter(List<Solution> solutionList, OnSolutionClickListener listener, OnOptionMenuClickListener optionMenuListener) {
|
public SolutionAdapter(List<Solution> solutionList, OnSolutionClickListener listener, OnOptionMenuClickListener optionMenuListener) {
|
||||||
this.solutionList = solutionList;
|
this.solutionList = solutionList;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.optionMenuListener = optionMenuListener; // 初始化
|
this.optionMenuListener = optionMenuListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增构造函数,用于不需要选项菜单的情况
|
||||||
|
public SolutionAdapter(List<Solution> solutionList, OnSolutionClickListener listener) {
|
||||||
|
this.solutionList = solutionList;
|
||||||
|
this.listener = listener;
|
||||||
|
this.optionMenuListener = null; // 设置为 null,表示不需要选项菜单
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -68,12 +75,14 @@ public class SolutionAdapter extends RecyclerView.Adapter<SolutionAdapter.Soluti
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 为 option 按钮设置点击监听器
|
|
||||||
holder.option.setOnClickListener(v -> {
|
|
||||||
if (optionMenuListener != null) {
|
if (optionMenuListener != null) {
|
||||||
|
holder.option.setVisibility(View.VISIBLE); // 显示按钮
|
||||||
|
holder.option.setOnClickListener(v -> {
|
||||||
holder.showOptionMenu(solution, optionMenuListener); // 调用方法显示菜单
|
holder.showOptionMenu(solution, optionMenuListener); // 调用方法显示菜单
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
holder.option.setVisibility(View.GONE); // 隐藏按钮
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="292dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/bg_rounded_rect"
|
|
||||||
android:backgroundTint="#164958"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="My Script 1"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/mode"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/mode"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="1-point Mode"
|
|
||||||
android:textColor="@color/text_gray"
|
|
||||||
android:textSize="14sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/play"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/solution_play"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/option"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/option"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/script_option"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@ -48,6 +48,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/script_option"
|
android:src="@drawable/script_option"
|
||||||
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user