Skip to content

【リファクタリング】現状のソースコードをよりわかりやすい形にメソッド分割を実施#5

Open
gobotan wants to merge 4 commits intomasterfrom
work
Open

【リファクタリング】現状のソースコードをよりわかりやすい形にメソッド分割を実施#5
gobotan wants to merge 4 commits intomasterfrom
work

Conversation

@gobotan
Copy link
Member

@gobotan gobotan commented Oct 28, 2024

大まかにリファクタ
動作確認は行っていないが現状コードが分かりづらいためまずは読める状態にする

@Alpha9n
Copy link

Alpha9n commented Oct 29, 2024

#4

free driveになっていたところをfoofle driveに変更
Copy link

@yui-Kitamura yui-Kitamura left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commandパッケージまで見ました

@gobotan gobotan requested review from yui-Kitamura and removed request for tererun October 30, 2024 12:33
@gobotan gobotan requested review from Alpha9n and yui-Kitamura and removed request for Alpha9n and yui-Kitamura October 30, 2024 12:42
@gobotan
Copy link
Member Author

gobotan commented Oct 30, 2024

レビューを複数人に依頼しようとしたら勝手に外しやがるので一旦猫さんをレビュワーに指定

@Alpha9n Alpha9n linked an issue Oct 30, 2024 that may be closed by this pull request
Copy link

@yui-Kitamura yui-Kitamura left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

昨日の10%くらいの熱量で見ました

@gobotan gobotan requested a review from yui-Kitamura November 5, 2024 13:52
<groupId>ga.ganma</groupId>
<artifactId>foofledrive</artifactId>
<version>0.7.9β</version>
<version>1.0.0</version>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

targetフォルダが上がって来てるけど含まれているjarビルドが旧のまま

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

既存コードの可読性改善を目的に、処理のメソッド分割・クラス分割、旧実装の整理(FilerelationFileRelationUtils 等)を進めつつ、依存バージョンとアプリ版本を更新するPRです。

Changes:

  • コマンド/GUIイベント/支払い処理のリファクタ(責務分離・メソッド抽出・クラス置換)
  • プレイヤーデータ/プラン周りの整理(旧 plan/Playerdata を deprecated 化、新 FoofleDrivePlan/PlayerDriveData・変換クラスを追加)
  • バージョン更新(plugin/pom)と Spigot API・Java 設定更新、および旧 ga.ganma.ender ツリーの削除

Reviewed changes

Copilot reviewed 34 out of 63 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst ビルド生成物(target配下)差分
target/maven-archiver/pom.properties ビルド生成物(Maven生成)差分
target/classes/plugin.yml ビルド生成物(コンパイル後成果物)差分
target/classes/ga/ganma/foofledrive/playerdata/Playerdata.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/plan.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/inventoryRelation/InventoryEncoder.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/inventoryRelation/InventoryAPI.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/inventoryRelation/InventoryAPI$1.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/economy/Economy.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/economy/Economy$1.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/command/Subplan.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/command/Subopen.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/command/CommandMain.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/bukkitRunnable/Runnable.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/Listener/GetEvent.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/Listener/GetEvent$1.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/Listener/GUIEvent.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/Foofledrive.class ビルド生成物(.class)追加
target/classes/ga/ganma/foofledrive/Filerelation.class ビルド生成物(.class)追加
src/main/java/ga/ganma/foofledrive/playerdata/Playerdata.java 旧データクラスのdeprecated化・フィールドfinal化等
src/main/java/ga/ganma/foofledrive/playerdata/PlayerDriveData.java 新データクラス追加
src/main/java/ga/ganma/foofledrive/plan.java 旧プラン enum のdeprecated化・整形
src/main/java/ga/ganma/foofledrive/inventoryRelation/InventoryEncoder.java インベントリのシリアライズ/デシリアライズの整形
src/main/java/ga/ganma/foofledrive/inventoryRelation/InventoryAPI.java プラン変更処理の再構成(メソッド抽出・命名変更)
src/main/java/ga/ganma/foofledrive/economy/Economy.java 支払い処理の共通化(processPayment/logAndNotify/getPlanCost)
src/main/java/ga/ganma/foofledrive/command/Subplan.java 旧クラス削除
src/main/java/ga/ganma/foofledrive/command/Subopen.java 旧クラス削除
src/main/java/ga/ganma/foofledrive/command/SubmitPlan.java 旧 Subplan 相当の新クラス追加
src/main/java/ga/ganma/foofledrive/command/SubmitOpen.java 旧 Subopen 相当の新クラス追加
src/main/java/ga/ganma/foofledrive/command/CommandMain.java コマンド処理の分割・GUI生成の整理
src/main/java/ga/ganma/foofledrive/bukkitRunnable/Runnable.java 定期タスク処理の分割・フォルダ参照方法の変更
src/main/java/ga/ganma/foofledrive/bizlogic/convert/ConvertPlayerData.java 旧 Playerdata → 新 PlayerDriveData の変換追加
src/main/java/ga/ganma/foofledrive/Listener/GetEvent.java Join/Closeイベント処理の分割・FileRelationUtils移行
src/main/java/ga/ganma/foofledrive/Listener/GUIEvent.java GUIクリック処理の分割・契約確認フローの整理
src/main/java/ga/ganma/foofledrive/Foofledrive.java config読み込み抽出・コマンドExecutor再利用・フィールド名変更
src/main/java/ga/ganma/foofledrive/FoofleDrivePlan.java 新プラン enum 追加
src/main/java/ga/ganma/foofledrive/Filerelation.java 旧ファイル操作クラス削除
src/main/java/ga/ganma/foofledrive/FileRelationUtils.java 新ファイル操作ユーティリティ追加(旧実装置換)
src/main/java/ga/ganma/ender/playerdata/Playerdata.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/plan.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/inventoryRelation/InventoryEncoder.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/inventoryRelation/InventoryAPI.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/command/Subplan.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/command/Subopen.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/command/CommandMain.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/Listener/GetEvent.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/Listener/GUIEvent.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/Filerelation.java 旧(別パッケージ)実装削除
src/main/java/ga/ganma/ender/Endercloud.java 旧(別パッケージ)プラグイン本体削除
pom.xml バージョン更新・Java/Spigot APIバージョン更新
foofledrive.iml IntelliJモジュール設定差分
.idea/vcs.xml IntelliJ設定追加
.idea/uiDesigner.xml IntelliJ設定追加
.idea/modules.xml IntelliJ設定追加
.idea/misc.xml IntelliJ設定追加(JDK設定含む)
.idea/jarRepositories.xml IntelliJ設定追加
.idea/encodings.xml IntelliJ設定追加
.idea/compiler.xml IntelliJ設定追加
.idea/.gitignore IntelliJ配下のgitignore追加
.gitignore /target/ のignore追加
Files not reviewed (8)
  • .idea/.gitignore: Language not supported
  • .idea/compiler.xml: Language not supported
  • .idea/encodings.xml: Language not supported
  • .idea/jarRepositories.xml: Language not supported
  • .idea/misc.xml: Language not supported
  • .idea/modules.xml: Language not supported
  • .idea/uiDesigner.xml: Language not supported
  • .idea/vcs.xml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +28
public static void changePlan(OfflinePlayer player, plan plan) {
Inventory inv = createInventoryForPlan(plan);
ItemStack[] is = trimInventoryItems(FileRelationUtils.readFile(player).getInv().getStorageContents(), plan);

public static boolean planchange(Player player, plan plan){
Inventory inv = null;
ItemStack[] is = null;
switch (plan){
case FREE:
inv = Bukkit.createInventory(null,9,"foofle drive");
is = Filerelation.readFile(player).getInv().getStorageContents();
if(is.length > 9){
int a = is.length;
List<ItemStack> isl = new ArrayList<>(Arrays.asList(is));
isl.subList(9,a).clear();
ItemStack[] array = new ItemStack[isl.size()];
int i = 0;
for (ItemStack ist : isl){
array[i] = ist;
i += 1;
}
is = array;
}
break;
inv.setStorageContents(is);
Foofledrive.econ.withdrawPlayer(player, Economy.getPlanCost(FileRelationUtils.readFile(player).getPlan()));
Playerdata pd = new Playerdata(player, inv, plan);
pd.setFinish(Calendar.getInstance());
FileRelationUtils.createFile(pd);
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changePlan(OfflinePlayer, plan) always withdraws money (withdrawPlayer) even though it’s also used by Economy.processPayment when the player does not have enough balance (downgrade to FREE). With the current refactor, online players also hit this overload (because processPayment takes OfflinePlayer), so insufficient-funds downgrades will still withdraw and can push balances negative. Consider removing the withdrawal from this overload, or splitting the responsibilities into (1) inventory resize + file update and (2) charging, and ensure the insufficient-funds path does not charge.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to 34
public static void changePlan(OfflinePlayer player, plan plan) {
Inventory inv = createInventoryForPlan(plan);
ItemStack[] is = trimInventoryItems(FileRelationUtils.readFile(player).getInv().getStorageContents(), plan);

public static boolean planchange(Player player, plan plan){
Inventory inv = null;
ItemStack[] is = null;
switch (plan){
case FREE:
inv = Bukkit.createInventory(null,9,"foofle drive");
is = Filerelation.readFile(player).getInv().getStorageContents();
if(is.length > 9){
int a = is.length;
List<ItemStack> isl = new ArrayList<>(Arrays.asList(is));
isl.subList(9,a).clear();
ItemStack[] array = new ItemStack[isl.size()];
int i = 0;
for (ItemStack ist : isl){
array[i] = ist;
i += 1;
}
is = array;
}
break;
inv.setStorageContents(is);
Foofledrive.econ.withdrawPlayer(player, Economy.getPlanCost(FileRelationUtils.readFile(player).getPlan()));
Playerdata pd = new Playerdata(player, inv, plan);
pd.setFinish(Calendar.getInstance());
FileRelationUtils.createFile(pd);
}

case LIGHT:
inv = Bukkit.createInventory(null,18,"foofle drive");
is = Filerelation.readFile(player).getInv().getStorageContents();
if(is.length >= 19){
int a = is.length;
List<ItemStack> isl = new ArrayList<>(Arrays.asList(is));
isl.subList(18,a).clear();
ItemStack[] array = new ItemStack[isl.size()];
int i = 0;
for (ItemStack ist : isl){
array[i] = ist;
i += 1;
}
is = array;
}
break;
case MIDDLE:
inv = Bukkit.createInventory(null,27,"foofle drive");
is = Filerelation.readFile(player).getInv().getStorageContents();
if(is.length >= 28){
int a = is.length;
List<ItemStack> isl = new ArrayList<>(Arrays.asList(is));
isl.subList(27,a).clear();
ItemStack[] array = new ItemStack[isl.size()];
int i = 0;
for (ItemStack ist : isl){
array[i] = ist;
i += 1;
}
is = array;
}
break;
public static boolean changePlan(Player player, plan plan) {
Inventory inv = createInventoryForPlan(plan);
ItemStack[] is = trimInventoryItems(FileRelationUtils.readFile(player).getInv().getStorageContents(), plan);

Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both changePlan(...) methods call FileRelationUtils.readFile(...) and immediately dereference it (.getInv() / .getPlan()). If the player data file is missing or unreadable, readFile(...) returns null and this will throw. Either enforce non-null by creating defaults, or add an explicit null check with a clear error/log before dereferencing.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +28
public static void paymoney(Player p) {
processPayment(p, FileRelationUtils.readFile(p), Foofledrive.econ.getBalance(p));
}

public static int getplanmoney(plan plan){
switch (plan){
case FREE:
return Foofledrive.configamout[0];
case LIGHT:
return Foofledrive.configamout[1];
case MIDDLE:
return Foofledrive.configamout[2];
case LARGE:
return Foofledrive.configamout[3];
}
public static void paymoney(OfflinePlayer p) {
processPayment(p, FileRelationUtils.readFile(p), Foofledrive.econ.getBalance(p));
}

return 0;
}
private static void processPayment(OfflinePlayer p, Playerdata pd, double bal) {
if (pd.getFinish() != null && pd.getFinish().before(Calendar.getInstance())) {
int planCost = getPlanCost(pd.getPlan());
if (bal >= planCost) {
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

paymoney(...) passes FileRelationUtils.readFile(...) directly into processPayment without checking for null, but readFile(...) returns null when the file doesn’t exist or can’t be read. processPayment then calls pd.getFinish() and will throw. Add a null guard (and possibly create a default Playerdata / log + return) before dereferencing pd.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +37
private static void processPayment(OfflinePlayer p, Playerdata pd, double bal) {
if (pd.getFinish() != null && pd.getFinish().before(Calendar.getInstance())) {
int planCost = getPlanCost(pd.getPlan());
if (bal >= planCost) {
Foofledrive.econ.withdrawPlayer(p, planCost);
logAndNotify(p, pd.getPlan() + "プランの料金を支払いました。", "[foofle drive]料金の支払いをしました。");
pd.setFinish(Calendar.getInstance());
FileRelationUtils.createFile(pd);
} else {
InventoryAPI.changePlan(p, plan.FREE);
logAndNotify(p, "お金が足りないため、自動的にfreeプランへ移行しました。", "[foofle drive]お金が足りないため、自動的にfreeプランへ移行しました。");
logAndNotify(p, "その際、2段目以降にあるアイテムを全消去しました。", "[foofle drive]その際、2段目以降にあるアイテムを全消去しました。");
}
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the insufficient-funds branch, InventoryAPI.changePlan(p, plan.FREE) is invoked with p typed as OfflinePlayer. For online players, this will call the OfflinePlayer overload (because processPayment takes OfflinePlayer), which currently performs a withdrawal and will likely charge even though the player cannot afford the plan. If you keep separate overloads, consider explicitly calling the Player overload when p instanceof Player and ensuring the downgrade path never withdraws.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +12
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="22" project-jdk-type="JavaSDK" />
</project> No newline at end of file
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDE-specific project files (.idea/*, *.iml) are included in this PR. These are usually developer-local settings and tend to cause churn across environments. If the repository doesn’t explicitly require committing IntelliJ project metadata, consider removing these files from the PR and adding appropriate ignore rules instead.

Suggested change
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="22" project-jdk-type="JavaSDK" />
</project>
<!--
This file previously contained IDE-specific IntelliJ configuration and
is intentionally left empty to avoid committing developer-local settings.
-->

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +61
String fileName = playerDataFile.getName();
String uuidString = fileName.replace(FileRelationUtils.DATA_FILE_EXTENTION, "");
UUID playerUUID = UUID.fromString(uuidString);
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerUUID);
Economy.paymoney(offlinePlayer);
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

processPlayerDataFile assumes every file in the playerdata folder is a valid UUID + .dat. If any other file exists (backup files, temp files, OS metadata), UUID.fromString(...) will throw and may abort the entire scheduled task. Consider validating the filename (e.g., endsWith(DATA_FILE_EXTENTION)) and catching IllegalArgumentException to skip invalid entries.

Suggested change
String fileName = playerDataFile.getName();
String uuidString = fileName.replace(FileRelationUtils.DATA_FILE_EXTENTION, "");
UUID playerUUID = UUID.fromString(uuidString);
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerUUID);
Economy.paymoney(offlinePlayer);
// プレイヤーデータファイルのみを対象とする(ディレクトリや拡張子が異なるファイルは無視)
if (playerDataFile == null || !playerDataFile.isFile()) {
return;
}
String fileName = playerDataFile.getName();
if (!fileName.endsWith(FileRelationUtils.DATA_FILE_EXTENTION)) {
return;
}
String uuidString = fileName.replace(FileRelationUtils.DATA_FILE_EXTENTION, "");
try {
UUID playerUUID = UUID.fromString(uuidString);
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerUUID);
Economy.paymoney(offlinePlayer);
} catch (IllegalArgumentException e) {
// UUID 形式でないファイル名はスキップする
plugin.getLogger().warning("[FoofleDrive] Invalid player data filename (not a UUID): " + fileName);
}

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +20
return new PlayerDriveData(playerdata.getMcid(), playerdata.getInv(), ConvertPlan(playerdata.getPlan()));
}

private FoofleDrivePlan ConvertPlan(plan plan) {
return switch (plan) {
case FREE -> FoofleDrivePlan.FREE;
case LIGHT -> FoofleDrivePlan.LIGHT;
case MIDDLE -> FoofleDrivePlan.MIDDLE;
case LARGE -> FoofleDrivePlan.LARGE;
};
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConvertPlan is named with an initial capital letter, which is inconsistent with Java method naming conventions and the surrounding code style (lowerCamelCase). Rename to convertPlan (and update the call site) to keep naming consistent and improve readability.

Copilot uses AI. Check for mistakes.
Comment on lines 14 to +28
@@ -24,8 +24,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>8</source>
<target>8</target>
<source>16</source>
<target>16</target>
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Project is set to compile with Java 16 (<source>/<target>16), but spigot-api is updated to 1.20.2-R0.1-SNAPSHOT (Minecraft 1.20.x typically requires Java 17+ at runtime and for compilation). This mismatch is likely to cause compilation/runtime failures. Consider bumping the compiler/source/target (and java.version) to 17 to match the Spigot API baseline.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to 20
ga\ganma\foofledrive\FoofleDrivePlan.class
ga\ganma\foofledrive\economy\Economy$1.class
ga\ganma\foofledrive\Listener\GetEvent$1.class
ga\ganma\foofledrive\Filerelation.class
ga\ganma\foofledrive\command\CommandMain.class
ga\ganma\foofledrive\command\Subopen.class
ga\ganma\foofledrive\bizlogic\convert\ConvertPlayerData.class
ga\ganma\foofledrive\Listener\GUIEvent.class
ga\ganma\foofledrive\bizlogic\convert\ConvertPlayerData$1.class
ga\ganma\foofledrive\bukkitRunnable\Runnable.class
ga\ganma\foofledrive\command\Subplan.class
ga\ganma\foofledrive\Listener\GetEvent.class
ga\ganma\foofledrive\playerdata\Playerdata.class
ga\ganma\foofledrive\playerdata\PlayerDriveData.class
ga\ganma\foofledrive\inventoryRelation\InventoryEncoder.class
ga\ganma\foofledrive\Foofledrive.class
ga\ganma\foofledrive\inventoryRelation\InventoryAPI$1.class
ga\ganma\foofledrive\economy\Economy.class
ga\ganma\foofledrive\Listener\GUIEvent.class
ga\ganma\foofledrive\inventoryRelation\InventoryAPI.class
ga\ganma\foofledrive\Listener\GUIEvent$1.class
ga\ganma\foofledrive\bukkitRunnable\Runnable.class
ga\ganma\foofledrive\command\Subplan.class
ga\ganma\foofledrive\Listener\GetEvent.class
ga\ganma\foofledrive\plan.class
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR includes build outputs under target/ (compiled .class files, Maven status files, generated plugin.yml, etc.). These artifacts are machine-generated and should not be committed; they also make reviews noisy and can cause merge conflicts. Please remove the committed target/ contents from git history for this PR and rely on the new /target/ entry in .gitignore to keep them out going forward.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +59
File folder = PLAYERDATA_FOLDER.toFile();
folder.mkdir();
File file = new File(PLAYERDATA_FOLDER + e.getMcid().toString() + ".dat");

Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createFile builds the target file as new File(PLAYERDATA_FOLDER + e.getMcid().toString() + ".dat"), which again concatenates paths without a separator. This will write to an unexpected location (and likely break reads). Build the file via PLAYERDATA_FOLDER.resolve(...) / new File(folder, filename) to ensure a valid path.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[foofleDrive] リファクタリング

4 participants