Merge branch 'main' into feature/add_task_menu

This commit is contained in:
Fujimatsu 2024-07-02 05:27:10 +00:00
commit e72d10f71a
57 changed files with 1406 additions and 379 deletions

View File

@ -1,18 +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 {
CompletableFuture<TaskListResponse> syncTasks();
/**
* タスク, 子供情報を同期してTaskItemModelを取得
*/
CompletableFuture<List<TaskItemModel>> syncTasks();
void syncChildList();
CompletableFuture<List<ChildModel>> syncChildList();
/**
* 親ユーザー情報同期

View File

@ -3,6 +3,7 @@ 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 {
@ -13,14 +14,14 @@ public interface TaskData {
* 存在する全てのタスクを取得する
* @return CompletableFuture<List<TaskItemModel>> タスクリスト
*/
CompletableFuture<List<TaskItemModel>> getTasks();
CompletableFuture<List<TaskItemModel>> getTasks(TaskItemModelCallback callback);
/**
* アタッチされている全てのタスクを取得する
* @param childId 子ID
* @return CompletableFuture<List<TaskItemModel>> タスクリスト
*/
CompletableFuture<List<TaskItemModel>> getTasks(String childId);
CompletableFuture<List<TaskItemModel>> getTasks(String childId, TaskItemModelCallback callback);
/**
* タスクを追加する

View File

@ -4,9 +4,28 @@ import one.nem.kidshift.model.ParentModel;
public interface UserSettings {
/**
* API設定のインスタンスを取得
* @return ApiSetting API設定
*/
ApiSetting getApiSetting();
/**
* タスク設定のインスタンスを取得
* @return TaskSetting タスク設定
*/
TaskSetting getTaskSetting();
/**
* アプリ共通設定のインスタンスを取得
* @return AppCommonSetting アプリ共通設定
*/
AppCommonSetting getAppCommonSetting();
/**
* キャッシュのインスタンスを取得
* @return SharedPrefCache キャッシュ
*/
SharedPrefCache getCache();
interface AppCommonSetting {

View File

@ -9,6 +9,7 @@ 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;
@ -41,13 +42,8 @@ public class ChildDataImpl implements ChildData {
ChildListResponse body = response.body();
if (body == null) return null;
return body.getList().stream().map(child -> {
ChildModel model = new ChildModel();
model.setDisplayName(child.getName().isEmpty() ? child.getId() : child.getName());
model.setInternalId(child.getId());
// 他のプロパティも処理する
return model;
}).collect(Collectors.toList());
return ChildModelConverter.childListResponseToChildModelList(body);
} catch (Exception e) {
logger.error(e.getMessage());
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,9 +8,16 @@ 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.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;
@ -19,42 +27,105 @@ 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 CompletableFuture<TaskListResponse> syncTasks() {
public CompletableFuture<List<TaskItemModel>> syncTasks() {
return doSyncTaskChild().thenApply(result -> result.taskList);
}
@Override
public CompletableFuture<List<ChildModel>> syncChildList() {
return doSyncTaskChild().thenApply(result -> result.childList);
}
private static class TaskSyncResult {
public List<TaskItemModel> taskList;
public List<ChildModel> childList;
}
/**
* タスクと子供リストを同期する(ラッパー)
* @return CompletableFuture<TaskSyncResult> タスクと子供リスト
*/
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);
}
};
});
}
/**
* バックエンドからタスクリストをFetchする
* @return CompletableFuture<TaskListResponse> バックエンドから取得したタスクリスト
*/
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 tasks: " + response.errorBody().string());
throw new RuntimeException("Error fetching tasks: " + response.errorBody().string());
logger.error("Error fetching task list: " + response.errorBody().string());
throw new RuntimeException("Error fetching task list: " + response.errorBody().string());
}
TaskListResponse responseBody = response.body();
logger.info("Tasks fetched with status: " + response.code());
logger.debug("Tasks: " + responseBody.getList());
// // Save to cache
// userSettings.getCache().setTasks(responseBody.getList());
// logger.info("Tasks saved to cache");
return responseBody;
} catch (Exception e) {
logger.error("Error fetching tasks");
logger.error("Error fetching task list");
throw new RuntimeException(e);
}
});
}
@Override
public void syncChildList() {
/**
* バックエンドから子供リストをFetchする
* @return CompletableFuture<ChildListResponse> バックエンドから取得した子供リスト
*/
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
@ -70,13 +141,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

@ -1,8 +1,5 @@
package one.nem.kidshift.data.impl;
import android.util.Log;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
@ -11,12 +8,9 @@ import one.nem.kidshift.data.KSActions;
import one.nem.kidshift.data.ParentData;
import one.nem.kidshift.data.UserSettings;
import one.nem.kidshift.data.retrofit.KidShiftApiService;
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
import one.nem.kidshift.model.ParentModel;
import one.nem.kidshift.model.callback.ParentModelCallback;
import one.nem.kidshift.utils.KSLogger;
import retrofit2.Call;
import retrofit2.Response;
public class ParentDataImpl implements ParentData {

View File

@ -5,39 +5,58 @@ 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 {
KSActions ksActions;
private KSActions ksActions;
private CacheWrapper cacheWrapper;
private KSLogger logger;
@Inject
public TaskDataImpl(KSActions ksActions) {
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() {
public CompletableFuture<List<TaskItemModel>> getTasks(TaskItemModelCallback callback) {
return CompletableFuture.supplyAsync(() -> {
TaskListResponse data = ksActions.syncTasks().join();
return data.getList().stream().map(task -> {
// Convert TaskItemModel
TaskItemModel model = new TaskItemModel();
model.setInternalId(task.getId());
model.setDisplayName(task.getName());
model.setReward(task.getReward());
return model;
}).collect(Collectors.toList());
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) {
public CompletableFuture<List<TaskItemModel>> getTasks(String childId, TaskItemModelCallback callback) {
return null;
}

View File

@ -1,10 +1,5 @@
package one.nem.kidshift.data.impl;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import javax.inject.Inject;
import one.nem.kidshift.data.UserSettings;

View File

@ -13,6 +13,9 @@ import okhttp3.Response;
import one.nem.kidshift.data.UserSettings;
import one.nem.kidshift.utils.KSLogger;
/**
* Authorization placeholderが指定されている場合にアクセストークンで置換するインターセプター
*/
public class AuthorizationInterceptor implements Interceptor {
private static final String HEADER_NAME = "Authorization";

View File

@ -4,11 +4,17 @@ package one.nem.kidshift.data.retrofit.model.child;
public class ChildAddRequest {
private String name;
// Constructor
/**
* コンストラクタ (全プロパティ)
* @param name 子供の名前
*/
public ChildAddRequest(String name) {
this.name = name;
}
/**
* コンストラクタ ()
*/
public ChildAddRequest() {
}

View File

@ -5,12 +5,19 @@ public class ChildBaseItem {
private String id;
private String name;
// Constructor
/**
* コンストラクタ (全プロパティ)
* @param id 子供ID
* @param name 子供の名前
*/
public ChildBaseItem(String id, String name) {
this.id = id;
this.name = name;
}
/**
* コンストラクタ ()
*/
public ChildBaseItem() {
}

View File

@ -7,13 +7,22 @@ public class ChildDetailsResponse extends ChildBaseItem {
private Date createdAt;
private String homeGroupId;
// Constructor
/**
* コンストラクタ (全プロパティ)
* @param id 子供ID
* @param name 子供の名前
* @param createdAt 作成日時
* @param homeGroupId ホームグループID
*/
public ChildDetailsResponse(String id, String name, Date createdAt, String homeGroupId) {
super(id, name);
this.createdAt = createdAt;
this.homeGroupId = homeGroupId;
}
/**
* コンストラクタ ()
*/
public ChildDetailsResponse() {
}

View File

@ -6,11 +6,17 @@ import java.util.List;
public class ChildListResponse {
private List<ChildResponse> list;
// Constructor
/**
* コンストラクタ (全プロパティ)
* @param list 子供リスト
*/
public ChildListResponse(List<ChildResponse> list) {
this.list = list;
}
/**
* コンストラクタ ()
*/
public ChildListResponse() {
}

View File

@ -0,0 +1,43 @@
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 {
/**
* ChildModelをChildAddRequestに変換する
* @param childModel ChildModel
* @return ChildAddRequest
*/
public static ChildAddRequest childModelToChildAddRequest(ChildModel childModel) {
ChildAddRequest request = new ChildAddRequest();
request.setName(childModel.getName());
return request;
}
/**
* ChildListResponseをChildModelリストに変換する
* @param childListResponse ChildListResponse
* @return ChildModelリスト
*/
public static List<ChildModel> childListResponseToChildModelList(ChildListResponse childListResponse) {
return childListResponse.getList().stream().map(ChildModelConverter::childResponseToChildModel).collect(Collectors.toList());
}
/**
* ChildResponseをChildModelに変換する
* @param childResponse ChildResponse
* @return ChildModel
*/
public static ChildModel childResponseToChildModel(ChildResponse childResponse) {
return new ChildModel(childResponse.getId(), childResponse.getName());
}
}

View File

@ -0,0 +1,26 @@
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 {
/**
* ParentInfoResponseをParentModelに変換する
* @param parentInfoResponse ParentInfoResponse
* @return ParentModel
*/
public static ParentModel parentInfoResponseToParentModel(ParentInfoResponse parentInfoResponse) {
return new ParentModel(parentInfoResponse.getId(), parentInfoResponse.getDisplayName(), parentInfoResponse.getEmail());
}
/**
* ParentModelをParentInfoResponseに変換する
* @param parentModel ParentModel
* @return ParentInfoResponse
*/
public static ParentInfoResponse parentModelToParentInfoResponse(ParentModel parentModel) {
return new ParentInfoResponse(parentModel.getId(), parentModel.getName(), parentModel.getEmail());
}
}

View File

@ -0,0 +1,50 @@
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 {
/**
* TaskResponseをTaskItemModelに変換する
* @param taskResponse TaskResponse
* @return TaskItemModel
*/
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;
}
/**
* TaskItemModelをTaskResponseに変換する
* @param taskItemModel TaskItemModel
* @return TaskResponse
*/
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;
}
/**
* TaskListResponseをTaskItemModelリストに変換する
* @param taskListResponse TaskListResponse
* @return TaskItemModelリスト
*/
public static List<TaskItemModel> taskListResponseToTaskItemModelList(TaskListResponse taskListResponse) {
return taskListResponse.getList().stream().map(TaskModelConverter::taskResponseToTaskItemModel).collect(Collectors.toList());
}
}

View File

@ -6,6 +6,12 @@ public class ParentInfoResponse {
private String email;
private String displayName;
/**
* コンストラクタ (全プロパティ)
* @param id 親ID
* @param email メールアドレス
* @param displayName 表示名
*/
public ParentInfoResponse(String id, String email, String displayName) {
this.id = id;
this.email = email;

View File

@ -4,6 +4,11 @@ public class ParentLoginRequest {
private String email;
private String password;
/**
* コンストラクタ (全プロパティ)
* @param email メールアドレス
* @param password パスワード
*/
public ParentLoginRequest(String email, String password) {
this.email = email;
this.password = password;

View File

@ -3,6 +3,10 @@ package one.nem.kidshift.data.retrofit.model.parent.auth;
public class ParentLoginResponse {
private String accessToken;
/**
* コンストラクタ (全プロパティ)
* @param accessToken アクセストークン
*/
public ParentLoginResponse(String accessToken) {
this.accessToken = accessToken;
}

View File

@ -5,24 +5,41 @@ import java.util.List;
public class TaskAddRequest extends TaskBaseItem {
private List<String> attachedChildren;
// コンストラクタ
// 全プロパティ
/**
* コンストラクタ (全プロパティ)
* @param name タスク名
* @param iconEmoji アイコン絵文字
* @param bgColor 背景色
* @param reward 報酬
* @param attachedChildren アタッチされた子供IDリスト
*/
public TaskAddRequest(String name, String iconEmoji, String bgColor, int reward, List<String> attachedChildren) {
super(name, iconEmoji, bgColor, reward);
this.attachedChildren = attachedChildren;
}
// ID, Optionalなフィールドなし (登録時など)
/**
* コンストラクタ (ID, Optionalなフィールドなし)
* @param name タスク名
* @param reward 報酬
* @param attachedChildren アタッチされた子供IDリスト
*/
public TaskAddRequest(String name, int reward, List<String> attachedChildren) {
super(name, reward);
this.attachedChildren = attachedChildren;
}
//
/**
* コンストラクタ ()
*/
public TaskAddRequest() {
}
// baseItemを指定して拡張
/**
* コンストラクタ (baseItemを指定して拡張)
* @param taskBaseItem タスクベースアイテム
* @param attachedChildren アタッチされた子供IDリスト
*/
public TaskAddRequest(TaskBaseItem taskBaseItem, List<String> attachedChildren) {
super(taskBaseItem.getName(), taskBaseItem.getIconEmoji(), taskBaseItem.getBgColor(), taskBaseItem.getReward());
this.attachedChildren = attachedChildren;

View File

@ -7,8 +7,14 @@ public class TaskBaseItem {
private String bgColor; // Optional
private int reward;
// コンストラクタ
// 全プロパティ
/**
* コンストラクタ (全プロパティ)
* @param id タスクID
* @param name タスク名
* @param iconEmoji アイコン絵文字
* @param bgColor 背景色
* @param reward 報酬
*/
public TaskBaseItem(String id, String name, String iconEmoji, String bgColor, int reward) {
this.id = id;
this.name = name;
@ -17,7 +23,13 @@ public class TaskBaseItem {
this.reward = reward;
}
// IDなし (登録時など)
/**
* コンストラクタ (IDなし)
* @param name タスク名
* @param iconEmoji アイコン絵文字
* @param bgColor 背景色
* @param reward 報酬
*/
public TaskBaseItem(String name, String iconEmoji, String bgColor, int reward) {
this.name = name;
this.iconEmoji = iconEmoji;
@ -25,20 +37,31 @@ public class TaskBaseItem {
this.reward = reward;
}
// Optionalなフィールドなし
/**
* コンストラクタ (Optionalなフィールドなし)
* @param id タスクID
* @param name タスク名
* @param reward 報酬
*/
public TaskBaseItem(String id, String name, int reward) {
this.id = id;
this.name = name;
this.reward = reward;
}
// ID, Optionalなフィールドなし (登録時など)
/**
* コンストラクタ (ID, Optionalなフィールドなし)
* @param name タスク名
* @param reward 報酬
*/
public TaskBaseItem(String name, int reward) {
this.name = name;
this.reward = reward;
}
//
/**
* コンストラクタ ()
*/
public TaskBaseItem() {
}

View File

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

View File

@ -5,24 +5,43 @@ import java.util.List;
public class TaskResponse extends TaskBaseItem {
private List<String> attachedChildren;
// コンストラクタ
// 全プロパティ
/**
* コンストラクタ (全プロパティ)
* @param id タスクID
* @param name タスク名
* @param iconEmoji アイコン絵文字
* @param bgColor 背景色
* @param reward 報酬
* @param attachedChildren アタッチされた子供IDリスト
*/
public TaskResponse(String id, String name, String iconEmoji, String bgColor, int reward, List<String> attachedChildren) {
super(id, name, iconEmoji, bgColor, reward);
this.attachedChildren = attachedChildren;
}
// 必須プロパティ
/**
* コンストラクタ (必須プロパティ)
* @param id タスクID
* @param name タスク名
* @param reward 報酬
* @param attachedChildren アタッチされた子供IDリスト
*/
public TaskResponse(String id, String name, int reward, List<String> attachedChildren) {
super(id, name, reward);
this.attachedChildren = attachedChildren;
}
//
/**
* コンストラクタ ()
*/
public TaskResponse() {
}
// baseItemを指定して拡張
/**
* コンストラクタ (baseItemを指定して拡張)
* @param taskBaseItem タスクベースアイテム
* @param attachedChildren アタッチされた子供IDリスト
*/
public TaskResponse(TaskBaseItem taskBaseItem, List<String> attachedChildren) {
super(taskBaseItem.getId(), taskBaseItem.getName(), taskBaseItem.getIconEmoji(), taskBaseItem.getBgColor(), taskBaseItem.getReward());
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,112 @@
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;
}
/**
* キャッシュを更新する
* @param childList 子供リスト
* @param taskList タスクリスト
* @return CompletableFuture
*/
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);
});
}
/**
* 子供リストをDBに挿入する
* @param childList 子供リスト
* @return CompletableFuture
*/
private CompletableFuture<Void> insertChildList(List<ChildModel> childList) {
return CompletableFuture.runAsync(() -> {
kidShiftDatabase.childCacheDao().insertChildList(ChildCacheConverter.childModelListToChildCacheEntityList(childList));
});
}
/**
* タスクリストをDBに挿入する
* @param taskList タスクリスト
* @return CompletableFuture
*/
private CompletableFuture<Void> insertTaskList(List<TaskItemModel> taskList) {
return CompletableFuture.runAsync(() -> {
kidShiftDatabase.taskCacheDao().insertTaskList(TaskCacheConverter.taskModelListToTaskCacheEntityList(taskList));
});
}
/**
* 子供リストを取得する
* @return CompletableFuture
*/
public CompletableFuture<List<ChildModel>> getChildList() {
return CompletableFuture.supplyAsync(() -> {
// Get a list of children from the database
return null;
});
}
/**
* タスクリストを取得する
* @return CompletableFuture
*/
public CompletableFuture<List<TaskItemModel>> getTaskList() {
return CompletableFuture.supplyAsync(() -> {
List<TaskCacheEntity> result = kidShiftDatabase.taskCacheDao().getTaskList();
return TaskCacheConverter.taskCacheEntityListToTaskModelList(result);
});
}
}

View File

@ -0,0 +1,41 @@
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 {
/**
* ChildModelをChildCacheEntityに変換する
* @param childModel ChildModel
* @return ChildCacheEntity
*/
public static ChildCacheEntity childModelToChildCacheEntity(ChildModel childModel) {
ChildCacheEntity entity = new ChildCacheEntity();
entity.id = childModel.getId();
entity.name = childModel.getName();
return entity;
}
/**
* ChildCacheEntityをChildModelに変換する
* @param childList ChildModelリスト
* @return ChildCacheEntityリスト
*/
public static List<ChildCacheEntity> childModelListToChildCacheEntityList(List<ChildModel> childList) {
return childList.stream().map(ChildCacheConverter::childModelToChildCacheEntity).collect(Collectors.toList());
}
/**
* ChildCacheEntityをChildModelに変換する
* @param entity ChildCacheEntity
* @return ChildModel
*/
public static ChildModel childCacheEntityToChildModel(ChildCacheEntity entity) {
return new ChildModel(entity.id, entity.name);
}
}

View File

@ -0,0 +1,53 @@
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 {
/**
* TaskItemModelをTaskCacheEntityに変換する
* @param taskModel TaskItemModel
* @return TaskCacheEntity
*/
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;
}
/**
* TaskCacheEntityをTaskItemModelに変換する
* @param taskList TaskItemModelリスト
* @return TaskCacheEntityリスト
*/
public static List<TaskCacheEntity> taskModelListToTaskCacheEntityList(List<TaskItemModel> taskList) {
return taskList.stream().map(TaskCacheConverter::taskModelToTaskCacheEntity).collect(Collectors.toList());
}
/**
* TaskCacheEntityをTaskItemModelに変換する
* @param entity TaskCacheEntity
* @return TaskItemModel
*/
public static TaskItemModel taskCacheEntityToTaskModel(TaskCacheEntity entity) {
return new TaskItemModel(entity.id, entity.name, entity.iconEmoji, entity.reward, null);
}
/**
* TaskCacheEntityリストをTaskItemModelリストに変換する
* @param entityList TaskCacheEntityリスト
* @return TaskItemModelリスト
*/
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

@ -0,0 +1,61 @@
package one.nem.kidshift.feature.debug;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.kidshift.data.ChildData;
@AndroidEntryPoint
public class DebugDialogCallFragment extends Fragment {
@Inject
ChildData childData;
private FragmentManager fragmentManager;
public DebugDialogCallFragment() {
// 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_dialog_call, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LayoutInflater inflater = requireActivity().getLayoutInflater();
View view1 =inflater.inflate(R.layout.fragment_debug_dialog_view,null);
int loginCode = childData.issueLoginCode("543256").join();
TextView loginCodeTextView = view1.findViewById(R.id.loginCode);
new StringBuilder(Integer.toString(loginCode)).insert(3,"-");
loginCodeTextView.setText(
new StringBuilder(Integer.toString(loginCode)).insert(3,"-"));
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle("ログインコード")
.setView(view1)
.setNeutralButton("閉じる",null);
builder.create();
view.findViewById(R.id.callDialogButton).setOnClickListener(v -> {
// ここに書く
builder.show();
});
}
}

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

@ -34,6 +34,7 @@ public class DebugTopMenuFragment extends Fragment {
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));
debugMenuListItems.add(new DebugMenuListItemModel("Dialog call", "ダイアログの表示テストをします", R.id.action_debugTopMenuFragment_to_debugDialogCallFragment, true));
DebugMenuListItemAdapter adapter = new DebugMenuListItemAdapter(debugMenuListItems);
recyclerView.setAdapter(adapter);

View File

@ -0,0 +1,18 @@
<?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=".DebugDialogCallFragment" >
<Button
android:id="@+id/callDialogButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ダイアログ表示"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/loginCode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="30dp"
android:paddingBottom="25dp"
android:textAppearance="@style/TextAppearance.AppCompat.Display3" />
</LinearLayout>
</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

@ -19,6 +19,9 @@
<action
android:id="@+id/action_debugTopMenuFragment_to_debugTempRegisterFragment"
app:destination="@id/debugTempRegisterFragment" />
<action
android:id="@+id/action_debugTopMenuFragment_to_debugDialogCallFragment"
app:destination="@id/debugDialogCallFragment" />
</fragment>
<fragment
android:id="@+id/debugDebugConsoleFragment"
@ -35,4 +38,9 @@
android:name="one.nem.kidshift.feature.debug.DebugTempRegisterFragment"
android:label="fragment_debug_temp_register"
tools:layout="@layout/fragment_debug_temp_register" />
<fragment
android:id="@+id/debugDialogCallFragment"
android:name="one.nem.kidshift.feature.debug.DebugDialogCallFragment"
android:label="fragment_debug_dialog_call"
tools:layout="@layout/fragment_debug_dialog_call" />
</navigation>

View File

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

View File

@ -41,7 +41,7 @@ public class ChildListAdapter extends RecyclerView.Adapter<ChildListAdapter.Main
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

@ -41,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

@ -6,7 +6,9 @@ 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.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -21,6 +23,7 @@ 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;
@ -37,6 +40,40 @@ public class ParentMainFragment extends Fragment {
public ParentMainFragment() {
// Required empty public constructor
}
private void dataRefresh(){
SwipeRefreshLayout swipeRefreshLayout = requireView().findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setRefreshing(true);
RecyclerView recyclerView =requireView().findViewById(R.id.main_recycle_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
List<TaskItemModel> task = taskData.getTasks(new TaskItemModelCallback() {
@Override
public void onUnchanged() {
// TODO
}
@Override
public void onUpdated(List<TaskItemModel> taskItem) {
// TODO
}
@Override
public void onFailed(String message) {
// TODO
}
}).join();
RecyclerView.Adapter mainAdapter = new ParentAdapter(task);
recyclerView.setAdapter(mainAdapter);
swipeRefreshLayout.setRefreshing(false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@ -45,20 +82,6 @@ public class ParentMainFragment extends Fragment {
//タスク一覧表示
View view = inflater.inflate(R.layout.fragment_parent_main, container, false);
RecyclerView recyclerView = view.findViewById(R.id.main_recycle_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
List<TaskItemModel> task = taskData.getTasks().join();
RecyclerView.Adapter mainAdapter = new ParentAdapter(task);
recyclerView.setAdapter(mainAdapter);
//お手伝い追加ダイアログ
LayoutInflater inflater1 = requireActivity().getLayoutInflater();
View view1 = inflater1.inflate(R.layout.add_task_list_dialog,null);
@ -71,7 +94,9 @@ public class ParentMainFragment extends Fragment {
RecyclerView.LayoutManager layoutManager1 = new LinearLayoutManager(getContext());
recyclerView1.setLayoutManager(layoutManager1);
List<ChildModel> child = childData.getChildList();
ksLogger.debug("子供一覧取得開始");
List<ChildModel> child = childData.getChildList().join();
ksLogger.debug("子供一覧取得完了");
RecyclerView.Adapter mainAdapter1 = new ChildListAdapter(child);
recyclerView1.setAdapter(mainAdapter1);
@ -94,5 +119,10 @@ public class ParentMainFragment extends Fragment {
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Do something...
SwipeRefreshLayout swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(()->{
dataRefresh();
});
}
}

View File

@ -1,23 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<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:id="@+id/main"
android:id="@+id/swipe_refresh_layout"
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"
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:orientation="vertical">
</LinearLayout>
<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" />
</LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -32,7 +32,7 @@ dependencies {
implementation libs.material
implementation libs.navigation.fragment
implementation libs.navigation.ui
implementation libs.swiperefreshlayout
implementation libs.androidx.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

@ -28,11 +28,6 @@ import one.nem.kidshift.model.ChildModel;
import one.nem.kidshift.model.ParentModel;
import one.nem.kidshift.model.callback.ParentModelCallback;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingMainFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class SettingMainFragment extends Fragment {
@ -42,67 +37,46 @@ public class SettingMainFragment extends Fragment {
@Inject
ParentData parentData;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public SettingMainFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SettingMainFragment.
*/
// TODO: Rename and change types and number of parameters
public static SettingMainFragment newInstance(String param1, String param2) {
SettingMainFragment fragment = new SettingMainFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_setting_main, container, false);
TextView username = view.findViewById(R.id.username);
TextView useradress = view.findViewById(R.id.useradress);
try {
CompletableFuture<ParentModel> completableFuture = parentData.getParent(new ParentModelCallback() {
@Override
public void onUnchanged() {
// TODO
//かわってないとき
}
@Override
public void onUpdated(ParentModel parent) {
// TODO
//変わってたら
requireActivity().runOnUiThread(() -> {
username.setText(parent.getName());
useradress.setText(parent.getEmail());
});
}
@Override
public void onFailed(String message) {
// TODO
requireActivity().runOnUiThread(()->{
username.setText("アドレスを設定してください。");
});
}
});
@ -112,7 +86,7 @@ public class SettingMainFragment extends Fragment {
- 結果に応じてRecyclerViewを更新する
- キャッシュ受け取りの時にjoinでUIスレッドをブロックしないように
- Placeholderの表示?
- エラーハンドリング
- エラーハンドリング try catch文
- onFailed時にそれを通知
*/
@ -120,24 +94,17 @@ public class SettingMainFragment extends Fragment {
if (parent == null) {
parent = new ParentModel(); // Workaround非ログインデバッグ用
parent.setDisplayName("親の名前");
parent.setName("親の名前");
parent.setEmail("親のアドレス");
}
View view = inflater.inflate(R.layout.fragment_setting_main, container, false);
// Pull-to-refreshスワイプで更新
SwipeRefreshLayout swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_layout);
ParentModel finalParent = parent;
swipeRefreshLayout.setOnRefreshListener(() ->{
TextView username = view.findViewById(R.id.username);
TextView useradress = view.findViewById(R.id.useradress);
username.setText(parent.getDisplayName());
useradress.setText(parent.getEmail());
username.setText(finalParent.getName());
useradress.setText(finalParent.getEmail());
RecyclerView recyclerView = view.findViewById(R.id.childrecyclerview);
@ -146,7 +113,7 @@ public class SettingMainFragment extends Fragment {
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
List<ChildModel> child = childData.getChildList();
List<ChildModel> child = childData.getChildList().join();
RecyclerView.Adapter mainAdapter = new SettingAdapter(child);
recyclerView.setAdapter(mainAdapter);
@ -155,36 +122,33 @@ public class SettingMainFragment extends Fragment {
});
//RecyclerViewの処理
TextView username = view.findViewById(R.id.username);
TextView useradress = view.findViewById(R.id.useradress);
username.setText(parent.getName());
useradress.setText(parent.getEmail());
} catch (Exception e) {
//
}
RecyclerView recyclerView = view.findViewById(R.id.childrecyclerview);
username.setText(parent.getDisplayName());
useradress.setText(parent.getEmail());
recyclerView.setHasFixedSize(true);
RecyclerView recyclerView = view.findViewById(R.id.childrecyclerview);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
List<ChildModel> child = childData.getChildList().join();
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
RecyclerView.Adapter mainAdapter = new SettingAdapter(child);
recyclerView.setAdapter(mainAdapter);
List<ChildModel> child = childData.getChildList().join();
LayoutInflater inflater1 = requireActivity().getLayoutInflater();
View view1 = inflater1.inflate(R.layout.add_child_list_dialog,null);
RecyclerView.Adapter mainAdapter = new SettingAdapter(child);
recyclerView.setAdapter(mainAdapter);
//子供の名前追加のダイアログ
LayoutInflater inflater1 = requireActivity().getLayoutInflater();
View view1 = inflater1.inflate(R.layout.add_child_list_dialog,null);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle("お子様の名前を入力してください。")
.setView(view1)
.setPositiveButton("追加",null)
.setNeutralButton("閉じる",null);
builder.create();
//子供の名前追加のダイアログ
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle("お子様の名前を入力してください。")
.setView(view1)
.setPositiveButton("追加",null)
.setNeutralButton("閉じる",null);
builder.create();
view.findViewById(R.id.addchildname).setOnClickListener(v -> {
builder.show();

View File

@ -1,6 +1,7 @@
[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"
@ -11,11 +12,13 @@ constraintlayout = "2.1.4"
nav = "2.7.7"
swiperefreshlayout = "1.1.0"
retrofit = "2.11.0"
room = "2.5.0"
room = "2.6.1"
[libraries]
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
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" }
@ -29,11 +32,11 @@ 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" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }

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,102 +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;
}
public TaskItemModel() {
}
// 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;
}
}