Merge branch 'main' into feature/settingmainfragment

# Conflicts:
#	feature/setting/src/main/java/one/nem/kidshift/feature/setting/SettingMainFragment.java
This commit is contained in:
ろむねこ 2024-07-01 11:53:27 +09:00
commit 666c4b0657
Signed by: Fujimatsu
GPG Key ID: FA1F39A1BA37D168
63 changed files with 1737 additions and 569 deletions

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@ -1,6 +1,7 @@
package one.nem.kidshift.data;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import one.nem.kidshift.model.ChildModel;
@ -11,13 +12,13 @@ public interface ChildData {
* @param childId 子ID
* @return ChildModel 子ユーザー情報
*/
ChildModel getChild(String childId);
CompletableFuture<ChildModel> getChild(String childId);
/**
* 子ユーザー一覧取得
* @return List<ChildModel> 子ユーザー一覧
*/
List<ChildModel> getChildList();
CompletableFuture<List<ChildModel>> getChildList();
/**
* 子ユーザー情報更新
@ -42,5 +43,5 @@ public interface ChildData {
* @param childId 子ID
* @return int ログインコード
*/
int issueLoginCode(String childId);
CompletableFuture<Integer> issueLoginCode(String childId);
}

View File

@ -1,17 +1,24 @@
package one.nem.kidshift.data;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.ParentModel;
import one.nem.kidshift.model.tasks.TaskItemModel;
/**
* データの同期など, ユーザーからの操作に基づかない処理を行う
*/
public interface KSActions {
void syncTasks();
/**
* タスク, 子供情報を同期してTaskItemModelを取得
*/
CompletableFuture<List<TaskItemModel>> syncTasks();
void syncChildList();
CompletableFuture<List<ChildModel>> syncChildList();
/**
* 親ユーザー情報同期

View File

@ -1,9 +1,11 @@
package one.nem.kidshift.data;
import java.util.concurrent.CompletableFuture;
public interface RewardData {
/**
* 現時点の合計報酬額を取得する
* @return Integer 合計報酬額
*/
Integer getTotalReward();
CompletableFuture<Integer> getTotalReward();
}

View File

@ -1,7 +1,9 @@
package one.nem.kidshift.data;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import one.nem.kidshift.model.callback.TaskItemModelCallback;
import one.nem.kidshift.model.tasks.TaskItemModel;
public interface TaskData {
@ -10,9 +12,16 @@ public interface TaskData {
/**
* 存在する全てのタスクを取得する
* @return List<TaskItemModel> タスクリスト
* @return CompletableFuture<List<TaskItemModel>> タスクリスト
*/
List<TaskItemModel> getTasks();
CompletableFuture<List<TaskItemModel>> getTasks(TaskItemModelCallback callback);
/**
* アタッチされている全てのタスクを取得する
* @param childId 子ID
* @return CompletableFuture<List<TaskItemModel>> タスクリスト
*/
CompletableFuture<List<TaskItemModel>> getTasks(String childId, TaskItemModelCallback callback);
/**
* タスクを追加する
@ -39,7 +48,7 @@ public interface TaskData {
* @param taskId タスクID
* @return TaskItemModel タスク
*/
TaskItemModel getTask(String taskId);
CompletableFuture<TaskItemModel> getTask(String taskId);
/**
* タスクの完了を記録する

View File

@ -1,53 +0,0 @@
package one.nem.kidshift.data.impl;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import one.nem.kidshift.data.ChildData;
import one.nem.kidshift.model.ChildModel;
public class ChildDataDummyImpl implements ChildData {
@Inject
public ChildDataDummyImpl() {
}
@Override
public ChildModel getChild(String childId) {
return null;
}
@Override
public List<ChildModel> getChildList() {
// 仮置きデータを生成する
List<ChildModel> childList = new ArrayList<>();
childList.add(new ChildModel("1", "子供1", "idididididid"));
childList.add(new ChildModel("2", "子供2", "idididididid"));
childList.add(new ChildModel("3", "子供3", "idididididid"));
return childList;
}
@Override
public void updateChild(ChildModel child) {
}
@Override
public void addChild(ChildModel child) {
}
@Override
public void removeChild(String childId) {
}
@Override
public int issueLoginCode(String childId) {
return 123456;
}
}

View File

@ -0,0 +1,73 @@
package one.nem.kidshift.data.impl;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.inject.Inject;
import one.nem.kidshift.data.ChildData;
import one.nem.kidshift.data.retrofit.KidShiftApiService;
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
import one.nem.kidshift.data.retrofit.model.converter.ChildModelConverter;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.utils.KSLogger;
import retrofit2.Call;
import retrofit2.Response;
public class ChildDataImpl implements ChildData {
private KidShiftApiService kidShiftApiService;
private KSLogger logger;
@Inject
public ChildDataImpl(KidShiftApiService kidShiftApiService, KSLogger logger) {
this.kidShiftApiService = kidShiftApiService;
this.logger = logger;
}
@Override
public CompletableFuture<ChildModel> getChild(String childId) {
return null;
}
@Override
public CompletableFuture<List<ChildModel>> getChildList() { // TODO-rca: DBにキャッシュするように修正する
return CompletableFuture.supplyAsync(() -> {
Call<ChildListResponse> call = kidShiftApiService.getChildList();
try {
Response<ChildListResponse> response = call.execute();
if (!response.isSuccessful()) return null; // TODO-rca: nullとするかは検討
ChildListResponse body = response.body();
if (body == null) return null;
return ChildModelConverter.childListResponseToChildModelList(body);
} catch (Exception e) {
logger.error(e.getMessage());
return null;
}
});
}
@Override
public void updateChild(ChildModel child) {
}
@Override
public void addChild(ChildModel child) {
}
@Override
public void removeChild(String childId) {
}
@Override
public CompletableFuture<Integer> issueLoginCode(String childId) {
return null;
}
}

View File

@ -1,5 +1,6 @@
package one.nem.kidshift.data.impl;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
@ -7,8 +8,17 @@ import javax.inject.Inject;
import one.nem.kidshift.data.KSActions;
import one.nem.kidshift.data.UserSettings;
import one.nem.kidshift.data.retrofit.KidShiftApiService;
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
import one.nem.kidshift.data.retrofit.model.converter.ChildModelConverter;
import one.nem.kidshift.data.retrofit.model.converter.ParentModelConverter;
import one.nem.kidshift.data.retrofit.model.converter.TaskModelConverter;
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
import one.nem.kidshift.data.room.KidShiftDatabase;
import one.nem.kidshift.data.room.utils.CacheWrapper;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.ParentModel;
import one.nem.kidshift.model.tasks.TaskItemModel;
import one.nem.kidshift.utils.KSLogger;
import retrofit2.Call;
import retrofit2.Response;
@ -18,23 +28,93 @@ public class KSActionsImpl implements KSActions {
private UserSettings userSettings;
private KidShiftApiService kidShiftApiService;
private KSLogger logger;
private CacheWrapper cacheWrapper;
@Inject
public KSActionsImpl(UserSettings userSettings, KidShiftApiService kidShiftApiService, KSLogger logger) {
public KSActionsImpl(UserSettings userSettings, KidShiftApiService kidShiftApiService, KSLogger logger, CacheWrapper cacheWrapper) {
this.userSettings = userSettings;
this.kidShiftApiService = kidShiftApiService;
this.logger = logger;
this.cacheWrapper = cacheWrapper;
logger.setTag("KSActions");
}
@Override
public void syncTasks() {
public CompletableFuture<List<TaskItemModel>> syncTasks() {
return doSyncTaskChild().thenApply(result -> result.taskList);
}
@Override
public void syncChildList() {
public CompletableFuture<List<ChildModel>> syncChildList() {
return doSyncTaskChild().thenApply(result -> result.childList);
}
private static class TaskSyncResult {
public List<TaskItemModel> taskList;
public List<ChildModel> childList;
}
private CompletableFuture<TaskSyncResult> doSyncTaskChild() {
return fetchChildListAsync().thenCombine(fetchTaskListAsync(), (childListResponse, taskListResponse) -> {
Thread cacheThread = new Thread(() -> {
logger.debug("キャッシュ更新スレッド開始(スレッドID: " + Thread.currentThread().getId() + ")");
cacheWrapper.updateCache(ChildModelConverter.childListResponseToChildModelList(childListResponse),
TaskModelConverter.taskListResponseToTaskItemModelList(taskListResponse)).join();
logger.info("キャッシュ更新完了");
});
cacheThread.start();
try {
// Workaround: DBオペレーションを待たずに結果を先に返したいが
// (現状(呼び出し元が)戻り値をそのままCallbackに渡しているために)
// キャッシュが空の場合のキャッシュ再取得のタイミングが調整できなくなる.
cacheThread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return new TaskSyncResult() {
{
taskList = TaskModelConverter.taskListResponseToTaskItemModelList(taskListResponse);
childList = ChildModelConverter.childListResponseToChildModelList(childListResponse);
}
};
});
}
private CompletableFuture<TaskListResponse> fetchTaskListAsync() {
return CompletableFuture.supplyAsync(() -> {
Call<TaskListResponse> call = kidShiftApiService.getTasks();
try {
Response<TaskListResponse> response = call.execute();
if (!response.isSuccessful()) {
logger.error("Error fetching task list: " + response.errorBody().string());
throw new RuntimeException("Error fetching task list: " + response.errorBody().string());
}
TaskListResponse responseBody = response.body();
return responseBody;
} catch (Exception e) {
logger.error("Error fetching task list");
throw new RuntimeException(e);
}
});
}
private CompletableFuture<ChildListResponse> fetchChildListAsync() {
return CompletableFuture.supplyAsync(() -> {
Call<ChildListResponse> call = kidShiftApiService.getChildList();
try {
Response<ChildListResponse> response = call.execute();
if (!response.isSuccessful()) {
logger.error("Error fetching child list: " + response.errorBody().string());
throw new RuntimeException("Error fetching child list: " + response.errorBody().string());
}
ChildListResponse responseBody = response.body();
return responseBody;
} catch (Exception e) {
logger.error("Error fetching child list");
throw new RuntimeException(e);
}
});
}
@Override
@ -50,13 +130,7 @@ public class KSActionsImpl implements KSActions {
throw new RuntimeException("Error fetching parent info: " + response.errorBody().string());
}
ParentInfoResponse responseBody = response.body();
ParentModel parent = new ParentModel();
// TODO: 詰め替えをどこかにまとめる, 他のプロパティも処理する
parent.setInternalId(responseBody.getId());
parent.setEmail(responseBody.getEmail());
parent.setDisplayName(responseBody.getEmail()); // Workaround
logger.info("Parent fetched with status: " + response.code());
logger.debug("Parent: " + parent);
ParentModel parent = ParentModelConverter.parentInfoResponseToParentModel(responseBody);
// Save to cache
userSettings.getCache().setParent(parent);
logger.info("Parent saved to cache");

View File

@ -2,6 +2,8 @@ package one.nem.kidshift.data.impl;
import com.github.javafaker.Faker;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
import one.nem.kidshift.data.RewardData;
@ -22,10 +24,7 @@ public class RewardDataDummyImpl implements RewardData {
}
@Override
public Integer getTotalReward() {
// logger.info("getTotalReward called");
Integer reward = faker.number().numberBetween(0, 10000);
// logger.info("Returning reward: " + reward);
return reward;
public CompletableFuture<Integer> getTotalReward() {
return CompletableFuture.supplyAsync(() -> faker.number().numberBetween(0, 1000));
}
}

View File

@ -1,78 +0,0 @@
package one.nem.kidshift.data.impl;
import com.github.javafaker.Faker;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.inject.Inject;
import one.nem.kidshift.data.TaskData;
import one.nem.kidshift.model.tasks.TaskItemModel;
import one.nem.kidshift.model.tasks.condition.TaskConditionBaseModel;
import one.nem.kidshift.model.tasks.condition.TaskConditionNoneModel;
import one.nem.kidshift.utils.KSLogger;
public class TaskDataDummyImpl implements TaskData {
private Faker faker;
@Inject
KSLogger logger;
@Inject
public TaskDataDummyImpl() {
faker = new Faker();
// logger.setTag("TaskDataDummyImpl");
}
@Override
public List<TaskItemModel> getTasks() {
// logger.info("getTotalReward called");
List<TaskItemModel> tasks = new ArrayList<>();
int totalTasks = faker.number().numberBetween(1, 15);
// logger.info("Returning total tasks: " + totalTasks);
for (int i = 0; i < totalTasks; i++) {
tasks.add(new TaskItemModel(
UUID.randomUUID().toString(),
faker.lorem().sentence(), UUID.randomUUID().toString(),
new TaskConditionNoneModel(),
faker.number().numberBetween(1, 1000)));
}
// logger.info("Returning tasks: " + tasks);
return tasks;
}
@Override
public void addTask(TaskItemModel task) {
logger.info("addTask called");
logger.info("Task: " + task);
}
@Override
public void removeTask(String taskId) {
logger.info("removeTask called");
logger.info("Task ID: " + taskId);
}
@Override
public void updateTask(TaskItemModel task) {
logger.info("updateTask called");
logger.info("Task: " + task);
}
@Override
public TaskItemModel getTask(String taskId) {
List<TaskItemModel> tasks = getTasks();
// return random task
return tasks.get(faker.number().numberBetween(0, tasks.size()));
}
@Override
public void recordTaskCompletion(String taskId, String childId) {
logger.info("recordTaskCompletion called");
logger.info("Task ID: " + taskId);
logger.info("Child ID: " + childId);
}
}

View File

@ -0,0 +1,87 @@
package one.nem.kidshift.data.impl;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.security.auth.callback.Callback;
import one.nem.kidshift.data.KSActions;
import one.nem.kidshift.data.TaskData;
import one.nem.kidshift.data.retrofit.model.converter.TaskModelConverter;
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
import one.nem.kidshift.data.room.utils.CacheWrapper;
import one.nem.kidshift.model.callback.TaskItemModelCallback;
import one.nem.kidshift.model.tasks.TaskItemModel;
import one.nem.kidshift.utils.KSLogger;
public class TaskDataImpl implements TaskData {
private KSActions ksActions;
private CacheWrapper cacheWrapper;
private KSLogger logger;
@Inject
public TaskDataImpl(KSActions ksActions, CacheWrapper cacheWrapper, KSLogger logger) {
this.ksActions = ksActions;
this.cacheWrapper = cacheWrapper;
this.logger = logger.setTag("TaskDataImpl");
}
@Override
public CompletableFuture<List<TaskItemModel>> getTasks(TaskItemModelCallback callback) {
return CompletableFuture.supplyAsync(() -> {
logger.debug("タスク取得開始");
Thread thread = new Thread(() -> {
// TODO-rca: ちゃんと比較して呼ぶ
ksActions.syncTasks().thenAccept(callback::onUpdated);
});
thread.start();
return cacheWrapper.getTaskList().thenApply(taskList -> {
if (taskList == null || taskList.isEmpty()) {
try {
logger.debug("キャッシュ無: タスク取得スレッド待機");
thread.join();
return cacheWrapper.getTaskList().join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
logger.debug("キャッシュ有 (タスク数: " + taskList.size() + ")");
return taskList;
}
}).join();
});
}
@Override
public CompletableFuture<List<TaskItemModel>> getTasks(String childId, TaskItemModelCallback callback) {
return null;
}
@Override
public void addTask(TaskItemModel task) {
}
@Override
public void removeTask(String taskId) {
}
@Override
public void updateTask(TaskItemModel task) {
}
@Override
public CompletableFuture<TaskItemModel> getTask(String taskId) {
return CompletableFuture.completedFuture(null);
}
@Override
public void recordTaskCompletion(String taskId, String childId) {
}
}

View File

@ -1,16 +0,0 @@
package one.nem.kidshift.data.modules;
import dagger.Binds;
import dagger.Module;
import dagger.hilt.InstallIn;
import dagger.hilt.android.components.FragmentComponent;
import one.nem.kidshift.data.ChildData;
import one.nem.kidshift.data.impl.ChildDataDummyImpl;
@Module
@InstallIn(FragmentComponent.class)
abstract public class ChildDataDummyModule {
@Binds
public abstract ChildData bindChildData(ChildDataDummyImpl childDataDummyImpl);
}

View File

@ -0,0 +1,16 @@
package one.nem.kidshift.data.modules;
import dagger.Binds;
import dagger.Module;
import dagger.hilt.InstallIn;
import dagger.hilt.components.SingletonComponent;
import one.nem.kidshift.data.ChildData;
import one.nem.kidshift.data.impl.ChildDataImpl;
@Module
@InstallIn(SingletonComponent.class)
public abstract class ChildDataModule {
@Binds
abstract ChildData provideChildData(ChildDataImpl childDataImpl);
}

View File

@ -5,12 +5,12 @@ import dagger.Module;
import dagger.hilt.InstallIn;
import dagger.hilt.android.components.FragmentComponent;
import one.nem.kidshift.data.TaskData;
import one.nem.kidshift.data.impl.TaskDataDummyImpl;
import one.nem.kidshift.data.impl.TaskDataImpl;
@Module
@InstallIn(FragmentComponent.class)
abstract public class TaskDataDummyModule {
public abstract class TaskDataModule {
@Binds
public abstract TaskData bindTaskData(TaskDataDummyImpl taskDataDummyImpl);
public abstract TaskData bindTaskData(TaskDataImpl taskDataImpl);
}

View File

@ -1,23 +1,119 @@
package one.nem.kidshift.data.retrofit;
import one.nem.kidshift.data.retrofit.interceptor.AuthorizationInterceptor;
import one.nem.kidshift.data.retrofit.model.child.ChildAddRequest;
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
import one.nem.kidshift.data.retrofit.model.child.ChildResponse;
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
import one.nem.kidshift.data.retrofit.model.parent.auth.ParentLoginRequest;
import one.nem.kidshift.data.retrofit.model.parent.auth.ParentLoginResponse;
import one.nem.kidshift.data.retrofit.model.task.TaskAddRequest;
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
import one.nem.kidshift.data.retrofit.model.task.TaskResponse;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
public interface KidShiftApiService {
// Parent APIs
// Auth
/**
* 保護者ログイン処理
* @param request ParentLoginRequest
* @return ParentLoginResponse
*/
@POST("/parent/auth/login")
Call<ParentLoginResponse> parentLogin(@Body ParentLoginRequest request);
/**
* 保護者アカウント情報取得処理
* @return ParentInfoResponse
*/
@GET("/parent/account")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<ParentInfoResponse> getParentInfo();
// Task APIs
/**
* タスク一覧取得
* @return TaskListResponse
*/
@GET("/parent/task")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<TaskListResponse> getTasks();
/**
* タスク追加
* @param request TaskAddRequest
* @return TaskResponse
*/
@POST("/parent/task")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<TaskResponse> addTask(@Body TaskAddRequest request);
/**
* タスク更新
* @param request TaskAddRequest
* @param id タスクID
* @return TaskResponse
*/
@PUT("/parent/task/{id}")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<TaskResponse> updateTask(@Body TaskAddRequest request, @Path("id") String id);
/**
* タスク削除
* @param id タスクID
* @return Void
*/
@DELETE("/parent/task/{id}")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<Void> removeTask(@Path("id") String id); // TODO-rca: OK responseをパース
/**
* タスク詳細取得
* @param id タスクID
* @return TaskResponse
*/
@GET("/parent/task/{id}")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<TaskResponse> getTask(@Path("id") String id);
/**
* タスク完了処理
* @param id タスクID
* @return Void
*/
@POST("/parent/task/{id}/complete")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<Void> completeTask(@Path("id") String id); // TODO-rca: OK responseをパース
// Child APIs
/**
* 子供一覧取得
* @return ChildListResponse
*/
@GET("/parent/child")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<ChildListResponse> getChildList();
/**
* 子供追加
* @param request ChildAddRequest
* @return ChildResponse
*/
@POST("/parent/child")
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
Call<ChildResponse> addChild(@Body ChildAddRequest request);
}

View File

@ -0,0 +1,23 @@
package one.nem.kidshift.data.retrofit.model.child;
// Request to add a child
public class ChildAddRequest {
private String name;
// Constructor
public ChildAddRequest(String name) {
this.name = name;
}
public ChildAddRequest() {
}
// Getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,33 @@
package one.nem.kidshift.data.retrofit.model.child;
// Base class for children
public class ChildBaseItem {
private String id;
private String name;
// Constructor
public ChildBaseItem(String id, String name) {
this.id = id;
this.name = name;
}
public ChildBaseItem() {
}
// Getters and setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,36 @@
package one.nem.kidshift.data.retrofit.model.child;
import java.util.Date;
// Response for detailed information about a child
public class ChildDetailsResponse extends ChildBaseItem {
private Date createdAt;
private String homeGroupId;
// Constructor
public ChildDetailsResponse(String id, String name, Date createdAt, String homeGroupId) {
super(id, name);
this.createdAt = createdAt;
this.homeGroupId = homeGroupId;
}
public ChildDetailsResponse() {
}
// Getters and setters
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getHomeGroupId() {
return homeGroupId;
}
public void setHomeGroupId(String homeGroupId) {
this.homeGroupId = homeGroupId;
}
}

View File

@ -0,0 +1,25 @@
package one.nem.kidshift.data.retrofit.model.child;
import java.util.List;
// Response for a list of children
public class ChildListResponse {
private List<ChildResponse> list;
// Constructor
public ChildListResponse(List<ChildResponse> list) {
this.list = list;
}
public ChildListResponse() {
}
// Getters and setters
public List<ChildResponse> getList() {
return list;
}
public void setList(List<ChildResponse> list) {
this.list = list;
}
}

View File

@ -0,0 +1,4 @@
package one.nem.kidshift.data.retrofit.model.child;
public class ChildRequest extends ChildBaseItem {
}

View File

@ -0,0 +1,4 @@
package one.nem.kidshift.data.retrofit.model.child;
public class ChildResponse extends ChildBaseItem {
}

View File

@ -0,0 +1,28 @@
package one.nem.kidshift.data.retrofit.model.converter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import one.nem.kidshift.data.retrofit.model.child.ChildAddRequest;
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
import one.nem.kidshift.data.retrofit.model.child.ChildResponse;
import one.nem.kidshift.model.ChildModel;
public class ChildModelConverter {
public static ChildAddRequest childModelToChildAddRequest(ChildModel childModel) {
ChildAddRequest request = new ChildAddRequest();
request.setName(childModel.getName());
return request;
}
public static List<ChildModel> childListResponseToChildModelList(ChildListResponse childListResponse) {
return childListResponse.getList().stream().map(ChildModelConverter::childResponseToChildModel).collect(Collectors.toList());
}
public static ChildModel childResponseToChildModel(ChildResponse childResponse) {
return new ChildModel(childResponse.getId(), childResponse.getName());
}
}

View File

@ -0,0 +1,16 @@
package one.nem.kidshift.data.retrofit.model.converter;
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
import one.nem.kidshift.model.ParentModel;
public class ParentModelConverter {
public static ParentModel parentInfoResponseToParentModel(ParentInfoResponse parentInfoResponse) {
return new ParentModel(parentInfoResponse.getId(), parentInfoResponse.getDisplayName(), parentInfoResponse.getEmail());
}
public static ParentInfoResponse parentModelToParentInfoResponse(ParentModel parentModel) {
return new ParentInfoResponse(parentModel.getId(), parentModel.getName(), parentModel.getEmail());
}
}

View File

@ -0,0 +1,35 @@
package one.nem.kidshift.data.retrofit.model.converter;
import java.util.List;
import java.util.stream.Collectors;
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
import one.nem.kidshift.data.retrofit.model.task.TaskResponse;
import one.nem.kidshift.model.tasks.TaskItemModel;
public class TaskModelConverter {
public static TaskItemModel taskResponseToTaskItemModel(TaskResponse taskResponse) {
TaskItemModel model = new TaskItemModel();
model.setId(taskResponse.getId());
model.setName(taskResponse.getName());
model.setReward(taskResponse.getReward());
model.setBgColor(taskResponse.getBgColor() == null ? "" : taskResponse.getBgColor());
model.setIconEmoji(taskResponse.getIconEmoji() == null ? "" : taskResponse.getIconEmoji());
return model;
}
public static TaskResponse taskItemModelToTaskResponse(TaskItemModel taskItemModel) {
TaskResponse response = new TaskResponse();
response.setId(taskItemModel.getId());
response.setName(taskItemModel.getName());
response.setReward(taskItemModel.getReward());
response.setBgColor(taskItemModel.getBgColor());
response.setIconEmoji(taskItemModel.getIconEmoji());
return response;
}
public static List<TaskItemModel> taskListResponseToTaskItemModelList(TaskListResponse taskListResponse) {
return taskListResponse.getList().stream().map(TaskModelConverter::taskResponseToTaskItemModel).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,39 @@
package one.nem.kidshift.data.retrofit.model.task;
import java.util.List;
public class TaskAddRequest extends TaskBaseItem {
private List<String> attachedChildren;
// コンストラクタ
// 全プロパティ
public TaskAddRequest(String name, String iconEmoji, String bgColor, int reward, List<String> attachedChildren) {
super(name, iconEmoji, bgColor, reward);
this.attachedChildren = attachedChildren;
}
// ID, Optionalなフィールドなし (登録時など)
public TaskAddRequest(String name, int reward, List<String> attachedChildren) {
super(name, reward);
this.attachedChildren = attachedChildren;
}
//
public TaskAddRequest() {
}
// baseItemを指定して拡張
public TaskAddRequest(TaskBaseItem taskBaseItem, List<String> attachedChildren) {
super(taskBaseItem.getName(), taskBaseItem.getIconEmoji(), taskBaseItem.getBgColor(), taskBaseItem.getReward());
this.attachedChildren = attachedChildren;
}
// Getters and setters
public List<String> getAttachedChildren() {
return attachedChildren;
}
public void setAttachedChildren(List<String> attachedChildren) {
this.attachedChildren = attachedChildren;
}
}

View File

@ -0,0 +1,85 @@
package one.nem.kidshift.data.retrofit.model.task;
public class TaskBaseItem {
private String id;
private String name;
private String iconEmoji; // Optional
private String bgColor; // Optional
private int reward;
// コンストラクタ
// 全プロパティ
public TaskBaseItem(String id, String name, String iconEmoji, String bgColor, int reward) {
this.id = id;
this.name = name;
this.iconEmoji = iconEmoji;
this.bgColor = bgColor;
this.reward = reward;
}
// IDなし (登録時など)
public TaskBaseItem(String name, String iconEmoji, String bgColor, int reward) {
this.name = name;
this.iconEmoji = iconEmoji;
this.bgColor = bgColor;
this.reward = reward;
}
// Optionalなフィールドなし
public TaskBaseItem(String id, String name, int reward) {
this.id = id;
this.name = name;
this.reward = reward;
}
// ID, Optionalなフィールドなし (登録時など)
public TaskBaseItem(String name, int reward) {
this.name = name;
this.reward = reward;
}
//
public TaskBaseItem() {
}
// Getters and setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIconEmoji() {
return iconEmoji;
}
public void setIconEmoji(String iconEmoji) {
this.iconEmoji = iconEmoji;
}
public String getBgColor() {
return bgColor;
}
public void setBgColor(String bgColor) {
this.bgColor = bgColor;
}
public int getReward() {
return reward;
}
public void setReward(int reward) {
this.reward = reward;
}
}

View File

@ -0,0 +1,27 @@
package one.nem.kidshift.data.retrofit.model.task;
import java.util.List;
public class TaskListResponse {
private List<TaskResponse> list;
// コンストラクタ
// 全プロパティ
public TaskListResponse(List<TaskResponse> list) {
this.list = list;
}
//
public TaskListResponse() {
}
// Getters and setters
public List<TaskResponse> getList() {
return list;
}
public void setList(List<TaskResponse> list) {
this.list = list;
}
}

View File

@ -0,0 +1,39 @@
package one.nem.kidshift.data.retrofit.model.task;
import java.util.List;
public class TaskResponse extends TaskBaseItem {
private List<String> attachedChildren;
// コンストラクタ
// 全プロパティ
public TaskResponse(String id, String name, String iconEmoji, String bgColor, int reward, List<String> attachedChildren) {
super(id, name, iconEmoji, bgColor, reward);
this.attachedChildren = attachedChildren;
}
// 必須プロパティ
public TaskResponse(String id, String name, int reward, List<String> attachedChildren) {
super(id, name, reward);
this.attachedChildren = attachedChildren;
}
//
public TaskResponse() {
}
// baseItemを指定して拡張
public TaskResponse(TaskBaseItem taskBaseItem, List<String> attachedChildren) {
super(taskBaseItem.getId(), taskBaseItem.getName(), taskBaseItem.getIconEmoji(), taskBaseItem.getBgColor(), taskBaseItem.getReward());
this.attachedChildren = attachedChildren;
}
// Getters and setters
public List<String> getAttachedChildren() {
return attachedChildren;
}
public void setAttachedChildren(List<String> attachedChildren) {
this.attachedChildren = attachedChildren;
}
}

View File

@ -1,7 +1,28 @@
package one.nem.kidshift.data.room.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
@Dao
public interface ChildCacheDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertChild(ChildCacheEntity child);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertChildList(List<ChildCacheEntity> childList);
@Query("SELECT * FROM child_cache WHERE id = :childId")
ChildCacheEntity getChild(String childId);
@Query("SELECT * FROM child_cache")
List<ChildCacheEntity> getChildList();
}

View File

@ -1,7 +1,26 @@
package one.nem.kidshift.data.room.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import java.util.List;
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
@Dao
public interface TaskCacheDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertTask(TaskCacheEntity task);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertTaskList(List<TaskCacheEntity> taskList);
@Query("SELECT * FROM task_cache WHERE id = :taskId")
TaskCacheEntity getTask(String taskId);
@Query("SELECT * FROM task_cache")
List<TaskCacheEntity> getTaskList();
}

View File

@ -1,7 +1,19 @@
package one.nem.kidshift.data.room.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import java.util.List;
import one.nem.kidshift.data.room.entity.TaskChildLinkageEntity;
@Dao
public interface TaskChildLinkageDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(TaskChildLinkageEntity taskChildLinkageEntity);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<TaskChildLinkageEntity> taskChildLinkageEntities);
}

View File

@ -11,8 +11,8 @@ public class ChildCacheEntity {
@PrimaryKey
@ColumnInfo(name = "id")
@NonNull
public String Id;
public String id;
@ColumnInfo(name = "display_name")
public String displayName;
@ColumnInfo(name = "name")
public String name;
}

View File

@ -11,10 +11,10 @@ public class TaskCacheEntity {
@PrimaryKey
@ColumnInfo(name = "id")
@NonNull
public String Id;
public String id;
@ColumnInfo(name = "display_name")
public String displayName;
@ColumnInfo(name = "name")
public String name;
@ColumnInfo(name = "icon_emoji")
public String iconEmoji;

View File

@ -0,0 +1,88 @@
package one.nem.kidshift.data.room.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
import dagger.Module;
import dagger.hilt.InstallIn;
import dagger.hilt.components.SingletonComponent;
import one.nem.kidshift.data.room.KidShiftDatabase;
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
import one.nem.kidshift.data.room.entity.TaskChildLinkageEntity;
import one.nem.kidshift.data.room.utils.converter.ChildCacheConverter;
import one.nem.kidshift.data.room.utils.converter.TaskCacheConverter;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.tasks.TaskItemModel;
import one.nem.kidshift.utils.KSLogger;
@Module
@InstallIn(SingletonComponent.class)
public class CacheWrapper {
private KidShiftDatabase kidShiftDatabase;
private KSLogger logger;
@Inject
public CacheWrapper(KidShiftDatabase kidShiftDatabase, KSLogger logger) {
this.kidShiftDatabase = kidShiftDatabase;
this.logger = logger;
}
public CompletableFuture<Void> updateCache(List<ChildModel> childList, List<TaskItemModel> taskList) {
return CompletableFuture.runAsync(() -> {
logger.debug("Updating cache");
insertChildList(childList).join();
logger.info("Child list inserted");
insertTaskList(taskList).join();
logger.info("Task list inserted");
// Update Linkage
List<TaskChildLinkageEntity> linkageList = new ArrayList<>(); // TODO-rca: タスク or 子供が追加された場合だけ実行するようにする?
for (TaskItemModel task : taskList) {
if (task.getAttachedChildren() == null || task.getAttachedChildren().isEmpty()) {
logger.warn("Task " + task.getName() + " has no attached children");
continue;
}
task.getAttachedChildren().forEach(child -> {
TaskChildLinkageEntity linkage = new TaskChildLinkageEntity();
linkage.taskId = task.getId();
linkage.childId = child.getId();
linkageList.add(linkage);
});
}
kidShiftDatabase.taskChildLinkageDao().insertAll(linkageList);
});
}
private CompletableFuture<Void> insertChildList(List<ChildModel> childList) {
return CompletableFuture.runAsync(() -> {
kidShiftDatabase.childCacheDao().insertChildList(ChildCacheConverter.childModelListToChildCacheEntityList(childList));
});
}
private CompletableFuture<Void> insertTaskList(List<TaskItemModel> taskList) {
return CompletableFuture.runAsync(() -> {
kidShiftDatabase.taskCacheDao().insertTaskList(TaskCacheConverter.taskModelListToTaskCacheEntityList(taskList));
});
}
public CompletableFuture<List<ChildModel>> getChildList() {
return CompletableFuture.supplyAsync(() -> {
// Get a list of children from the database
return null;
});
}
public CompletableFuture<List<TaskItemModel>> getTaskList() {
return CompletableFuture.supplyAsync(() -> {
List<TaskCacheEntity> result = kidShiftDatabase.taskCacheDao().getTaskList();
return TaskCacheConverter.taskCacheEntityListToTaskModelList(result);
});
}
}

View File

@ -0,0 +1,26 @@
package one.nem.kidshift.data.room.utils.converter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
import one.nem.kidshift.model.ChildModel;
public class ChildCacheConverter {
public static ChildCacheEntity childModelToChildCacheEntity(ChildModel childModel) {
ChildCacheEntity entity = new ChildCacheEntity();
entity.id = childModel.getId();
entity.name = childModel.getName();
return entity;
}
public static List<ChildCacheEntity> childModelListToChildCacheEntityList(List<ChildModel> childList) {
return childList.stream().map(ChildCacheConverter::childModelToChildCacheEntity).collect(Collectors.toList());
}
public static ChildModel childCacheEntityToChildModel(ChildCacheEntity entity) {
return new ChildModel(entity.id, entity.name);
}
}

View File

@ -0,0 +1,33 @@
package one.nem.kidshift.data.room.utils.converter;
import java.util.List;
import java.util.stream.Collectors;
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
import one.nem.kidshift.model.tasks.TaskItemModel;
public class TaskCacheConverter {
public static TaskCacheEntity taskModelToTaskCacheEntity(TaskItemModel taskModel) {
TaskCacheEntity entity = new TaskCacheEntity();
entity.id = taskModel.getId();
entity.name = taskModel.getName();
entity.iconEmoji = taskModel.getIconEmoji();
entity.reward = taskModel.getReward();
return entity;
}
public static List<TaskCacheEntity> taskModelListToTaskCacheEntityList(List<TaskItemModel> taskList) {
return taskList.stream().map(TaskCacheConverter::taskModelToTaskCacheEntity).collect(Collectors.toList());
}
public static TaskItemModel taskCacheEntityToTaskModel(TaskCacheEntity entity) {
return new TaskItemModel(entity.id, entity.name, entity.iconEmoji, entity.reward, null);
}
public static List<TaskItemModel> taskCacheEntityListToTaskModelList(List<TaskCacheEntity> entityList) {
return entityList.stream().map(TaskCacheConverter::taskCacheEntityToTaskModel).collect(Collectors.toList());
}
}

View File

@ -36,6 +36,10 @@ dependencies {
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
implementation project(':utils')
implementation project(':model')
implementation project(':data')
// Hilt (DI)
implementation libs.com.google.dagger.hilt.android
annotationProcessor libs.com.google.dagger.hilt.compiler

View File

@ -7,13 +7,32 @@ import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.kidshift.data.RewardData;
import one.nem.kidshift.utils.KSLogger;
/**
* A simple {@link Fragment} subclass.
* Use the {@link ChildMainFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class ChildMainFragment extends Fragment {
@Inject
KSLogger ksLogger;
@Inject
RewardData rewardData;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
@ -61,4 +80,29 @@ public class ChildMainFragment extends Fragment {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_child_main, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ksLogger.addTag("ChildMainFragment");
Integer reward = rewardData.getTotalReward().join();
ksLogger.debug("取得したデータ: " + reward);
Calendar cl = Calendar.getInstance();
TextView tr = view.findViewById(R.id.totalReward);
TextView dv = view.findViewById(R.id.dateView);
Date date = new Date();
NumberFormat nf = NumberFormat.getNumberInstance();
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyy年MM月");
dv.setText(sdf.format(cl.getTime()) + " お小遣い総額");
tr.setText("¥" + nf.format(reward).toString());
}
}

View File

@ -8,13 +8,25 @@
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/totalReward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="🧒CHILD"
android:textAppearance="@style/TextAppearance.AppCompat.Display3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/dateView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="お小遣い総額"
app:layout_constraintBottom_toTopOf="@+id/totalReward"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.10"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.85" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -44,4 +44,6 @@ dependencies {
implementation project(':model')
implementation project(':utils')
implementation project(':data')
implementation 'com.google.android.gms:play-services-cronet:18.0.1'
}

View File

@ -1,62 +0,0 @@
package one.nem.kidshift.feature.debug;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.kidshift.data.RewardData;
import one.nem.kidshift.data.TaskData;
@AndroidEntryPoint
public class DebugMockTestFragment extends Fragment {
@Inject
TaskData taskData;
@Inject
RewardData rewardData;
public DebugMockTestFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_debug_mock_test, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// TaskData
TextView taskDataStatus = view.findViewById(R.id.taskData_mockedStatusTextView);
taskDataStatus.setText("isMocked: true"); // TODO: 固定値やめる
TextView taskDataResult = view.findViewById(R.id.taskData_resultTextView);
view.findViewById(R.id.taskData_getTasksButton).setOnClickListener(v -> {
taskDataResult.setText(taskData.getTasks().stream().map(Object::toString).reduce("", (a, b) -> a + b + "\n"));
});
// RewardData
TextView rewardDataStatus = view.findViewById(R.id.rewardData_mockedStatusTextView);
rewardDataStatus.setText("isMocked: true"); // TODO: 固定値やめる
TextView rewardDataResult = view.findViewById(R.id.rewardData_resultTextView);
view.findViewById(R.id.rewardData_getTotalRewardButton).setOnClickListener(v -> {
rewardDataResult.setText(rewardData.getTotalReward().toString());
});
}
}

View File

@ -4,17 +4,47 @@ import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.text.Editable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextClock;
import android.widget.TextView;
import org.chromium.net.CronetEngine;
import org.chromium.net.CronetException;
import org.chromium.net.UrlRequest;
import org.chromium.net.UrlResponseInfo;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.kidshift.utils.KSLogger;
/**
* A simple {@link Fragment} subclass.
* Use the {@link DebugTempLoginFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class DebugTempLoginFragment extends Fragment {
@Inject
KSLogger logger;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
@ -59,6 +89,93 @@ public class DebugTempLoginFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_debug_temp_login, container, false);
View view = inflater.inflate(R.layout.fragment_debug_temp_login, container, false);
logger.setTag("Login");
//xmlレイアウトからid取得
EditText id = (EditText) view.findViewById(R.id.idtext);
EditText pass = (EditText) view.findViewById(R.id.pass);
CronetEngine.Builder engineBuilder = new CronetEngine.Builder(getContext().getApplicationContext());
engineBuilder.enableHttp2(true);
CronetEngine engine = engineBuilder.build();
//ログインボタンを押したときの処理
view.findViewById(R.id.button).setOnClickListener(
view1 -> {
//入力された値id,passを取得
Editable getText = id.getText();
Editable getPass = pass.getText();
// //入力された値id,passをログに表示
// logger.debug(getText.toString());
// logger.debug(getPass.toString());
Executor executor = Executors.newSingleThreadExecutor();
CronetCallback callback = new CronetCallback();
UrlRequest.Builder requestBuilder = engine.newUrlRequestBuilder(
"https://kidshift-beta.nem.one/debug/hello", callback, executor);
UrlRequest request = requestBuilder.build();
request.start();
}
);
return view;
}
private class CronetCallback extends UrlRequest.Callback{
private ByteArrayOutputStream bytesReceived = new ByteArrayOutputStream(); // 追加
private WritableByteChannel receiveChannel = Channels.newChannel(bytesReceived); // 追加
@Override
public void onRedirectReceived(UrlRequest request,UrlResponseInfo info,String newLocationUrl){
request.followRedirect();
// リダイレクトを許可しない場合
// request.cancel();
}
@Override
public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
request.read(ByteBuffer.allocateDirect(1024));
}
@Override
public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
byteBuffer.flip();
try {
receiveChannel.write(byteBuffer);
} catch (IOException e){
}
byteBuffer.clear();
request.read(byteBuffer);
String body = StandardCharsets.UTF_8.decode(byteBuffer).toString();
logger.debug(body);
}
@Override
public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
byte[] byteArray = bytesReceived.toByteArray();
String json = new String(byteArray);
}
@Override
public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) {
error.printStackTrace();
}
}
}

View File

@ -31,7 +31,6 @@ public class DebugTopMenuFragment extends Fragment {
recyclerView.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(getContext()));
List<DebugMenuListItemModel> debugMenuListItems = new ArrayList<>();
debugMenuListItems.add(new DebugMenuListItemModel("Data mock tester", "データモジュールの取得処理のモックをテストします", R.id.action_debugTopMenuFragment_to_debugMockTestFragment, true));
debugMenuListItems.add(new DebugMenuListItemModel("Debug console", "デバッグコマンドを実行します", R.id.action_debugTopMenuFragment_to_debugDebugConsoleFragment, true));
debugMenuListItems.add(new DebugMenuListItemModel("Temp login", "仮置きログイン画面を表示", R.id.action_debugTopMenuFragment_to_debugTempLoginFragment, true));
debugMenuListItems.add(new DebugMenuListItemModel("Temp register", "仮置き登録画面を表示", R.id.action_debugTopMenuFragment_to_debugTempRegisterFragment, true));

View File

@ -1,119 +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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugMockTestFragment">
<!-- TODO: Update blank fragment layout -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TaskData"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/taskData_mockedStatusTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="isMocked:" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/taskData_getTasksButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="getTasks()"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<Button
android:id="@+id/taskData_placeholderButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="-----" />
</LinearLayout>
<TextView
android:id="@+id/taskData_resultTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="result..." />
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="16dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RewardData"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/rewardData_mockedStatusTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="isMocked:" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/rewardData_getTotalRewardButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="getTotalReward()"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
</LinearLayout>
<TextView
android:id="@+id/rewardData_resultTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="result..." />
</LinearLayout>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,14 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugTempLoginFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:text="KidShiftアカウント"
android:textSize="34sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/idtext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="120dp"
android:ems="10"
android:hint="IDを入力"
android:inputType="text"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<EditText
android:id="@+id/pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:ems="10"
android:inputType="textPassword"
android:textSize="30sp"
android:hint="パスワード入力"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/idtext" />
<Button
android:id="@+id/button"
android:layout_width="154dp"
android:layout_height="68dp"
android:layout_marginTop="80dp"
android:backgroundTint="#9400d3"
android:text="ログイン"
android:textColor="#ffffff"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pass" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,14 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugTempRegisterFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
android:id="@+id/registerTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="KidShift アカウント"
android:textSize="30dp"
app:layout_constraintBottom_toTopOf="@id/editLinear"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.51" />
<LinearLayout
android:id="@+id/editLinear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@+id/registerTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/registerButton">
<EditText
android:id="@+id/registerEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart= "24dp"
android:layout_marginTop="96dp"
android:layout_marginEnd="24dp"
android:hint="メールアドレス"
android:inputType="textEmailAddress"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/registerPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:hint="パスワード"
android:imeActionLabel="パスワードは5文字以上で入力してください"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:selectAllOnFocus="true"/>
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/registerEmail" />-->
<EditText
android:id="@+id/registerPasswordCheck"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:hint="パスワードの確認"
android:imeActionLabel="パスワードは5文字以上で入力してください"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:selectAllOnFocus="true"/>
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/registerPassword" />-->
</LinearLayout>
<Button
android:id="@+id/registerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginStart="48dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="48dp"
android:layout_marginBottom="64dp"
android:enabled="false"
android:text="登録"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editLinear"
app:layout_constraintVertical_bias="0.2" />
<ProgressBar
android:id="@+id/registerLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="32dp"
android:layout_marginTop="64dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="64dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/editLinear"
app:layout_constraintStart_toStartOf="@+id/editLinear"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -10,9 +10,6 @@
android:name="one.nem.kidshift.feature.debug.DebugTopMenuFragment"
android:label="fragment_debug_top_menu"
tools:layout="@layout/fragment_debug_top_menu" >
<action
android:id="@+id/action_debugTopMenuFragment_to_debugMockTestFragment"
app:destination="@id/debugMockTestFragment" />
<action
android:id="@+id/action_debugTopMenuFragment_to_debugDebugConsoleFragment"
app:destination="@id/debugDebugConsoleFragment" />
@ -23,11 +20,6 @@
android:id="@+id/action_debugTopMenuFragment_to_debugTempRegisterFragment"
app:destination="@id/debugTempRegisterFragment" />
</fragment>
<fragment
android:id="@+id/debugMockTestFragment"
android:name="one.nem.kidshift.feature.debug.DebugMockTestFragment"
android:label="fragment_debug_mock_test"
tools:layout="@layout/fragment_debug_mock_test" />
<fragment
android:id="@+id/debugDebugConsoleFragment"
android:name="one.nem.kidshift.feature.debug.DebugDebugConsoleFragment"

View File

@ -0,0 +1,49 @@
package one.nem.kidshift.feature.parent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.chip.Chip;
import java.util.List;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.tasks.TaskItemModel;
public class ChildListAdapter extends RecyclerView.Adapter<ChildListAdapter.MainViewHolder> {
private final List<ChildModel> childDataList;
ChildListAdapter(List<ChildModel> childDataList) {
this.childDataList = childDataList;
}
static class MainViewHolder extends RecyclerView.ViewHolder {
CheckBox childname;
MainViewHolder(@NonNull View itemView) {
super(itemView);
childname = itemView.findViewById(R.id.childname);
}
}
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.select_child_list,parent,false);
return new MainViewHolder(view);
}
public void onBindViewHolder(@NonNull MainViewHolder holder,int position){
ChildModel childData = this.childDataList.get(position);
holder.childname.setText(childData.getName());
}
@Override
public int getItemCount(){ return childDataList.size();}
}

View File

@ -10,6 +10,7 @@ import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.tasks.TaskItemModel;
public class ParentAdapter extends RecyclerView.Adapter<ParentAdapter.MainViewHolder> {
@ -18,6 +19,8 @@ public class ParentAdapter extends RecyclerView.Adapter<ParentAdapter.MainViewHo
ParentAdapter(List<TaskItemModel> taskDataList) { this.taskDataList = taskDataList; }
static class MainViewHolder extends RecyclerView.ViewHolder{
TextView taskTitle;
TextView taskContents;
@ -38,7 +41,7 @@ public class ParentAdapter extends RecyclerView.Adapter<ParentAdapter.MainViewHo
public void onBindViewHolder(@NonNull MainViewHolder holder,int position){
TaskItemModel taskData = this.taskDataList.get(position);
holder.taskTitle.setText(taskData.getDisplayName());
holder.taskTitle.setText(taskData.getName());
holder.taskContents.setText(Long.toString(taskData.getReward()));
}

View File

@ -11,12 +11,17 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.kidshift.data.ChildData;
import one.nem.kidshift.data.TaskData;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.callback.TaskItemModelCallback;
import one.nem.kidshift.model.tasks.TaskItemModel;
import one.nem.kidshift.utils.KSLogger;
@ -27,6 +32,8 @@ public class ParentMainFragment extends Fragment {
KSLogger ksLogger;
@Inject
TaskData taskData;
@Inject
ChildData childData;
public ParentMainFragment() {
// Required empty public constructor
@ -35,6 +42,8 @@ public class ParentMainFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//タスク一覧表示
View view = inflater.inflate(R.layout.fragment_parent_main, container, false);
RecyclerView recyclerView = view.findViewById(R.id.main_recycle_view);
@ -44,11 +53,60 @@ public class ParentMainFragment extends Fragment {
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
List<TaskItemModel> task = taskData.getTasks();
ksLogger.debug("タスク一覧取得開始");
List<TaskItemModel> task = taskData.getTasks(new TaskItemModelCallback() {
@Override
public void onUnchanged() {
// TODO: Do something
}
@Override
public void onUpdated(List<TaskItemModel> taskItem) {
// TODO: Do something
}
@Override
public void onFailed(String message) {
// TODO: Do something
}
}).join();
ksLogger.debug("タスク一覧取得完了");
RecyclerView.Adapter mainAdapter = new ParentAdapter(task);
recyclerView.setAdapter(mainAdapter);
//お手伝い追加ダイアログ
LayoutInflater inflater1 = requireActivity().getLayoutInflater();
View view1 = inflater1.inflate(R.layout.add_task_list_dialog,null);
//子供選択表示
RecyclerView recyclerView1 = view1.findViewById(R.id.taskchild);
recyclerView1.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager1 = new LinearLayoutManager(getContext());
recyclerView1.setLayoutManager(layoutManager1);
ksLogger.debug("子供一覧取得開始");
List<ChildModel> child = childData.getChildList().join();
ksLogger.debug("子供一覧取得完了");
RecyclerView.Adapter mainAdapter1 = new ChildListAdapter(child);
recyclerView1.setAdapter(mainAdapter1);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle("お手伝い名追加")
.setView(view1)
.setPositiveButton("追加", null)
.setNeutralButton("閉じる",null);
builder.create();
view.findViewById(R.id.addtask).setOnClickListener(v -> {
builder.show();
});
return view;
}

View File

@ -0,0 +1,43 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/taskname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:ems="10"
android:hint="お手伝い名を入力"
android:inputType="text"
android:textSize="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/taskmoney"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:ems="10"
android:hint="金額を入力"
android:inputType="number"
android:textSize="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/taskname" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/taskchild"
android:layout_width="232dp"
android:layout_height="158dp"
android:layout_marginTop="25dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/taskmoney" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,16 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ParentMainFragment">
<Button
android:id="@+id/addtask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/main_recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="wrap_content" />
</FrameLayout>
</LinearLayout>

View File

@ -0,0 +1,17 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/childname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -32,6 +32,7 @@ dependencies {
implementation libs.material
implementation libs.navigation.fragment
implementation libs.navigation.ui
implementation libs.swiperefreshlayout
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core

View File

@ -42,7 +42,7 @@ public class SettingAdapter extends RecyclerView.Adapter<SettingAdapter.MainView
@Override
public void onBindViewHolder(@NonNull MainViewHolder holder, int position){
ChildModel childData = this.childDataList.get(position);
holder.childname.setText(childData.getDisplayName());
holder.childname.setText(childData.getName());
}
@Override

View File

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
@ -16,7 +17,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
@ -136,13 +136,45 @@ public class SettingMainFragment extends Fragment {
ParentModel parent = completableFuture.join();
if (parent == null) {
parent = new ParentModel(); // Workaround非ログインデバッグ用
parent.setName("親の名前");
parent.setEmail("親のアドレス");
}
// Pull-to-refreshスワイプで更新
SwipeRefreshLayout swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_layout);
ParentModel finalParent = parent;
swipeRefreshLayout.setOnRefreshListener(() ->{
username.setText(finalParent.getName());
useradress.setText(finalParent.getEmail());
RecyclerView recyclerView = view.findViewById(R.id.childrecyclerview);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
List<ChildModel> child = childData.getChildList().join();
RecyclerView.Adapter mainAdapter = new SettingAdapter(child);
recyclerView.setAdapter(mainAdapter);
swipeRefreshLayout.setRefreshing(false);
});
//RecyclerViewの処理
TextView username = view.findViewById(R.id.username);
TextView useradress = view.findViewById(R.id.useradress);
username.setText(parent.getDisplayName());
useradress.setText(parent.getEmail());
} catch (Exception e) {
//
}
RecyclerView recyclerView = view.findViewById(R.id.childrecyclerview);
recyclerView.setHasFixedSize(true);
@ -171,12 +203,6 @@ public class SettingMainFragment extends Fragment {
});
//RecyclerViewの処理
return view;
}
}

View File

@ -1,10 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingMainFragment">
tools:context=".SettingMainFragment"
android:id="@+id/swipe_refresh_layout">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"-->
<!-- xmlns:app="http://schemas.android.com/apk/res-auto"-->
<!-- xmlns:tools="http://schemas.android.com/tools"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- tools:context=".SettingMainFragment">-->
<!-- TODO: Update blank fragment layout -->
@ -88,3 +101,4 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -1,7 +1,6 @@
[versions]
agp = "8.3.2"
gson = "2.11.0"
javafaker = "1.0.2"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
@ -10,14 +9,16 @@ material = "1.12.0"
activity = "1.9.0"
constraintlayout = "2.1.4"
nav = "2.7.7"
swiperefreshlayout = "1.1.0"
retrofit = "2.11.0"
room = "2.5.0"
room = "2.6.1"
javafaker = "1.0.2"
[libraries]
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
javafaker = { module = "com.github.javafaker:javafaker", version.ref = "javafaker" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
javafaker = { module = "com.github.javafaker:javafaker", version.ref = "javafaker" }
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
@ -31,6 +32,7 @@ com-google-dagger-hilt-compiler = { group="com.google.dagger", name="hilt-compil
navigation-fragment = { group="androidx.navigation", name="navigation-fragment", version.ref="nav"}
navigation-ui = { group="androidx.navigation", name="navigation-ui", version.ref="nav"}
navigation-dynamic-features-fragment = { group="androidx.navigation", name="navigation-dynamic-features-fragment", version.ref="nav"}
swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }

View File

@ -1,50 +1,18 @@
package one.nem.kidshift.model;
// TODO: parent, childを共通クラスから継承させる
public class ChildModel {
String internalId;
String displayName;
String homeGroupId;
public class ChildModel extends UserBaseModel {
public ChildModel(String internalId, String displayName, String homeGroupId) {
this.internalId = internalId;
this.displayName = displayName;
this.homeGroupId = homeGroupId;
// Additional fields
public ChildModel(String id, String name) {
super(id, name);
}
public ChildModel(String internalId, String displayName) {
this.internalId = internalId;
this.displayName = displayName;
}
public ChildModel(String internalId) {
this.internalId = internalId;
public ChildModel(String name) {
super(name);
}
public ChildModel() {
}
public String getInternalId() {
return internalId;
}
public void setInternalId(String internalId) {
this.internalId = internalId;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getHomeGroupId() {
return homeGroupId;
}
public void setHomeGroupId(String homeGroupId) {
this.homeGroupId = homeGroupId;
}
}

View File

@ -1,65 +1,33 @@
package one.nem.kidshift.model;
// TODO: parent, childを共通クラスから継承させる
public class ParentModel {
String internalId;
String displayName;
String homeGroupId;
String email;
public class ParentModel extends UserBaseModel {
public ParentModel(String internalId, String displayName, String homeGroupId, String email) {
this.internalId = internalId;
this.displayName = displayName;
this.homeGroupId = homeGroupId;
private String email;
public ParentModel(String id, String name, String email) {
super(id, name);
this.email = email;
}
public ParentModel(String internalId, String displayName, String homeGroupId) {
this.internalId = internalId;
this.displayName = displayName;
this.homeGroupId = homeGroupId;
private ParentModel(UserBaseModel userBaseModel, String email) {
super(userBaseModel.getId().isEmpty() ? null : userBaseModel.getId(), userBaseModel.getName());
this.email = email;
}
public ParentModel(String internalId, String displayName) {
this.internalId = internalId;
this.displayName = displayName;
public ParentModel(String name, String email) {
super(name);
this.email = email;
}
public ParentModel() {
}
// Getter
public String getInternalId() {
return internalId;
}
public String getDisplayName() {
return displayName;
}
public String getHomeGroupId() {
return homeGroupId;
}
public String getEmail() {
return email;
}
// Setter
public void setInternalId(String internalId) {
this.internalId = internalId;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public void setHomeGroupId(String homeGroupId) {
this.homeGroupId = homeGroupId;
}
public void setEmail(String email) {
this.email = email;
}

View File

@ -0,0 +1,35 @@
package one.nem.kidshift.model;
public class UserBaseModel {
private String id;
private String name;
public UserBaseModel(String id, String name) {
this.id = id;
this.name = name;
}
public UserBaseModel(String name) {
this.name = name;
}
public UserBaseModel() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,14 @@
package one.nem.kidshift.model.callback;
import java.util.List;
import one.nem.kidshift.model.tasks.TaskItemModel;
public interface TaskItemModelCallback {
void onUnchanged();
void onUpdated(List<TaskItemModel> taskItem);
void onFailed(String message);
}

View File

@ -4,98 +4,113 @@ import android.graphics.Color;
import androidx.annotation.NonNull;
import java.util.List;
import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.tasks.condition.TaskConditionBaseModel;
public class TaskItemModel {
String internalId;
String attachedChildId;
String displayName;
String iconEmoji;
Color bgColor;
TaskConditionBaseModel condition;
long reward;
private String id;
private String name;
private String iconEmoji; // Optional
private String bgColor; // Optional
private int reward;
private List<ChildModel> attachedChildren; // Optional
// constructor
public TaskItemModel(String internalId, String displayName, String attachedChildId, String iconEmoji, Color bgColor, TaskConditionBaseModel condition, long reward) {
this.internalId = internalId;
this.attachedChildId = attachedChildId;
this.displayName = displayName;
// コンストラクタ
// 全プロパティ
public TaskItemModel(String id, String name, String iconEmoji, String bgColor, int reward, List<ChildModel> attachedChildren) {
this.id = id;
this.name = name;
this.iconEmoji = iconEmoji;
this.condition = condition;
this.bgColor = bgColor;
this.reward = reward;
this.attachedChildren = attachedChildren;
}
// IDなし (登録時など)
public TaskItemModel(String name, String iconEmoji, String bgColor, int reward, List<ChildModel> attachedChildren) {
this.name = name;
this.iconEmoji = iconEmoji;
this.bgColor = bgColor;
this.reward = reward;
this.attachedChildren = attachedChildren;
}
// Optionalなフィールドなし
public TaskItemModel(String id, String name, int reward, List<ChildModel> attachedChildren) {
this.id = id;
this.name = name;
this.reward = reward;
this.attachedChildren = attachedChildren;
}
// ID, Optionalなフィールドなし (登録時など)
public TaskItemModel(String name, int reward, List<ChildModel> attachedChildren) {
this.name = name;
this.reward = reward;
this.attachedChildren = attachedChildren;
}
//
public TaskItemModel() {
}
// Getters and setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIconEmoji() {
return iconEmoji;
}
public void setIconEmoji(String iconEmoji) {
this.iconEmoji = iconEmoji;
}
public String getBgColor() {
return bgColor;
}
public void setBgColor(String bgColor) {
this.bgColor = bgColor;
}
public TaskItemModel(String internalId, String displayName, String attachedChildId, String iconEmoji, TaskConditionBaseModel condition, long reward) {
this.internalId = internalId;
this.attachedChildId = attachedChildId;
this.displayName = displayName;
this.iconEmoji = iconEmoji;
this.condition = condition;
this.reward = reward;
}
public TaskItemModel(String internalId, String displayName, String attachedChildId, TaskConditionBaseModel condition, long reward) {
this.internalId = internalId;
this.attachedChildId = attachedChildId;
this.displayName = displayName;
this.condition = condition;
this.reward = reward;
}
// getter setter
public String getInternalId() {
return internalId;
}
public void setInternalId(String internalId) {
this.internalId = internalId;
}
public String getAttachedChildId() {
return attachedChildId;
}
public void setAttachedChildId(String attachedChildId) {
this.attachedChildId = attachedChildId;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public TaskConditionBaseModel getCondition() {
return condition;
}
public void setCondition(TaskConditionBaseModel condition) {
this.condition = condition;
}
public long getReward() {
public int getReward() {
return reward;
}
public void setReward(long reward) {
public void setReward(int reward) {
this.reward = reward;
}
@NonNull
@Override
public String toString() {
return "TaskItemModel{" + '\n' +
" internalId='" + internalId + '\n' +
" attachedChildId='" + attachedChildId + '\n' +
" displayName='" + displayName + '\n' +
// " condition=" + condition.toString() + '\n' +
" condition=" + "__________" + '\n' +
" reward=" + reward + '\n' +
'}';
public int getBgColorInt() {
return Color.parseColor(bgColor);
}
public void setBgColorInt(int color) {
this.bgColor = String.format("#%06X", 0xFFFFFF & color);
}
public List<ChildModel> getAttachedChildren() {
return attachedChildren;
}
public void setAttachedChildren(List<ChildModel> attachedChildren) {
this.attachedChildren = attachedChildren;
}
}