Compare commits

..
Author SHA1 Message Date
r-ca 1a80d00319 フォルダを開けるように WIP 2024-01-22 13:29:40 +09:00
r-ca 3f893fc580 インタフェース修正 2024-01-22 12:16:56 +09:00
r-ca 225058f836 壊れたImportを修正 2024-01-22 12:11:06 +09:00
r-ca c23b92d386 リネーム 2024-01-22 12:10:45 +09:00
ろむねこ 41e5ab2349 Merge pull request #92 from lacerta-doc/feature/library/create_folder
Feature/library/create folder
2024-01-22 12:09:26 +09:00
r-ca 580e79b03a Revert "InputDialogのWrapper作成 WIP"
This reverts commit 301fab8024.
2024-01-22 12:07:52 +09:00
r-ca 301fab8024 InputDialogのWrapper作成 WIP 2024-01-22 12:07:46 +09:00
r-ca 281238a38e 作成するフォルダの名前を指定できるように 2024-01-22 12:07:07 +09:00
r-ca 81fa259985 フォルダを作成できるように 2024-01-22 11:55:38 +09:00
r-ca b2c6085933 パースメソッドを追加 2024-01-22 11:54:39 +09:00
r-ca caf3a0dd34 絶対パスを正常に解決できるように 2024-01-22 11:50:29 +09:00
r-ca c4e10b9487 絶対パスを正常に解決できるように 2024-01-22 11:49:45 +09:00
r-ca b05ee22c29 createFolder関数実装 2024-01-22 11:34:03 +09:00
ろむねこ 839433dbb1 Merge pull request #91 from lacerta-doc/test
Test
2024-01-22 11:28:31 +09:00
r-ca 153242ef66 WIP 2024-01-22 11:27:56 +09:00
r-ca 05997eafe1 フラグメントからToolBarのアイテムを制御できるようにした 2024-01-22 11:26:11 +09:00
r-ca d6f4885b4a iroiro 2024-01-22 11:08:48 +09:00
r-ca 0b33c60a5a ToolBar削除 2024-01-22 11:04:21 +09:00
r-ca ad3a600e8c ToolBar削除 2024-01-22 11:03:44 +09:00
r-ca 50dfb9be8b ToolBar削除 2024-01-22 11:03:14 +09:00
r-ca fafb996453 ToolBar削除 2024-01-22 11:02:08 +09:00
r-ca e1129bc009 ToolBar削除 2024-01-22 11:02:01 +09:00
r-ca 5752e3285b ToolBar削除 2024-01-22 11:01:57 +09:00
r-ca a2ed78dfb8 プロパティ追加 2024-01-22 10:58:52 +09:00
r-ca 0eadc3c3d5 レイアウト移植 2024-01-22 10:56:19 +09:00
r-ca 6d0b24eb70 レイアウト移植 WIP 2024-01-22 10:54:51 +09:00
ろむねこ 9da41e73aa Merge pull request #90 from lacerta-doc/feature/library/add
Feature/library/add
2024-01-22 10:32:47 +09:00
r-ca 01f28ecd4d ドキュメントを正常に取得できるように 2024-01-22 10:31:26 +09:00
r-ca 2f3a331527 FeatureSwitch切り替え 2024-01-22 10:31:09 +09:00
r-ca 9496c3efbb 依存関係追加 2024-01-22 10:23:08 +09:00
r-ca 93b833f7a9 nullの場合は0を返すように 2024-01-22 10:20:38 +09:00
r-ca 3130be88be getLibraryPage実装WIP 2024-01-22 10:12:21 +09:00
r-ca bb7b628d2f 壊れた実装を削除 2024-01-22 10:00:17 +09:00
r-ca 5f9ea732cf 実装 WIP 2024-01-22 01:24:55 +09:00
r-ca 42f6bc17d3 レイアウトコピー 2024-01-22 01:21:10 +09:00
r-ca 1c6878c3fd コピー 2024-01-22 01:21:00 +09:00
r-ca b5beb7cc15 Adapter修正 2024-01-22 01:20:55 +09:00
r-ca c6fb06ffe2 レイアウトコピー 2024-01-22 01:17:57 +09:00
ろむねこ 95d808dc75 Merge pull request #89 from lacerta-doc/feature/switch
Feature/switch
2024-01-22 01:12:16 +09:00
r-ca b4135f9ec0 リファクタリング 2024-01-21 20:37:04 +09:00
r-ca a62d748c72 ログ追加 2024-01-21 20:35:20 +09:00
r-ca ea0b1a7665 初回起動の場合に初期化処理としてデフォルト値を書き込むように 2024-01-21 20:34:47 +09:00
r-ca 4cfc87a40b 初回起動フラグ追加 2024-01-21 20:32:29 +09:00
r-ca 40a0d08a1f デバッグメニューを無効に 2024-01-21 20:28:56 +09:00
r-ca fd850651b3 実装を単純にした 2024-01-21 20:28:33 +09:00
r-ca ec633a7238 FeatureSwitch実装仮 2024-01-21 20:16:38 +09:00
r-ca e10207959b Merge branch 'develop' into feature/switch 2024-01-21 19:53:55 +09:00
ろむねこ c46ec70d97 Merge pull request #88 from lacerta-doc/fix_versions
compileSDKバージョンを34にアップデート
2024-01-21 19:53:25 +09:00
r-ca 871dfad6c4 compileSDKバージョンを34にアップデート 2024-01-21 19:48:30 +09:00
r-ca 676a0e2772 WIP 2024-01-21 19:45:02 +09:00
r-ca d9d22198d5 FeatureSwitch実装WIP 2024-01-21 19:18:43 +09:00
r-ca 2dc3407217 FeatureSwitchのOverrideができるように 2024-01-21 19:11:25 +09:00
r-ca d40f61928c 依存関係追加 2024-01-21 19:10:03 +09:00
r-ca 19ff824591 Enum追加 2024-01-21 19:09:37 +09:00
r-ca ec7adbe331 SharedPrefUtilsメソッド追加 2024-01-21 19:07:33 +09:00
r-ca af626f4dc0 依存関係追加 2024-01-21 19:04:01 +09:00
r-ca acea8ba27d Revert "依存関係追加"
This reverts commit 8f1849591d.
2024-01-21 19:03:45 +09:00
r-ca 8f1849591d 依存関係追加 2024-01-21 19:02:33 +09:00
r-ca 882207682f FeatureSwitchクラス作成 WIP 2024-01-21 18:56:15 +09:00
ろむねこ 0be12e73a8 Merge pull request #87 from lacerta-doc/component/viewer/1
ビューワー実装 WIP
2024-01-21 18:49:50 +09:00
r-ca f0b4cc556e 正常に画像を取得できるように 2024-01-21 18:45:51 +09:00
r-ca 8c71dedd85 XmlMetaのパース処理を修正 2024-01-21 18:44:26 +09:00
r-ca c1151b778c 画像の表示時にアニメーションするように 2024-01-21 17:56:52 +09:00
r-ca 10e3093c53 レイアウト調整 2024-01-21 17:56:07 +09:00
r-ca 9ef49e0226 レイアウト調整 2024-01-21 17:55:51 +09:00
r-ca a8ce70e6d9 レイアウト調整 2024-01-21 17:54:52 +09:00
r-ca 2f9777f1f4 adjustViewBounds 2024-01-21 17:53:56 +09:00
r-ca 0a867051f2 パス修正 2024-01-21 16:43:51 +09:00
r-ca 673918771c XmlMetaを正常に更新できるようにした 2024-01-21 16:36:52 +09:00
r-ca df14850df1 メソッドチェーン対応 2024-01-21 16:34:07 +09:00
r-ca 28cae3fa19 メソッドチェーン対応WIP 2024-01-21 16:33:26 +09:00
r-ca c167d83940 引数変更 2024-01-21 16:28:06 +09:00
r-ca 722a3d8c7b Xmlを保存できるようにした 2024-01-21 16:26:56 +09:00
r-ca d7f22c8e36 nullをキャッチするようにした 2024-01-21 16:15:11 +09:00
r-ca 0da5e8a961 WIP 2024-01-21 15:43:09 +09:00
r-ca c45847ecd2 NavigationComponent廃止 2024-01-21 15:31:06 +09:00
r-ca d6faf8ec16 ナビゲーショングラフに追加 2024-01-21 15:23:51 +09:00
r-ca 3e21b0ea1c Hiltをプラグインとして追加 2024-01-21 15:18:21 +09:00
r-ca a8e15d8e18 リスナに対応するイベントを実装 2024-01-21 15:17:43 +09:00
r-ca 50eeaa03bf 不要な実装を削除 2024-01-21 15:16:29 +09:00
r-ca f5b94e0f6a コンストラクタに追加 2024-01-21 15:16:18 +09:00
r-ca e9145d491c インターフェース作成 2024-01-21 15:15:35 +09:00
r-ca cb662fe1ff WIP 2024-01-21 15:13:53 +09:00
r-ca 8ad3150f33 コールバックインターフェース作成 2024-01-21 15:10:52 +09:00
r-ca 5cc718e35d Setter, コンストラクタ追加 2024-01-21 15:06:48 +09:00
r-ca 0accd4fa79 Merge branch 'develop' into component/viewer/1 2024-01-21 15:04:37 +09:00
ろむねこ 5840c0126e Merge pull request #86 from lacerta-doc/fix/async
非同期化
2024-01-21 15:03:21 +09:00
r-ca 017a2413b6 挿入時にアニメーションが発生するように 2024-01-20 23:51:34 +09:00
r-ca c53c4ed9a1 Debug 2024-01-20 23:51:20 +09:00
r-ca 12ba9234a4 遅れて追加されたアイテムをUIに反映できるように 2024-01-20 23:49:13 +09:00
r-ca aaff0be438 Debug 2024-01-20 23:40:32 +09:00
r-ca 11e32572ef エラー回避(暫定, 廃止予定) 2024-01-20 23:30:14 +09:00
r-ca ce3f9ebfd7 エラー回避(暫定, 廃止予定) 2024-01-20 23:30:09 +09:00
r-ca 1b70b444f2 コンストラクタ追加 2024-01-20 23:23:54 +09:00
r-ca 7214da80fa 仮置きを非同期に 2024-01-20 23:19:20 +09:00
r-ca 4e5aab276a getRecentDocumentを非同期に 2024-01-20 23:17:31 +09:00
r-ca 4ab13508c4 InterfaceをCompletableFutureに変更 2024-01-20 23:08:49 +09:00
r-ca df22a754b7 ProgressDialogをShowしていなかったので修正 2024-01-20 23:07:17 +09:00
r-ca 9efecab4b6 コンストラクタ追加 2024-01-20 23:00:57 +09:00
r-ca 9aea4bb90e LacertaLibraryのスタブを廃止 2024-01-20 23:00:21 +09:00
r-ca 5c17f96d3d ドキュメントを非同期で取得できるようにした WIP 2024-01-20 22:59:00 +09:00
r-ca d47c6d0cc8 修正 2024-01-20 22:40:59 +09:00
r-ca 176160cd8f createDocument修正 2024-01-20 22:40:03 +09:00
r-ca e6a4393b6d 非同期化 2024-01-20 22:39:35 +09:00
r-ca acc5b166d5 CompletableFeatureを使用して処理するように 2024-01-20 22:24:12 +09:00
r-ca 1d2f3345df CompletableFeatureを使用して処理するように 2024-01-20 22:22:59 +09:00
r-ca b63e9a6747 テスト 2024-01-20 17:46:23 +09:00
r-ca 1f8b56bc78 依存関係追加 2024-01-20 17:45:42 +09:00
r-ca dc9a6bfd9b iroiro 2024-01-20 17:43:23 +09:00
r-ca a825ad6a36 アダプタ実装 2024-01-20 17:39:21 +09:00
r-ca dd1be73904 アダプタ作成 WIP 2024-01-20 17:37:26 +09:00
r-ca 7156bc417c モデル作成 2024-01-20 17:35:57 +09:00
r-ca d9c46898ab 依存関係追加 2024-01-20 17:29:24 +09:00
r-ca 19ce9cbd7e レイアウト修正 WIP 2024-01-20 17:27:28 +09:00
r-ca 584556faca レイアウトコピー 2024-01-20 17:26:59 +09:00
r-ca 028ca6303a 引数追加 2024-01-20 17:25:44 +09:00
r-ca 76734de987 引数削除 2024-01-20 17:24:32 +09:00
r-ca 646a97e77b Arg取得 WIP 2024-01-20 17:21:48 +09:00
r-ca 1aa41eb638 依存関係追加 2024-01-20 17:19:50 +09:00
r-ca 2a34100bf2 NavHost追加 2024-01-20 17:15:39 +09:00
r-ca 5d33d188bd ComponentViewerTopFragment作成 2024-01-20 17:13:27 +09:00
r-ca 8343ba9c2d 依存関係追加 2024-01-20 17:11:44 +09:00
r-ca 95cbfdf42c ナビゲーショングラフ作成 2024-01-20 17:10:30 +09:00
r-ca 7e72cbef54 アクティビティ作成 2024-01-20 17:06:28 +09:00
ろむねこ a7642795ca Merge pull request #85 from lacerta-doc/feature/settings/create
設定画面の骨組みを作成
2024-01-20 16:31:49 +09:00
r-ca f392991988 アニメーションのDurationを変更 2024-01-20 16:18:15 +09:00
r-ca 556c7d0841 アニメーションを全部に追加 2024-01-20 16:14:36 +09:00
r-ca d43bcf09b2 UI調整 2024-01-20 16:13:42 +09:00
r-ca 6120427400 カラーリソース追加 2024-01-20 16:10:46 +09:00
r-ca 2b087a4c45 アイコン背景色変更 2024-01-20 16:06:57 +09:00
r-ca 457e58264b Stringリソースからタイトルを取得するように 2024-01-20 16:05:55 +09:00
r-ca 4d5d02c794 アイコン変更 2024-01-20 16:02:57 +09:00
r-ca b8f3b016b7 メニューに追加 2024-01-20 16:00:10 +09:00
r-ca b6307f67ce ナビゲーションに追加 2024-01-20 15:59:21 +09:00
r-ca 1e8dec3021 引数削除 2024-01-20 15:58:12 +09:00
r-ca 86d290b217 引数削除 2024-01-20 15:57:55 +09:00
r-ca 02d26f864d 引数削除 2024-01-20 15:57:34 +09:00
r-ca 5aa6c975da スキャンページフラグメント作成 2024-01-20 15:56:49 +09:00
r-ca 7075fc710d Dataページフラグメント作成 2024-01-20 15:56:14 +09:00
r-ca ba0cb871a4 Display設定ページフラグメント作成 2024-01-20 15:55:43 +09:00
r-ca 95a2a44cb1 ハイフン削除 2024-01-20 15:54:51 +09:00
r-ca fd65b17921 Drawable追加 2024-01-20 15:54:13 +09:00
r-ca a3f469b466 アニメーションを追加 テスト 2024-01-20 15:50:03 +09:00
r-ca e86129295a Durationを200msに変更 2024-01-20 15:49:53 +09:00
r-ca f4c46fbd5d アイテムをタッチしたら画面推移するように 2024-01-20 15:40:52 +09:00
r-ca 439b76f8bf Stringリソースを参照するように 2024-01-20 15:38:59 +09:00
r-ca ffd455c6d8 Stringリソースを参照するように 2024-01-20 15:38:13 +09:00
r-ca 29c3fddd14 Stringリソース追加 2024-01-20 15:37:55 +09:00
r-ca 516a55e4e0 ボトムナビゲーションに追加 2024-01-20 15:29:09 +09:00
r-ca 68e4d0639a メインナビゲーションにinclude 2024-01-20 15:28:08 +09:00
r-ca db26e639e6 テスト用にアイテム追加 2024-01-20 15:27:39 +09:00
r-ca 32cd27997c モデル変更 2024-01-20 15:27:11 +09:00
r-ca 6fb8091754 ナビゲーショングラフに追加 2024-01-20 15:24:58 +09:00
r-ca 0d7d47ea10 引数削除 2024-01-20 15:24:37 +09:00
r-ca 3d544fa423 フラグメント生成 2024-01-20 15:23:56 +09:00
r-ca 487451712e ナビゲーショングラフ生成 2024-01-20 15:22:23 +09:00
r-ca e78718ab79 id修正 2024-01-20 15:20:09 +09:00
r-ca 35c58e14ad インポート修正 2024-01-20 15:19:00 +09:00
r-ca 4efad853f7 アダプタ実装 2024-01-20 15:18:39 +09:00
r-ca 6c22050906 設定画面のリストアイテム用モデル作成 2024-01-20 15:18:32 +09:00
r-ca 17dc90162b ファイル移動 2024-01-20 15:14:16 +09:00
r-ca 72933fd45b ファイル移動 2024-01-20 15:13:49 +09:00
r-ca c8c0e37052 リネーム 2024-01-20 15:11:59 +09:00
r-ca 7b6d8e3a18 レイアウトコピー 2024-01-20 15:10:52 +09:00
r-ca 6167c412c7 依存関係追加 2024-01-20 15:10:00 +09:00
r-ca 226f09f8bb 引数削除 2024-01-20 15:09:13 +09:00
r-ca 0c4ba99a07 TopFragment作成 2024-01-20 15:08:44 +09:00
r-ca 097adebd9b .idea 2024-01-20 15:07:51 +09:00
r-ca 03a75a5b29 依存関係に追加 2024-01-20 15:07:45 +09:00
r-ca 0c6e2b1a98 settingモジュール作成 2024-01-20 15:07:07 +09:00
ろむねこ a7b92120ba Merge pull request #84 from lacerta-doc/feature/home/fix
ホーム画面改修
2024-01-20 15:06:00 +09:00
98 changed files with 2310 additions and 624 deletions

No files matched your search

+2 -2
View File
@@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2023-12-18T03:36:14.973846Z">
<DropdownSelection timestamp="2024-01-20T07:15:21.179573376Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=ZY22H7V3G7" />
<DeviceId pluginId="LocalEmulator" identifier="path=/home/rca/.android/avd/Pixel_3a_API_34_extension_level_7_x86_64.avd" />
</handle>
</Target>
</DropdownSelection>
+1 -1
View File
@@ -4,7 +4,6 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
@@ -23,6 +22,7 @@
<option value="$PROJECT_DIR$/feature/library" />
<option value="$PROJECT_DIR$/feature/scan" />
<option value="$PROJECT_DIR$/feature/search" />
<option value="$PROJECT_DIR$/feature/setting" />
<option value="$PROJECT_DIR$/model" />
<option value="$PROJECT_DIR$/processor" />
<option value="$PROJECT_DIR$/shared" />
+1 -1
View File
@@ -1,6 +1,6 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
+5
View File
@@ -74,7 +74,12 @@ dependencies {
implementation project(':feature:library')
implementation project(':feature:scan')
implementation project(':feature:debug') // デバッグメニュー
implementation project(':feature:setting') // 設定画面
implementation project(':data')
implementation project(':shared:ui')
implementation project(':model')
implementation project(':utils')
}
@@ -1,40 +1,53 @@
package one.nem.lacerta;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import one.nem.lacerta.model.FragmentNavigation;
import one.nem.lacerta.model.pref.FeatureSwitchOverride;
import one.nem.lacerta.utils.FeatureSwitch;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.utils.repository.SharedPrefUtils;
import javax.inject.Inject;
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity implements FragmentNavigation {
@Inject
SharedPrefUtils sharedPrefUtils;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_nav);
// Initialize app
if (sharedPrefUtils.getIsFirstLaunch()) initializeApp();
// Init navigation
try {
FragmentManager supportFragmentManager = getSupportFragmentManager();
NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
assert navHostFragment != null;
NavController navController = navHostFragment.getNavController();
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_nav);
NavigationUI.setupWithNavController(bottomNavigationView, navController);
}
catch (Exception e) {
@@ -44,10 +57,68 @@ public class MainActivity extends AppCompatActivity {
finish(); // Exit app
}
// Apply feature switch
applyFeatureSwitch(bottomNavigationView, FeatureSwitchOverride.ENABLE_SEARCH, FeatureSwitch.FeatureMaster.enableSearch, one.nem.lacerta.feature.search.R.id.feature_search_navigation);
applyFeatureSwitch(bottomNavigationView, FeatureSwitchOverride.ENABLE_DEBUG_MENU, FeatureSwitch.FeatureMaster.enableDebugMenu, one.nem.lacerta.feature.debug.R.id.feature_debug_navigation);
// Set navigation bar color
getWindow().setNavigationBarColor(ContextCompat.getColor(this, one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer));
// Set status bar color
getWindow().setStatusBarColor(ContextCompat.getColor(this, one.nem.lacerta.shared.ui.R.color.colorSurface));
// Set app bar color
AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) {
// Collapsed
getWindow().setStatusBarColor(ContextCompat.getColor(getApplicationContext(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer));
} else if (verticalOffset == 0) {
// Expanded
getWindow().setStatusBarColor(ContextCompat.getColor(getApplicationContext(), one.nem.lacerta.shared.ui.R.color.colorSurface));
} else {
// Somewhere in between
// Here you can add a color transition if you want
}
}
});
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
// Public
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
public void setActionBarBackButton(boolean isEnabled) {
getSupportActionBar().setDisplayHomeAsUpEnabled(isEnabled);
}
private void initializeApp() {
Log.d("Init", "Initializing app");
// Set feature switch override to default value
sharedPrefUtils.setFeatureSwitchOverride(FeatureSwitchOverride.ENABLE_SEARCH, FeatureSwitch.FeatureMaster.enableSearch);
sharedPrefUtils.setFeatureSwitchOverride(FeatureSwitchOverride.ENABLE_DEBUG_MENU, FeatureSwitch.FeatureMaster.enableDebugMenu);
// Set isFirstLaunch to false
sharedPrefUtils.setIsFirstLaunch(false);
}
private void applyFeatureSwitch(BottomNavigationView bottomNavigationView, FeatureSwitchOverride featureSwitchOverride, boolean defaultValue, int menuId) {
boolean isEnabled = FeatureSwitch.Meta.canOverrideSwitch ? sharedPrefUtils.getFeatureSwitchOverride(featureSwitchOverride) : defaultValue;
if (!isEnabled) bottomNavigationView.getMenu().removeItem(menuId);
}
@Override
public void navigateToFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, fragment)
.addToBackStack(null)
.commit();
}
}
+49 -12
View File
@@ -1,24 +1,61 @@
<?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"
android:theme="@style/Theme.Lacerta"
tools:context=".MainActivity">
android:background="@color/colorSurface">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/bottom_nav"
app:layout_constraintBottom_toTopOf="@id/bottom_nav"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/main_nav"
tools:layout="@layout/fragment_debug_menu_container" />
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="@color/colorSurface"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:collapsedTitleGravity="start|center_vertical"
app:contentScrim="@color/colorSecondaryContainer"
app:expandedTitleGravity="start|bottom"
app:expandedTitleMarginBottom="16dp"
app:expandedTitleMarginStart="16dp"
app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title="HOGE" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/main_nav"
tools:layout="@layout/fragment_home_top"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
@@ -32,6 +69,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_nav_menu"/>
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
+6 -1
View File
@@ -19,6 +19,11 @@
<item
android:id="@id/feature_debug_navigation"
android:icon="@drawable/developer_mode_24px"
android:title="@string/debug_menu_title"/>
android:title="@string/debug_menu_title" />
<item
android:id="@id/feature_setting_navigation"
android:icon="@drawable/settings_24px"
android:title="@string/setting_title"/>
</menu>
+4 -1
View File
@@ -2,14 +2,17 @@
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/app_main_nav"
app:startDestination="@id/feature_debug_navigation">
app:startDestination="@id/feature_home_navigation">
<include app:graph="@navigation/feature_debug_navigation" />
<include app:graph="@navigation/feature_library_navigation" />
<include app:graph="@navigation/feature_home_navigation" />
<include app:graph="@navigation/feature_search_navigation" />
<include app:graph="@navigation/feature_setting_navigation" />
</navigation>
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
android {
namespace 'one.nem.lacerta.component.common'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
+1 -1
View File
@@ -5,7 +5,7 @@ plugins {
android {
namespace 'one.nem.lacerta.component.scanner'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
@@ -1,5 +1,6 @@
package one.nem.lacerta.component.scanner;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
@@ -22,6 +23,7 @@ import com.websitebeaver.documentscanner.DocumentScanner;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
@@ -152,21 +154,35 @@ public class ScannerManagerActivity extends AppCompatActivity {
private void saveNewDocument() {
logger.debug(TAG, "saveNewDocument");
// Deprecatedだが、中断機能が存在しないので操作をブロックする目的で(意図的に)使用
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("保存中..."); // TODO-rca: テキストをリソースに移動
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setCancelable(false);
dialog.show();
DocumentMeta documentMeta = new DocumentMeta("Untitled"); // TODO-rca: デフォルトタイトルを指定できるようにする
DocumentDetail documentDetail = document.createDocument(documentMeta);
Bitmap[] bitmaps = new Bitmap[this.croppedImages.size()];
this.croppedImages.toArray(bitmaps);
try {
documentProcessorFactory.create(documentDetail).addNewPagesToLast(bitmaps);
Toast.makeText(this, "Saved.", Toast.LENGTH_SHORT).show();
lacertaVcsFactory.create(documentDetail.getMeta().getId()).generateRevisionAtCurrent("Initial commit");
lacertaVcsFactory.create(documentDetail.getMeta().getId()).printLog(); // Debug
lacertaVcsFactory.create(documentDetail.getMeta().getId()).printRev(); // Debug
document.createDocument(documentMeta).thenAccept((documentDetail) -> {
Bitmap[] bitmaps = new Bitmap[croppedImages.size()];
croppedImages.toArray(bitmaps);
logger.debug(TAG, "bitmaps.length: " + bitmaps.length);
addPagesToDocumentDetail(documentDetail, bitmaps).join();
document.updateDocument(documentDetail).join();
dialog.dismiss();
finish();
} catch (Exception e) {
logger.error(TAG, "Error: " + e.getMessage());
logger.e_code("9dff2a28-20e8-4ccd-9d04-f0c7646faa6a");
}
});
}
private CompletableFuture<Void> addPagesToDocumentDetail(DocumentDetail documentDetail, Bitmap[] bitmaps) {
return CompletableFuture.runAsync(() -> {
try {
document.updateDocument(documentProcessorFactory.create(documentDetail).addNewPagesToLast(bitmaps).getDocumentDetail()).join();
lacertaVcsFactory.create(documentDetail.getMeta().getId()).generateRevisionAtCurrent("Initial commit");
} catch (Exception e) {
logger.error(TAG, "Error: " + e.getMessage());
logger.e_code("9dff2a28-20e8-4ccd-9d04-f0c7646faa6a");
}
});
}
private void insertToExistDocument() {
+23 -1
View File
@@ -1,10 +1,11 @@
plugins {
alias(libs.plugins.com.android.library)
id 'com.google.dagger.hilt.android'
}
android {
namespace 'one.nem.lacerta.component.viewer'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
@@ -29,7 +30,28 @@ dependencies {
implementation libs.androidx.appcompat
implementation libs.com.google.android.material
implementation libs.androidx.activity
implementation libs.androidx.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.androidx.test.ext.junit
androidTestImplementation libs.androidx.test.espresso.core
// Navigation
implementation libs.navigation.fragment
implementation libs.navigation.ui
implementation libs.navigation.dynamic.features.fragment
// DI
implementation libs.com.google.dagger.hilt.android
annotationProcessor libs.com.google.dagger.hilt.compiler
// shared
implementation project(':shared:ui')
implementation project(':utils')
implementation project(':data')
implementation project(':model')
}
@@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name=".ViewerMainActivity"
android:exported="false" />
</application>
</manifest>
@@ -0,0 +1,88 @@
package one.nem.lacerta.component.viewer;
import android.graphics.Bitmap;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.Document;
import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.page.Page;
import one.nem.lacerta.utils.LacertaLogger;
/**
* A simple {@link Fragment} subclass.
* Use the {@link ComponentViewerTopFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class ComponentViewerTopFragment extends Fragment {
@Inject
Document document;
@Inject
LacertaLogger logger;
private static final String TAG = "ComponentViewerTopFragment";
private String documentId;
public ComponentViewerTopFragment() {
// Required empty public constructor
}
public static ComponentViewerTopFragment newInstance(String documentId) {
ComponentViewerTopFragment fragment = new ComponentViewerTopFragment();
Bundle args = new Bundle();
args.putString("documentId", documentId);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
documentId = getArguments().getString("documentId");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_component_viewer_top, container, false);
RecyclerView recyclerView = view.findViewById(R.id.body_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
ViewerBodyAdapter viewerBodyAdapter = new ViewerBodyAdapter(fileName -> {
Toast.makeText(getContext(), fileName, Toast.LENGTH_SHORT).show();
});
recyclerView.setAdapter(viewerBodyAdapter);
document.getDocument(documentId).thenAccept(documentDetail -> {
ArrayList<Page> pages = documentDetail.getPages();
logger.debug(TAG, "pages.size(): " + pages.size());
viewerBodyAdapter.setPages(pages);
getActivity().runOnUiThread(() -> {
viewerBodyAdapter.notifyItemRangeChanged(0, pages.size());
});
});
return view;
}
}
@@ -0,0 +1,5 @@
package one.nem.lacerta.component.viewer;
public interface ItemClickListener {
void onItemClick(String fileName); // DEBUG
}
@@ -0,0 +1,66 @@
package one.nem.lacerta.component.viewer;
import android.graphics.Bitmap;
import android.media.Image;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import one.nem.lacerta.model.document.page.Page;
public class ViewerBodyAdapter extends RecyclerView.Adapter<ViewerBodyAdapter.ViewHolder>{
ArrayList<Page> pages;
ItemClickListener listener;
public ViewerBodyAdapter(ArrayList<Page> pages, ItemClickListener listener){
this.pages = pages;
this.listener = listener;
}
public ViewerBodyAdapter(ItemClickListener listener){
this.pages = new ArrayList<>();
this.listener = listener;
}
public void setPages(ArrayList<Page> pages){
this.pages = pages;
}
@NonNull
@Override
public ViewerBodyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = View.inflate(parent.getContext(), R.layout.viewer_body_list_item, null);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewerBodyAdapter.ViewHolder holder, int position) {
Bitmap bitmap = pages.get(position).getBitmap();
holder.image.setImageBitmap(bitmap);
holder.itemView.setOnClickListener(v -> {
});
}
@Override
public int getItemCount() {
return pages.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView image;
public ViewHolder(@NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imageView);
}
}
}
@@ -0,0 +1,65 @@
package one.nem.lacerta.component.viewer;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.utils.LacertaLogger;
@AndroidEntryPoint
public class ViewerMainActivity extends AppCompatActivity {
@Inject
LacertaLogger logger;
@Inject
public ViewerMainActivity() {
}
// Variables
private static final String TAG = "ViewerMainActivity";
String documentId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_viewer_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
Intent intent = getIntent();
try {
documentId = intent.getStringExtra("documentId");
}
catch (Exception e) {
logger.error(TAG, "Failed to get documentId from intent");
logger.error(TAG, "Searchable Error code: " + "f64c21a2-391f-4c40-92f6-183da459de21");
Toast.makeText(this, "Failed to get documentId from intent", Toast.LENGTH_LONG).show();
finish();
}
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, ComponentViewerTopFragment.newInstance(documentId))
.commitNow();
}
}
@@ -0,0 +1,20 @@
package one.nem.lacerta.component.viewer.model;
import android.graphics.Bitmap;
public class ViewerBodyListItem {
Bitmap image;
public ViewerBodyListItem(Bitmap image) {
this.image = image;
}
public Bitmap getImage() {
return image;
}
public void setImage(Bitmap image) {
this.image = image;
}
}
@@ -0,0 +1,21 @@
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ViewerMainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="one.nem.lacerta.component.viewer.ComponentViewerTopFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,51 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorSurface">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
app:contentScrim="@color/colorSecondaryContainer"
android:background="@color/colorSurface"
android:layout_width="match_parent"
android:layout_height="160dp"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:collapsedTitleGravity="start|center_vertical"
app:expandedTitleGravity="start|bottom"
app:expandedTitleMarginBottom="16dp"
app:expandedTitleMarginStart="16dp"
app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title="Title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/body_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="8dp"
android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/component_viewer_navigation"
app:startDestination="@id/componentViewerTopFragment">
<fragment
android:id="@+id/componentViewerTopFragment"
android:name="one.nem.lacerta.component.viewer.ComponentViewerTopFragment"
android:label="ComponentViewerTopFragment" />
</navigation>
@@ -0,0 +1,4 @@
<resources>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
@@ -2,6 +2,7 @@ package one.nem.lacerta.data;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import one.nem.lacerta.model.document.DocumentMeta;
import one.nem.lacerta.model.document.DocumentDetail;
@@ -13,13 +14,13 @@ import one.nem.lacerta.model.document.tag.DocumentTag;
*/
public interface Document {
DocumentDetail createDocument(DocumentMeta meta);
CompletableFuture<DocumentDetail> createDocument(DocumentMeta meta);
DocumentDetail createDocument();
CompletableFuture<DocumentDetail> createDocument();
void deleteDocument(String documentId);
CompletableFuture<Void> deleteDocument(String documentId);
void updateDocument(DocumentMeta meta, DocumentDetail detail);
CompletableFuture<Void> updateDocument(DocumentDetail detail);
DocumentDetail getDocument(String documentId);
CompletableFuture<DocumentDetail> getDocument(String documentId);
}
@@ -1,6 +1,7 @@
package one.nem.lacerta.data;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType;
@@ -11,15 +12,16 @@ import one.nem.lacerta.model.document.DocumentDetail;
public interface LacertaLibrary {
// Get History
ArrayList<ListItem> getRecentDocument(int limit);
ArrayList<ListItem> getRecentDocument(int limit, int offset);
CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit);
CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit, int offset);
// Get Library page
LibraryItemPage getLibraryPage(int limit);
LibraryItemPage getLibraryPage(int limit, int offset);
LibraryItemPage getLibraryPage(String pageId, int limit);
LibraryItemPage getLibraryPage(String pageId, int limit, int offset);
CompletableFuture<LibraryItemPage> getLibraryPage(int limit);
CompletableFuture<LibraryItemPage> getLibraryPage(int limit, int offset);
CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit);
CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit, int offset);
// Create Folder
CompletableFuture<String> createFolder(String path, String name);
// GetDocument
DocumentDetail getDocumentDetailById(String id); // TODO-rca: Documentに統合する
}
@@ -1,8 +1,10 @@
package one.nem.lacerta.data.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
// Hilt
import javax.inject.Inject;
@@ -16,13 +18,20 @@ import one.nem.lacerta.model.document.DocumentMeta;
import one.nem.lacerta.model.document.DocumentDetail;
// Lacerta/source
import one.nem.lacerta.model.document.internal.XmlMetaModel;
import one.nem.lacerta.model.document.internal.XmlMetaPageModel;
import one.nem.lacerta.model.document.page.Page;
import one.nem.lacerta.source.database.LacertaDatabase;
import one.nem.lacerta.source.database.entity.DocumentEntity;
// Lacerta/utils
import one.nem.lacerta.source.file.FileManager;
import one.nem.lacerta.source.file.factory.FileManagerFactory;
import one.nem.lacerta.utils.LacertaLogger;
// Lacerta/vcs
import one.nem.lacerta.utils.XmlMetaParser;
import one.nem.lacerta.utils.repository.DeviceInfoUtils;
import one.nem.lacerta.vcs.LacertaVcs;
import one.nem.lacerta.vcs.factory.LacertaVcsFactory;
@@ -40,6 +49,14 @@ public class DocumentImpl implements Document {
@Inject
LacertaVcsFactory vcsFactory;
@Inject
FileManagerFactory fileManagerFactory;
@Inject
DeviceInfoUtils deviceInfoUtils;
@Inject
XmlMetaParser xmlMetaParser;
@Inject
public DocumentImpl() {
@@ -49,35 +66,37 @@ public class DocumentImpl implements Document {
@Override
public DocumentDetail createDocument(DocumentMeta meta) {
DocumentDetail detail = new DocumentDetail();
detail.setMeta(meta);
detail.setPages(new ArrayList<>());
public CompletableFuture<DocumentDetail> createDocument(DocumentMeta meta) {
return CompletableFuture.supplyAsync(() -> {
DocumentDetail detail = new DocumentDetail();
detail.setMeta(meta);
detail.setPages(new ArrayList<>());
// Create DocumentEntity
DocumentEntity documentEntity = new DocumentEntity();
documentEntity.id = meta.getId();
documentEntity.title = meta.getTitle();
documentEntity.author = meta.getAuthor();
documentEntity.defaultBranch = meta.getDefaultBranch();
documentEntity.updatedAt = meta.getUpdatedAt();
documentEntity.createdAt = meta.getCreatedAt();
documentEntity.publicPath = meta.getPath().getStringPath();
documentEntity.tagIds = meta.getTagIds();
// TODO-rca: UIスレッドから追い出す
database.documentDao().insert(documentEntity);
// Create DocumentEntity
DocumentEntity documentEntity = new DocumentEntity();
documentEntity.id = meta.getId();
documentEntity.title = meta.getTitle();
documentEntity.author = meta.getAuthor();
documentEntity.defaultBranch = meta.getDefaultBranch();
documentEntity.updatedAt = meta.getUpdatedAt();
documentEntity.createdAt = meta.getCreatedAt();
documentEntity.publicPath = meta.getPath().getStringPath();
documentEntity.tagIds = meta.getTagIds();
// Vcs
LacertaVcs vcs = vcsFactory.create(meta.getId());
vcs.createDocument(meta.getId());
database.documentDao().insert(documentEntity);
// XmlMeta
updateXmlMeta(detail).join();
// Vcs
LacertaVcs vcs = vcsFactory.create(meta.getId());
vcs.createDocument(meta.getId());
return detail;
return detail;
});
}
@Override
public DocumentDetail createDocument() {
public CompletableFuture<DocumentDetail> createDocument() {
DocumentMeta meta = new DocumentMeta();
meta.setId(UUID.randomUUID().toString());
meta.setTitle("New Document");
@@ -91,17 +110,112 @@ public class DocumentImpl implements Document {
}
@Override
public void deleteDocument(String documentId) {
public CompletableFuture<Void> deleteDocument(String documentId) {
return CompletableFuture.supplyAsync(() -> {
return null;
});
}
@Override
public void updateDocument(DocumentMeta meta, DocumentDetail detail) {
public CompletableFuture<Void> updateDocument(DocumentDetail detail) {
return CompletableFuture.supplyAsync(() -> {
updateXmlMeta(detail).join();
return null;
});
}
@Override
public DocumentDetail getDocument(String documentId) {
return null;
public CompletableFuture<DocumentDetail> getDocument(String documentId) {
return CompletableFuture.supplyAsync(() -> {
DocumentEntity documentEntity = database.documentDao().findById(documentId);
if (documentEntity == null) {
throw new IllegalArgumentException("documentId is not found");
}
DocumentMeta meta = new DocumentMeta();
meta.setId(documentEntity.id);
meta.setTitle(documentEntity.title);
meta.setAuthor(documentEntity.author);
meta.setDefaultBranch(documentEntity.defaultBranch);
meta.setUpdatedAt(documentEntity.updatedAt);
meta.setCreatedAt(documentEntity.createdAt);
meta.setPath(new PublicPath().resolve(documentEntity.publicPath));
meta.setTags(new ArrayList<>()); // TODO-rca: タグを取得する
DocumentDetail detail = new DocumentDetail();
getPagesByXmlMeta(documentId).thenCompose(xmlMetaPageModels -> getPagesByXmlMetaPageModel(documentId, xmlMetaPageModels)).thenAccept(pages -> {
logger.debug(TAG, "pages: " + pages.size());
detail.setMeta(meta);
detail.setPages(pages);
}).join();
return detail;
});
}
private CompletableFuture<ArrayList<XmlMetaPageModel>> getPagesByXmlMeta(String documentId) {
return CompletableFuture.supplyAsync(() -> {
FileManager fileManager = fileManagerFactory.create(deviceInfoUtils.getExternalStorageDirectory());
try {
ArrayList<XmlMetaPageModel> xmlMetaPageModels = xmlMetaParser.deserialize(fileManager.resolve(documentId).loadXml("meta.xml")).getPages();
// Debug
logger.debug(TAG, "xmlMetaPageModels: " + xmlMetaPageModels.size());
for (XmlMetaPageModel xmlMetaPageModel : xmlMetaPageModels) {
logger.debug(TAG, "\txmlMetaPageModel: " + xmlMetaPageModel.getFilename());
}
return xmlMetaPageModels;
} catch (IOException e) {
logger.error(TAG, "DocumentMeta parse error");
logger.trace(TAG, e.getMessage());
logger.e_code("db18c04a-1625-4871-9e4e-918d805568ac");
}
return null;
});
}
private CompletableFuture<ArrayList<Page>> getPagesByXmlMetaPageModel(String documentId, ArrayList<XmlMetaPageModel> xmlMetaPageModels) {
return CompletableFuture.supplyAsync(() -> {
ArrayList<Page> pages = new ArrayList<>();
FileManager fileManager;
try {
fileManager = fileManagerFactory.create(deviceInfoUtils.getExternalStorageDirectory()).resolve(documentId);
} catch (IOException e) {
logger.error(TAG, "FileManager resolve error");
logger.trace(TAG, e.getMessage());
logger.e_code("2235e8ee-4177-46f8-af6b-084381b202e6");
return null;
}
for (XmlMetaPageModel xmlMetaPageModel : xmlMetaPageModels) {
try {
pages.add(new Page(xmlMetaPageModel.getFilename(), fileManager.resolve("raw").loadBitmap(xmlMetaPageModel.getFilename())));
} catch (IOException e) {
logger.error(TAG, "Bitmap decode error");
logger.trace(TAG, e.getMessage());
logger.e_code("3bba8c8f-90fb-4a24-a726-7ea201929f8b");
return null;
}
}
return pages;
});
}
private CompletableFuture<Void> updateXmlMeta(DocumentDetail documentDetail) {
return CompletableFuture.supplyAsync(() -> {
// TODO-rca: リビジョンIDを検証する, 挿入する
FileManager fileManager = fileManagerFactory.create(deviceInfoUtils.getExternalStorageDirectory());
ArrayList<XmlMetaPageModel> xmlMetaPageModels = new ArrayList<>();
for (Page page : documentDetail.getPages()) {
xmlMetaPageModels.add(new XmlMetaPageModel(page.getFileName()));
}
try {
fileManager.createDirectoryIfNotExist(documentDetail.getMeta().getId()).resolve(documentDetail.getMeta().getId())
.createFileIfNotExist("meta.xml").resolve("meta.xml").saveXml(xmlMetaParser.serialize(new XmlMetaModel("revisionId_PLACEHOLDER", xmlMetaPageModels)));
} catch (IOException e) {
logger.error(TAG, "DocumentMeta serialize error");
logger.trace(TAG, e.getMessage());
logger.e_code("e3b4d0c9-5b7e-4b7e-9e9a-5b8b8b8b8b8b");
}
return null;
});
}
}
@@ -1,8 +1,12 @@
package one.nem.lacerta.data.impl;
import java.text.DateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
@@ -10,63 +14,201 @@ import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType;
import one.nem.lacerta.model.PublicPath;
import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.source.database.LacertaDatabase;
import one.nem.lacerta.source.database.common.DateTypeConverter;
import one.nem.lacerta.source.database.entity.DocumentEntity;
import one.nem.lacerta.source.database.entity.FolderEntity;
import one.nem.lacerta.utils.LacertaLogger;
public class LacertaLibraryImpl implements LacertaLibrary {
@Inject
LacertaLogger logger;
@Inject
LacertaDatabase database;
@Override
public ArrayList<ListItem> getRecentDocument(int limit) {
List<DocumentEntity> documentEntities = database.documentDao().getRecentDocument(limit);
ArrayList<ListItem> listItems = new ArrayList<>();
for (DocumentEntity documentEntity : documentEntities) {
ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
listItem.setTitle(documentEntity.title);
listItem.setDescription(DateFormat.getDateInstance().format(documentEntity.updatedAt));
listItem.setItemId(documentEntity.id);
listItems.add(listItem);
}
return listItems;
@Inject
public LacertaLibraryImpl(LacertaLogger logger, LacertaDatabase database) {
this.logger = logger;
this.database = database;
}
@Override
public ArrayList<ListItem> getRecentDocument(int limit, int offset) {
public CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit) {
return CompletableFuture.supplyAsync(() -> {
// 5秒フリーズさせる
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<DocumentEntity> documentEntities = database.documentDao().getRecentDocument(limit);
ArrayList<ListItem> listItems = new ArrayList<>();
for (DocumentEntity documentEntity : documentEntities) {
ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
listItem.setTitle(documentEntity.title);
listItem.setDescription(DateFormat.getDateInstance().format(documentEntity.updatedAt));
listItem.setItemId(documentEntity.id);
listItems.add(listItem);
}
return listItems;
});
}
@Override
public CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit, int offset) {
return null; // TODO-rca: Implement
}
@Override
public LibraryItemPage getLibraryPage(int limit) {
return null;
// Internal
private CompletableFuture<List<FolderEntity>> getFolderEntitiesByPublicPath(String publicPath) {
return CompletableFuture.supplyAsync(() -> {
return database.folderDao().findByPublicPathWithLimit(publicPath, 10); // TODO-rca: ハードコーディングやめる
});
}
private CompletableFuture<List<DocumentEntity>> getDocumentEntitiesByPublicPath(String publicPath) {
return CompletableFuture.supplyAsync(() -> {
return database.documentDao().findByPublicPathWithLimit(publicPath, 10); // TODO-rca: ハードコーディングやめる
});
}
@Override
public LibraryItemPage getLibraryPage(int limit, int offset) {
return null;
public CompletableFuture<LibraryItemPage> getLibraryPage(int limit) {
return CompletableFuture.supplyAsync(() -> {
// 5秒フリーズさせる
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LibraryItemPage libraryItemPage = new LibraryItemPage();
List<FolderEntity> folderEntities = getFolderEntitiesByPublicPath("/").join();
logger.debug("LacertaLibraryImpl", "folderEntities.size(): " + folderEntities.size());
List<DocumentEntity> documentEntities = getDocumentEntitiesByPublicPath("/").join();
logger.debug("LacertaLibraryImpl", "documentEntities.size(): " + documentEntities.size());
ArrayList<ListItem> listItems = new ArrayList<>();
for (FolderEntity folderEntity : folderEntities) {
logger.debug("LacertaLibraryImpl", "folderEntity.name: " + folderEntity.name);
ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_FOLDER);
listItem.setTitle(folderEntity.name);
listItem.setDescription("フォルダ"); // TODO-rca: ハードコーディングやめる
listItem.setItemId(folderEntity.id);
listItems.add(listItem);
}
for (DocumentEntity documentEntity : documentEntities) {
logger.debug("LacertaLibraryImpl", "documentEntity.title: " + documentEntity.title);
ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
listItem.setTitle(documentEntity.title);
// listItem.setDescription(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm").format(documentEntity.updatedAt.toInstant()));
listItem.setItemId(documentEntity.id);
listItems.add(listItem);
}
libraryItemPage.setPageTitle("/");
libraryItemPage.setPageId("root");
libraryItemPage.setListItems(listItems);
logger.debug("LacertaLibraryImpl", "libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
return libraryItemPage;
});
}
@Override
public LibraryItemPage getLibraryPage(String pageId, int limit) {
return null;
public CompletableFuture<LibraryItemPage> getLibraryPage(int limit, int offset) {
return CompletableFuture.supplyAsync(() -> {
return null;
});
}
@Override
public LibraryItemPage getLibraryPage(String pageId, int limit, int offset) {
return null;
public CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit) {
return CompletableFuture.supplyAsync(() -> {
LibraryItemPage libraryItemPage = new LibraryItemPage();
FolderEntity folderEntity = database.folderDao().findById(pageId);
if (folderEntity == null) {
return null;
}
PublicPath publicPath = new PublicPath().parse(folderEntity.publicPath);
String resolvedPublicPath = publicPath.resolve(folderEntity.name).getStringPath();
logger.debug("LacertaLibraryImpl", "Resolved publicPath: " + resolvedPublicPath);
List<FolderEntity> folderEntities = getFolderEntitiesByPublicPath(resolvedPublicPath).join();
logger.debug("LacertaLibraryImpl", "folderEntities.size(): " + folderEntities.size());
List<DocumentEntity> documentEntities = getDocumentEntitiesByPublicPath(resolvedPublicPath).join();
logger.debug("LacertaLibraryImpl", "documentEntities.size(): " + documentEntities.size());
ArrayList<ListItem> listItems = new ArrayList<>();
for (FolderEntity childFolderEntity : folderEntities) {
logger.debug("LacertaLibraryImpl", "childFolderEntity.name: " + childFolderEntity.name);
ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_FOLDER);
listItem.setTitle(childFolderEntity.name);
listItem.setDescription("フォルダ"); // TODO-rca: ハードコーディングやめる
listItem.setItemId(childFolderEntity.id);
listItems.add(listItem);
}
for (DocumentEntity documentEntity : documentEntities) {
logger.debug("LacertaLibraryImpl", "documentEntity.title: " + documentEntity.title);
ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
listItem.setTitle(documentEntity.title);
// listItem.setDescription(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm").format(documentEntity.updatedAt.toInstant()));
listItem.setItemId(documentEntity.id);
listItems.add(listItem);
}
libraryItemPage.setPageTitle(folderEntity.name);
libraryItemPage.setPageId(folderEntity.id);
libraryItemPage.setListItems(listItems);
logger.debug("LacertaLibraryImpl", "libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
return libraryItemPage;
});
}
@Override
public DocumentDetail getDocumentDetailById(String id) {
return null;
public CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit, int offset) {
return CompletableFuture.supplyAsync(() -> {
return null;
});
}
@Override
public CompletableFuture<String> createFolder(String parentId, String name) {
return CompletableFuture.supplyAsync(() -> {
FolderEntity parentFolderEntity = database.folderDao().findById(parentId);
PublicPath publicPath;
if (parentFolderEntity == null) {
publicPath = new PublicPath().resolve("/");
} else {
publicPath = new PublicPath().resolve(parentFolderEntity.publicPath);
}
FolderEntity folderEntity = new FolderEntity();
folderEntity.id = UUID.randomUUID().toString();
folderEntity.name = name;
folderEntity.publicPath = publicPath.getStringPath();
database.folderDao().insert(folderEntity);
return folderEntity.id;
});
}
}
@@ -1,219 +1,219 @@
package one.nem.lacerta.data.impl;
import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType;
import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.DocumentMeta;
import one.nem.lacerta.model.document.path.DocumentPath;
import one.nem.lacerta.utils.LacertaLogger;
import com.github.javafaker.DateAndTime;
import com.github.javafaker.Faker;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;
import javax.inject.Inject;
/**
* LacertaLibraryのスタブ実装
*/
public class LacertaLibraryStubImpl implements LacertaLibrary {
LacertaLogger logger;
Faker faker;
@Inject
public LacertaLibraryStubImpl(LacertaLogger logger) {
faker = new Faker(); // Init Faker
this.logger = logger;
logger.debug("LibraryStub", "Initialized");
}
// Internal Methods
// Generate Stub Data
private LibraryItemPage generateStubLibraryItemPage(int limit, String pageId) {
logger.debug("LibraryStub", "generateStubLibraryItemPage");
ArrayList<ListItem> listItems = new ArrayList<>();
int itemTotal = faker.number().numberBetween(1, limit); // 実際に返却するアイテム数を決定
int folderTotal;
// フォルダ数の抽選
if (itemTotal > 4) {
folderTotal = faker.number().numberBetween(1, itemTotal - 2);
}
else {
if (itemTotal > 2) {
folderTotal = 1;
}
else { // ドキュメント数がゼロにならないように
folderTotal = 0;
}
}
int documentTotal = itemTotal - folderTotal; // ドキュメント数を決定
logger.debug("LibraryStub", "itemTotal: " + itemTotal);
logger.debug("LibraryStub", "folderTotal: " + folderTotal);
logger.debug("LibraryStub", "documentTotal: " + documentTotal);
// フォルダを生成
for (int i = 0; i < folderTotal; i++) {
listItems.add(generateStubListItem(ListItemType.ITEM_TYPE_FOLDER));
}
// ドキュメントを生成
for (int i = 0; i < documentTotal; i++) {
listItems.add(generateStubListItem(ListItemType.ITEM_TYPE_DOCUMENT));
}
LibraryItemPage libraryItemPage = new LibraryItemPage();
libraryItemPage.setListItems(listItems);
if (pageId == null) {
libraryItemPage.setPageId(UUID.randomUUID().toString());
} else {
libraryItemPage.setPageId(pageId);
}
libraryItemPage.setPageTitle("FakePage" + faker.number().digits(3));
return libraryItemPage;
}
private ListItem generateStubListItem(ListItemType itemType) {
if (itemType == ListItemType.ITEM_TYPE_FOLDER) {
ListItem listItem = new ListItem();
listItem.setTitle("FakeFolder" + faker.number().digits(3));
listItem.setDescription("Updated at " + DateFormat.getDateTimeInstance().format(faker.date().birthday()));
listItem.setItemType(ListItemType.ITEM_TYPE_FOLDER);
listItem.setItemId(UUID.randomUUID().toString());
return listItem;
} else if (itemType == ListItemType.ITEM_TYPE_DOCUMENT) {
ListItem listItem = new ListItem();
listItem.setTitle("FakeDocument" + faker.book().title());
listItem.setDescription("Updated at " + DateFormat.getDateTimeInstance().format(faker.date().birthday()));
listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
listItem.setItemId(UUID.randomUUID().toString());
return listItem;
} else {
return null;
}
}
private LibraryItemPage getRecentDocumentPage(int limit) {
int itemTotal = faker.number().numberBetween(1, limit);
ArrayList<ListItem> listItems = new ArrayList<>();
for (int i = 0; i < itemTotal; i++) {
listItems.add(generateStubListItem(ListItemType.ITEM_TYPE_DOCUMENT));
}
// DescriptionからDateを抽出して新しい順にソート
listItems.sort((a, b) -> {
String aDate = a.getDescription().substring(11);
String bDate = b.getDescription().substring(11);
return bDate.compareTo(aDate);
});
LibraryItemPage libraryItemPage = new LibraryItemPage();
libraryItemPage.setListItems(listItems);
libraryItemPage.setPageId(UUID.randomUUID().toString());
libraryItemPage.setPageTitle("RecentDocument");
return libraryItemPage;
}
private DocumentDetail generateStubDocumentDetail(String id) throws IllegalArgumentException {
if (Objects.isNull(id)) {
throw new IllegalArgumentException("id is null");
}
DocumentMeta documentMeta = new DocumentMeta();
documentMeta.setId(id);
documentMeta.setTitle("FakeDocument" + faker.book().title());
documentMeta.setCreatedAt(faker.date().birthday());
documentMeta.setUpdatedAt(faker.date().birthday()); // TODO-rca: 更新日のほうが古くなることがあるのでなんとかする?
ArrayList<String> tagIds = new ArrayList<>();
DocumentDetail documentDetail = new DocumentDetail();
documentDetail.setMeta(documentMeta);
// documentDetail.setPath(null); // TODO-rca: なんとかする
// documentDetail.setAuthor(faker.name().fullName());
// documentDetail.setRepository(null); // TODO-rca: なんとかする
return documentDetail;
}
/**
* 履歴ページを取得する
* @param limit 取得するアイテム数
* @return ページオブジェクト
*/
@Override
public ArrayList<ListItem> getRecentDocument(int limit) {
return getRecentDocumentPage(limit).getListItems();
}
/**
* 履歴ページを取得する
* @param limit 取得するアイテム数
* @param offset 取得するアイテムのオフセット
* @return ページオブジェクト
*/
@Override
public ArrayList<ListItem> getRecentDocument(int limit, int offset) {
return getRecentDocumentPage(limit).getListItems();
}
/**
* ライブラリページを取得する
* @param limit 取得するアイテム数
* @return ページオブジェクト
*/
@Override
public LibraryItemPage getLibraryPage(int limit) {
return generateStubLibraryItemPage(limit, null);
}
/**
* ライブラリページを取得する
* @param limit 取得するアイテム数
* @param offset 取得するアイテムのオフセット
* @return ページオブジェクト
*/
@Override
public LibraryItemPage getLibraryPage(int limit, int offset) {
return generateStubLibraryItemPage(limit, null);
}
/**
* ライブラリページを取得する
* @param pageId ページID
* @param limit 取得するアイテム数
* @return ページオブジェクト
*/
@Override
public LibraryItemPage getLibraryPage(String pageId, int limit) {
return generateStubLibraryItemPage(limit, pageId);
}
/**
* ライブラリページを取得する
* @param pageId ページID
* @param limit 取得するアイテム数
* @param offset 取得するアイテムのオフセット
* @return ページオブジェクト
*/
@Override
public LibraryItemPage getLibraryPage(String pageId, int limit, int offset) {
return generateStubLibraryItemPage(limit, pageId);
}
/**
* ドキュメント詳細を取得する
* @param id ドキュメントID
* @return ドキュメント詳細オブジェクト
*/
@Override
public DocumentDetail getDocumentDetailById(String id) throws IllegalArgumentException {
return generateStubDocumentDetail(id);
}
}
//package one.nem.lacerta.data.impl;
//
//import one.nem.lacerta.data.LacertaLibrary;
//import one.nem.lacerta.model.LibraryItemPage;
//import one.nem.lacerta.model.ListItem;
//import one.nem.lacerta.model.ListItemType;
//import one.nem.lacerta.model.document.DocumentDetail;
//
//import one.nem.lacerta.model.document.DocumentMeta;
//import one.nem.lacerta.model.document.path.DocumentPath;
//import one.nem.lacerta.utils.LacertaLogger;
//
//import com.github.javafaker.DateAndTime;
//import com.github.javafaker.Faker;
//
//import java.text.DateFormat;
//import java.util.ArrayList;
//import java.util.Objects;
//import java.util.UUID;
//
//import javax.inject.Inject;
//
///**
// * LacertaLibraryのスタブ実装
// */
//public class LacertaLibraryStubImpl implements LacertaLibrary {
//
// LacertaLogger logger;
//
// Faker faker;
//
// @Inject
// public LacertaLibraryStubImpl(LacertaLogger logger) {
// faker = new Faker(); // Init Faker
// this.logger = logger;
// logger.debug("LibraryStub", "Initialized");
// }
//
// // Internal Methods
//
// // Generate Stub Data
// private LibraryItemPage generateStubLibraryItemPage(int limit, String pageId) {
// logger.debug("LibraryStub", "generateStubLibraryItemPage");
// ArrayList<ListItem> listItems = new ArrayList<>();
// int itemTotal = faker.number().numberBetween(1, limit); // 実際に返却するアイテム数を決定
// int folderTotal;
// // フォルダ数の抽選
// if (itemTotal > 4) {
// folderTotal = faker.number().numberBetween(1, itemTotal - 2);
// }
// else {
// if (itemTotal > 2) {
// folderTotal = 1;
// }
// else { // ドキュメント数がゼロにならないように
// folderTotal = 0;
// }
// }
// int documentTotal = itemTotal - folderTotal; // ドキュメント数を決定
// logger.debug("LibraryStub", "itemTotal: " + itemTotal);
// logger.debug("LibraryStub", "folderTotal: " + folderTotal);
// logger.debug("LibraryStub", "documentTotal: " + documentTotal);
//
// // フォルダを生成
// for (int i = 0; i < folderTotal; i++) {
// listItems.add(generateStubListItem(ListItemType.ITEM_TYPE_FOLDER));
// }
// // ドキュメントを生成
// for (int i = 0; i < documentTotal; i++) {
// listItems.add(generateStubListItem(ListItemType.ITEM_TYPE_DOCUMENT));
// }
//
// LibraryItemPage libraryItemPage = new LibraryItemPage();
// libraryItemPage.setListItems(listItems);
// if (pageId == null) {
// libraryItemPage.setPageId(UUID.randomUUID().toString());
// } else {
// libraryItemPage.setPageId(pageId);
// }
// libraryItemPage.setPageTitle("FakePage" + faker.number().digits(3));
//
// return libraryItemPage;
// }
//
// private ListItem generateStubListItem(ListItemType itemType) {
// if (itemType == ListItemType.ITEM_TYPE_FOLDER) {
// ListItem listItem = new ListItem();
// listItem.setTitle("FakeFolder" + faker.number().digits(3));
// listItem.setDescription("Updated at " + DateFormat.getDateTimeInstance().format(faker.date().birthday()));
// listItem.setItemType(ListItemType.ITEM_TYPE_FOLDER);
// listItem.setItemId(UUID.randomUUID().toString());
// return listItem;
// } else if (itemType == ListItemType.ITEM_TYPE_DOCUMENT) {
// ListItem listItem = new ListItem();
// listItem.setTitle("FakeDocument" + faker.book().title());
// listItem.setDescription("Updated at " + DateFormat.getDateTimeInstance().format(faker.date().birthday()));
// listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
// listItem.setItemId(UUID.randomUUID().toString());
// return listItem;
// } else {
// return null;
// }
// }
//
// private LibraryItemPage getRecentDocumentPage(int limit) {
// int itemTotal = faker.number().numberBetween(1, limit);
// ArrayList<ListItem> listItems = new ArrayList<>();
// for (int i = 0; i < itemTotal; i++) {
// listItems.add(generateStubListItem(ListItemType.ITEM_TYPE_DOCUMENT));
// }
// // DescriptionからDateを抽出して新しい順にソート
// listItems.sort((a, b) -> {
// String aDate = a.getDescription().substring(11);
// String bDate = b.getDescription().substring(11);
// return bDate.compareTo(aDate);
// });
// LibraryItemPage libraryItemPage = new LibraryItemPage();
// libraryItemPage.setListItems(listItems);
// libraryItemPage.setPageId(UUID.randomUUID().toString());
// libraryItemPage.setPageTitle("RecentDocument");
// return libraryItemPage;
// }
//
// private DocumentDetail generateStubDocumentDetail(String id) throws IllegalArgumentException {
//
// if (Objects.isNull(id)) {
// throw new IllegalArgumentException("id is null");
// }
//
// DocumentMeta documentMeta = new DocumentMeta();
// documentMeta.setId(id);
// documentMeta.setTitle("FakeDocument" + faker.book().title());
// documentMeta.setCreatedAt(faker.date().birthday());
// documentMeta.setUpdatedAt(faker.date().birthday()); // TODO-rca: 更新日のほうが古くなることがあるのでなんとかする?
// ArrayList<String> tagIds = new ArrayList<>();
//
// DocumentDetail documentDetail = new DocumentDetail();
// documentDetail.setMeta(documentMeta);
//// documentDetail.setPath(null); // TODO-rca: なんとかする
//// documentDetail.setAuthor(faker.name().fullName());
//// documentDetail.setRepository(null); // TODO-rca: なんとかする
// return documentDetail;
// }
//
// /**
// * 履歴ページを取得する
// * @param limit 取得するアイテム数
// * @return ページオブジェクト
// */
// @Override
// public ArrayList<ListItem> getRecentDocument(int limit) {
// return getRecentDocumentPage(limit).getListItems();
// }
//
// /**
// * 履歴ページを取得する
// * @param limit 取得するアイテム数
// * @param offset 取得するアイテムのオフセット
// * @return ページオブジェクト
// */
// @Override
// public ArrayList<ListItem> getRecentDocument(int limit, int offset) {
// return getRecentDocumentPage(limit).getListItems();
// }
//
// /**
// * ライブラリページを取得する
// * @param limit 取得するアイテム数
// * @return ページオブジェクト
// */
// @Override
// public LibraryItemPage getLibraryPage(int limit) {
// return generateStubLibraryItemPage(limit, null);
// }
//
// /**
// * ライブラリページを取得する
// * @param limit 取得するアイテム数
// * @param offset 取得するアイテムのオフセット
// * @return ページオブジェクト
// */
// @Override
// public LibraryItemPage getLibraryPage(int limit, int offset) {
// return generateStubLibraryItemPage(limit, null);
// }
//
// /**
// * ライブラリページを取得する
// * @param pageId ページID
// * @param limit 取得するアイテム数
// * @return ページオブジェクト
// */
// @Override
// public LibraryItemPage getLibraryPage(String pageId, int limit) {
// return generateStubLibraryItemPage(limit, pageId);
// }
//
// /**
// * ライブラリページを取得する
// * @param pageId ページID
// * @param limit 取得するアイテム数
// * @param offset 取得するアイテムのオフセット
// * @return ページオブジェクト
// */
// @Override
// public LibraryItemPage getLibraryPage(String pageId, int limit, int offset) {
// return generateStubLibraryItemPage(limit, pageId);
// }
//
// /**
// * ドキュメント詳細を取得する
// * @param id ドキュメントID
// * @return ドキュメント詳細オブジェクト
// */
// @Override
// public DocumentDetail getDocumentDetailById(String id) throws IllegalArgumentException {
// return generateStubDocumentDetail(id);
// }
//}
@@ -30,9 +30,10 @@ public class LacertaSearchStubImpl implements LacertaSearch {
*/
@Override
public ArrayList<ListItem> autoSearch(String query, int limit) {
logger.debug("SearchStub", "autoSearch");
logger.debug("SearchStub", "query: " + query);
return library.getLibraryPage(limit).getListItems();
// logger.debug("SearchStub", "autoSearch");
// logger.debug("SearchStub", "query: " + query);
// return library.getLibraryPage(limit).getListItems();
return null;
}
/**
@@ -44,8 +45,9 @@ public class LacertaSearchStubImpl implements LacertaSearch {
*/
@Override
public ArrayList<ListItem> autoSearch(String query, int limit, int offset) {
logger.debug("SearchStub", "autoSearch");
logger.debug("SearchStub", "query: " + query);
return library.getLibraryPage(limit, offset).getListItems();
// logger.debug("SearchStub", "autoSearch");
// logger.debug("SearchStub", "query: " + query);
// return library.getLibraryPage(limit, offset).getListItems();
return null;
}
}
@@ -7,7 +7,7 @@ import dagger.hilt.android.components.FragmentComponent;
import dagger.hilt.migration.DisableInstallInCheck;
import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.data.impl.LacertaLibraryStubImpl;
import one.nem.lacerta.data.impl.LacertaLibraryImpl;
import one.nem.lacerta.utils.LacertaLogger;
@Module
@@ -16,6 +16,6 @@ import one.nem.lacerta.utils.LacertaLogger;
abstract public class LacertaLibraryModule {
@Binds
public abstract LacertaLibrary bindLacertaLibrary(LacertaLibraryStubImpl impl);
public abstract LacertaLibrary bindLacertaLibrary(LacertaLibraryImpl impl);
}
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
android {
namespace 'one.nem.lacerta.feature.common'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
@@ -57,7 +57,8 @@ public class DebugMenuLibraryItemListPageFragment extends Fragment {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_debug_menu_library_item_list_page, container, false);
ArrayList<ListItem> listItems = lacertaLibrary.getRecentDocument(10);
// ArrayList<ListItem> listItems = lacertaLibrary.getRecentDocument(10);
ArrayList<ListItem> listItems = new ArrayList<>();
for (ListItem listItem : listItems) {
System.out.println(listItem.getTitle());
}
+3 -1
View File
@@ -5,7 +5,7 @@ plugins {
android {
namespace 'one.nem.lacerta.feature.home'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
@@ -57,4 +57,6 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation project(':component:common')
implementation project(':component:viewer')
}
@@ -0,0 +1,5 @@
package one.nem.lacerta.feature.home;
public interface DocumentSelectListener {
void onDocumentSelect(String documentId);
}
@@ -1,5 +1,6 @@
package one.nem.lacerta.feature.home;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@@ -9,6 +10,7 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@@ -23,10 +25,12 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.component.viewer.ViewerMainActivity;
import one.nem.lacerta.data.Document;
import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.model.ListItem;
@@ -67,18 +71,7 @@ public class HomeTopFragment extends Fragment {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home_top, container, false);
ArrayList<ListItem> recentDocument = lacertaLibrary.getRecentDocument(10);
Log.d("docs", Integer.toString(recentDocument.size()));
RecyclerView recyclerView = view.findViewById(R.id.home_item_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
ListItemAdapter listItemAdapter = new ListItemAdapter(recentDocument);
recyclerView.setAdapter(listItemAdapter);
setHasOptionsMenu(true);
return view;
}
@@ -86,31 +79,30 @@ public class HomeTopFragment extends Fragment {
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
CollapsingToolbarLayout collapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar);
Toolbar toolbar = view.findViewById(R.id.toolbar);
RecyclerView recyclerView = view.findViewById(R.id.home_item_recycler_view);
// Set the Toolbar
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
// Set the title of the CollapsingToolbarLayout
collapsingToolbarLayout.setTitle("Lacerta");
AppBarLayout appBarLayout = view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) {
// Collapsed
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getActivity(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer));
} else if (verticalOffset == 0) {
// Expanded
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getActivity(), one.nem.lacerta.shared.ui.R.color.colorSurface));
} else {
// Somewhere in between
// Here you can add a color transition if you want
}
}
ListItemAdapter listItemAdapter = new ListItemAdapter(documentId -> {
Log.d("HomeTopFragment", "onViewCreated: " + documentId);
Intent intent = new Intent(getContext(), ViewerMainActivity.class);
intent.putExtra("documentId", documentId);
startActivity(intent);
});
recyclerView.setAdapter(listItemAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
lacertaLibrary.getRecentDocument(10).thenAccept(listItems -> {
listItemAdapter.setListItems(listItems);
getActivity().runOnUiThread(() -> {
listItemAdapter.notifyItemRangeInserted(0, listItems.size());
});
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.drawer_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
@@ -1,6 +1,6 @@
package one.nem.lacerta.feature.home;
import android.media.Image;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -12,20 +12,28 @@ import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import one.nem.lacerta.component.viewer.ViewerMainActivity;
import one.nem.lacerta.model.ListItem;
public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListItemViewHolder>{
ArrayList<ListItem> listItems;
public ListItemAdapter(ArrayList<ListItem> listItems){
DocumentSelectListener listener;
public ListItemAdapter(DocumentSelectListener listener){
this.listItems = new ArrayList<>();
this.listener = listener;
}
public void setListItems(ArrayList<ListItem> listItems) {
this.listItems = listItems;
}
@NonNull
@Override
public ListItemAdapter.ListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(one.nem.lacerta.component.common.R.layout.common_library_list_item, parent, false);
View view = LayoutInflater.from(parent.getContext()).inflate(one.nem.lacerta.shared.ui.R.layout.common_list_item, parent, false);
return new ListItemViewHolder(view);
}
@@ -36,6 +44,12 @@ public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListIt
holder.icon.setColorFilter(one.nem.lacerta.shared.ui.R.color.colorOnSurface);
holder.title.setText(listItem.getTitle());
holder.description.setText(listItem.getDescription());
holder.itemView.setOnClickListener( v -> {
Intent intent = new Intent(v.getContext(), ViewerMainActivity.class);
intent.putExtra("documentId", listItem.getItemId());
v.getContext().startActivity(intent);
});
}
@Override
@@ -51,9 +65,9 @@ public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListIt
public ListItemViewHolder(@NonNull View itemView) {
super(itemView);
icon = itemView.findViewById(one.nem.lacerta.component.common.R.id.item_icon);
title = itemView.findViewById(one.nem.lacerta.component.common.R.id.item_title);
description = itemView.findViewById(one.nem.lacerta.component.common.R.id.item_description);
icon = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_icon);
title = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_title);
description = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_description);
}
}
}
@@ -1,50 +1,11 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorSurface">
android:layout_height="match_parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_item_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
app:contentScrim="@color/colorSecondaryContainer"
android:background="@color/colorSurface"
android:layout_width="match_parent"
android:layout_height="160dp"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:collapsedTitleGravity="start|center_vertical"
app:expandedTitleGravity="start|bottom"
app:expandedTitleMarginBottom="16dp"
app:expandedTitleMarginStart="16dp"
app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title="HOGE" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_item_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
android:layout_height="match_parent" />
</FrameLayout>
+3 -1
View File
@@ -5,7 +5,7 @@ plugins {
android {
namespace 'one.nem.lacerta.feature.library'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
@@ -51,5 +51,7 @@ dependencies {
implementation project(':data')
implementation project(':utils')
}
@@ -0,0 +1,6 @@
package one.nem.lacerta.feature.library;
public interface DocumentSelectListener {
void onFolderSelected(String folderId, String folderName);
void onDocumentSelected(String documentId, String documentName);
}
@@ -1,38 +0,0 @@
package one.nem.lacerta.feature.library;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
// LibraryArchiveFragment.java
//画面変移用のコード
//Fragmentへのデータの受け渡し機能
public class LibraryArchiveFragment extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_library_top);
// ここに入力された内容を表示する機能
TextView textView = findViewById(R.id.document_list);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 文字をタップしたときの処理
// 移動先のアクティビティを指定
Intent intent = new Intent(LibraryArchiveFragment.this, LibraryDocFragment.class);
// データを付加する
intent.putExtra("key_name", "value_data");
startActivity(intent);
}
});
}
}
@@ -0,0 +1,186 @@
package one.nem.lacerta.feature.library;
import android.app.AlertDialog;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.model.FragmentNavigation;
import one.nem.lacerta.utils.LacertaLogger;
/**
* A simple {@link Fragment} subclass.
* Use the {@link LibraryPageFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class LibraryPageFragment extends Fragment {
// Param
private String folderId;
@Inject
LacertaLibrary lacertaLibrary;
@Inject
LacertaLogger logger;
ListItemAdapter listItemAdapter;
int currentTotalItemCount = 0;
public LibraryPageFragment() {
// Required empty public constructor
}
public static LibraryPageFragment newInstance(String folderId) {
LibraryPageFragment fragment = new LibraryPageFragment();
Bundle args = new Bundle();
args.putString("folderId", folderId);
fragment.setArguments(args);
return fragment;
}
public static LibraryPageFragment newInstance() {
LibraryPageFragment fragment = new LibraryPageFragment();
Bundle args = new Bundle();
args.putString("folderId", null);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_library_top, container, false);
setHasOptionsMenu(true);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = view.findViewById(R.id.library_item_recycler_view);
this.listItemAdapter = new ListItemAdapter(new DocumentSelectListener() {
@Override
public void onFolderSelected(String folderId, String folderName) {
logger.debug("LibraryTopFragment", "Folder selected! folderId: " + folderId + ", folderName: " + folderName);
// 画面遷移
FragmentNavigation fragmentNavigation = (FragmentNavigation) getActivity();
assert fragmentNavigation != null;
fragmentNavigation.navigateToFragment(LibraryPageFragment.newInstance(folderId));
}
@Override
public void onDocumentSelected(String documentId, String documentName) {
Toast.makeText(getContext(), "Document selected! documentId: " + documentId + ", documentName: " + documentName, Toast.LENGTH_SHORT).show();
}
});
recyclerView.setAdapter(listItemAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
if (getArguments() != null) {
this.folderId = getArguments().getString("folderId");
}
if (this.folderId == null) { // Root
lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> {
logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
listItemAdapter.setLibraryItemPage(libraryItemPage);
getActivity().runOnUiThread(() -> {
// ActionBarのタイトルを変更する
getActivity().setTitle("ライブラリ");
// ActionBarに戻るボタンを非表示にする
// getActivity().getActionBar().setDisplayHomeAsUpEnabled(false);
listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1);
});
this.currentTotalItemCount = libraryItemPage.getListItems().size();
});
} else { // Root以外
lacertaLibrary.getLibraryPage(this.folderId, 10).thenAccept(libraryItemPage -> {
logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
listItemAdapter.setLibraryItemPage(libraryItemPage);
getActivity().runOnUiThread(() -> {
// ActionBarのタイトルを変更する
getActivity().setTitle(libraryItemPage.getPageTitle());
// ActionBarに戻るボタンを表示する
// getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1);
});
this.currentTotalItemCount = libraryItemPage.getListItems().size();
});
}
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.dir_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
// Selected
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_item_create_new_folder) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("フォルダの作成");
builder.setMessage("フォルダ名を入力してください");
final android.widget.EditText input = new android.widget.EditText(getContext());
input.setText("フォルダ名");
builder.setView(input);
builder.setPositiveButton("作成", (dialog, which) -> {
lacertaLibrary.createFolder(null, input.getText().toString()).thenAccept(folderId -> {
logger.debug("LibraryTopFragment", "folderId: " + folderId);
});
// Refresh
updateItem();
});
builder.setNegativeButton("キャンセル", (dialog, which) -> {
dialog.cancel();
});
builder.show();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void updateItem() {
lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> {
logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
getActivity().runOnUiThread(() -> {
listItemAdapter.notifyItemRangeRemoved(0, this.currentTotalItemCount - 1);
});
listItemAdapter.setLibraryItemPage(libraryItemPage);
getActivity().runOnUiThread(() -> {
listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1);
});
this.currentTotalItemCount = libraryItemPage.getListItems().size();
});
}
}
@@ -1,106 +0,0 @@
package one.nem.lacerta.feature.library;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.Document;
import one.nem.lacerta.model.document.DocumentMeta;
import one.nem.lacerta.model.document.tag.DocumentTag;
/**
* A simple {@link Fragment} subclass.
* Use the {@link LibraryTopFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class LibraryTopFragment extends Fragment {
// @Inject
// Document document;
// 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 LibraryTopFragment() {
// 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 LibraryTopFragment.
*/
// TODO: Rename and change types and number of parameters
public static LibraryTopFragment newInstance(String param1, String param2) {
LibraryTopFragment fragment = new LibraryTopFragment();
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_library_top, container, false);
// Use view.findViewById instead of findViewById
RecyclerView documentRecyclerView = view.findViewById(R.id.document_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
documentRecyclerView.setLayoutManager(layoutManager);
//データを取得
// List<DocumentMeta> metas = document.getAllDocumentMetas(100);
// Toast.makeText(getContext(), "Documents: " + Integer.toString(metas.size()), Toast.LENGTH_LONG).show();
// Create and set the adapter
// DocumentAdapter adapter = new DocumentAdapter(metas);
// documentRecyclerView.setAdapter(adapter);
// Use a LinearLayoutManager to specify the layout
return view;
}
}
@@ -0,0 +1,78 @@
package one.nem.lacerta.feature.library;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType;
public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListItemViewHolder>{
LibraryItemPage libraryItemPage;
DocumentSelectListener listener;
public ListItemAdapter(DocumentSelectListener listener) {
this.listener = listener;
}
public void setLibraryItemPage(LibraryItemPage libraryItemPage) {
this.libraryItemPage = libraryItemPage;
}
@NonNull
@Override
public ListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(one.nem.lacerta.shared.ui.R.layout.common_list_item, parent, false);
return new ListItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ListItemViewHolder holder, int position) {
ListItem listItem = libraryItemPage.getListItems().get(position);
holder.icon.setImageResource(listItem.getItemType().getIconId());
holder.icon.setColorFilter(one.nem.lacerta.shared.ui.R.color.colorOnSurface);
holder.title.setText(listItem.getTitle());
holder.description.setText(listItem.getDescription());
holder.itemView.setOnClickListener( v -> {
if (listItem.getItemType() == ListItemType.ITEM_TYPE_DOCUMENT) {
listener.onDocumentSelected(listItem.getItemId(), listItem.getTitle());
}
else if (listItem.getItemType() == ListItemType.ITEM_TYPE_FOLDER) {
listener.onFolderSelected(listItem.getItemId(), listItem.getTitle());
}
});
}
@Override
public int getItemCount() {
return this.libraryItemPage == null ? 0
: this.libraryItemPage.getListItems() == null ? 0 : this.libraryItemPage.getListItems().size();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder{
ImageView icon;
TextView title;
TextView description;
public ListItemViewHolder(@NonNull View itemView) {
super(itemView);
icon = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_icon);
title = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_title);
description = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_description);
}
}
}
@@ -1,32 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout 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"
android:theme="@style/Theme.Lacerta"
tools:context=".LibraryTopFragment">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryContainer"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:title="Library"
app:titleTextColor="@color/colorOnPrimaryContainer" />
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/document_list"
android:id="@+id/library_item_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tool_bar" />
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_item_create_new_folder"
android:icon="@drawable/developer_mode_24px"
android:title="@string/app_name"
app:showAsAction="ifRoom"/> <!-- TODO-rca: change this -->
</menu>
@@ -6,7 +6,7 @@
app:startDestination="@id/feature_library_top_fragment">
<fragment
android:id="@+id/feature_library_top_fragment"
android:name="one.nem.lacerta.feature.library.LibraryTopFragment"
android:name="one.nem.lacerta.feature.library.LibraryPageFragment"
android:label="fragment_library_top"
tools:layout="@layout/fragment_library_top" />
</navigation>
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
android {
namespace 'one.nem.lacerta.feature.scan'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
android {
namespace 'one.nem.lacerta.feature.search'
compileSdk 33
compileSdk 34
defaultConfig {
minSdk 26
+1
View File
@@ -0,0 +1 @@
/build
+48
View File
@@ -0,0 +1,48 @@
plugins {
alias(libs.plugins.com.android.library)
}
android {
namespace 'one.nem.lacerta.setting'
compileSdk 34
defaultConfig {
minSdk 26
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation libs.androidx.appcompat
implementation libs.com.google.android.material
testImplementation libs.junit
androidTestImplementation libs.androidx.test.ext.junit
androidTestImplementation libs.androidx.test.espresso.core
// Navigation
implementation libs.navigation.fragment
implementation libs.navigation.ui
implementation libs.navigation.dynamic.features.fragment
// DI
implementation libs.com.google.dagger.hilt.android
annotationProcessor libs.com.google.dagger.hilt.compiler
// shared
implementation project(':shared:ui')
}
View File
Whitespace-only changes.
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,26 @@
package one.nem.lacerta.setting;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("one.nem.lacerta.setting.test", appContext.getPackageName());
}
}
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,63 @@
package one.nem.lacerta.setting;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import one.nem.lacerta.setting.model.SettingListItem;
public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListItemViewHolder>{
ArrayList<SettingListItem> listItems;
public ListItemAdapter(ArrayList<SettingListItem> listItems){
this.listItems = listItems;
}
@NonNull
@Override
public ListItemAdapter.ListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(one.nem.lacerta.shared.ui.R.layout.common_list_item, parent, false);
return new ListItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ListItemAdapter.ListItemViewHolder holder, int position) {
SettingListItem listItem = listItems.get(position);
holder.icon.setImageDrawable(listItem.getIcon());
holder.icon.setColorFilter(one.nem.lacerta.shared.ui.R.color.colorOnSurface);
holder.title.setText(listItem.getTitle());
holder.description.setText(listItem.getDescription());
holder.itemView.setOnClickListener( v -> {
Navigation.findNavController(v).navigate(listItem.getDestination());
});
}
@Override
public int getItemCount() {
return listItems.size();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder{
ImageView icon;
TextView title;
TextView description;
public ListItemViewHolder(@NonNull View itemView) {
super(itemView);
icon = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_icon);
title = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_title);
description = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_description);
}
}
}
@@ -0,0 +1,43 @@
package one.nem.lacerta.setting;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingAboutPageFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class SettingAboutPageFragment extends Fragment {
public SettingAboutPageFragment() {
// Required empty public constructor
}
public static SettingAboutPageFragment newInstance() {
SettingAboutPageFragment fragment = new SettingAboutPageFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_setting_about_page, container, false);
return view;
}
}
@@ -0,0 +1,40 @@
package one.nem.lacerta.setting;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingDataPageFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class SettingDataPageFragment extends Fragment {
public SettingDataPageFragment() {
// Required empty public constructor
}
public static SettingDataPageFragment newInstance() {
SettingDataPageFragment fragment = new SettingDataPageFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_setting_data_page, container, false);
}
}
@@ -0,0 +1,40 @@
package one.nem.lacerta.setting;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingDisplayPageFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class SettingDisplayPageFragment extends Fragment {
public SettingDisplayPageFragment() {
// Required empty public constructor
}
public static SettingDisplayPageFragment newInstance() {
SettingDisplayPageFragment fragment = new SettingDisplayPageFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_setting_display_page, container, false);
}
}
@@ -0,0 +1,41 @@
package one.nem.lacerta.setting;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingScanPageFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class SettingScanPageFragment extends Fragment {
public SettingScanPageFragment() {
// Required empty public constructor
}
public static SettingScanPageFragment newInstance() {
SettingScanPageFragment fragment = new SettingScanPageFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_setting_scan_page, container, false);
}
}
@@ -0,0 +1,92 @@
package one.nem.lacerta.setting;
import android.os.Bundle;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import one.nem.lacerta.setting.model.SettingListItem;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingTopFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class SettingTopFragment extends Fragment {
public SettingTopFragment() {
// Required empty public constructor
}
public static SettingTopFragment newInstance() {
SettingTopFragment fragment = new SettingTopFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_setting_top, container, false);
// Setting items
ArrayList<SettingListItem> settingListItems = new ArrayList<>();
settingListItems.add(
new SettingListItem(
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_display_title),
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_display_description),
ContextCompat.getDrawable(getContext(), one.nem.lacerta.shared.ui.R.drawable.palette_24px),
R.id.action_settingTopFragment_to_settingDisplayPageFragment
)
);
settingListItems.add(
new SettingListItem(
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_data_title),
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_data_description),
ContextCompat.getDrawable(getContext(), one.nem.lacerta.shared.ui.R.drawable.settings_backup_restore_24px),
R.id.action_settingTopFragment_to_settingDataPageFragment
)
);
settingListItems.add(
new SettingListItem(
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_scan_title),
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_scan_description),
ContextCompat.getDrawable(getContext(), one.nem.lacerta.shared.ui.R.drawable.document_scanner_24px),
R.id.action_settingTopFragment_to_settingScanPageFragment
)
);
settingListItems.add(
new SettingListItem(
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_about_title),
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_about_description),
ContextCompat.getDrawable(getContext(), one.nem.lacerta.shared.ui.R.drawable.info_24px),
R.id.action_settingTopFragment_to_settingAboutPageFragment
)
);
// Init RecyclerView
RecyclerView recyclerView = view.findViewById(R.id.setting_item_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new ListItemAdapter(settingListItems));
return view;
}
}
@@ -0,0 +1,34 @@
package one.nem.lacerta.setting.model;
import android.graphics.drawable.Drawable;
public class SettingListItem {
String title;
String description;
Drawable icon;
int destination;
public SettingListItem(String title, String description, Drawable icon, int destination) {
this.title = title;
this.description = description;
this.icon = icon;
this.destination = destination;
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public Drawable getIcon() {
return icon;
}
public int getDestination() {
return destination;
}
}
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingAboutPageFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingDataPageFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingDisplayPageFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingScanPageFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
@@ -0,0 +1,11 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/setting_item_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/feature_setting_navigation"
app:startDestination="@id/settingTopFragment">
<fragment
android:id="@+id/settingTopFragment"
android:name="one.nem.lacerta.setting.SettingTopFragment"
android:label="SettingTopFragment" >
<action
android:id="@+id/action_settingTopFragment_to_settingAboutPageFragment"
app:destination="@id/settingAboutPageFragment"
app:enterAnim="@anim/slide_from_right"
app:exitAnim="@anim/slide_to_left"
app:popEnterAnim="@anim/slide_from_left"
app:popExitAnim="@anim/slide_to_right" />
<action
android:id="@+id/action_settingTopFragment_to_settingDisplayPageFragment"
app:destination="@id/settingDisplayPageFragment"
app:enterAnim="@anim/slide_from_right"
app:exitAnim="@anim/slide_to_left"
app:popEnterAnim="@anim/slide_from_left"
app:popExitAnim="@anim/slide_to_right" />
<action
android:id="@+id/action_settingTopFragment_to_settingDataPageFragment"
app:destination="@id/settingDataPageFragment"
app:enterAnim="@anim/slide_from_right"
app:exitAnim="@anim/slide_to_left"
app:popEnterAnim="@anim/slide_from_left"
app:popExitAnim="@anim/slide_to_right" />
<action
android:id="@+id/action_settingTopFragment_to_settingScanPageFragment"
app:destination="@id/settingScanPageFragment"
app:enterAnim="@anim/slide_from_right"
app:exitAnim="@anim/slide_to_left"
app:popEnterAnim="@anim/slide_from_left"
app:popExitAnim="@anim/slide_to_right" />
</fragment>
<fragment
android:id="@+id/settingAboutPageFragment"
android:name="one.nem.lacerta.setting.SettingAboutPageFragment"
android:label="fragment_setting_about_page"
tools:layout="@layout/fragment_setting_about_page" />
<fragment
android:id="@+id/settingDataPageFragment"
android:name="one.nem.lacerta.setting.SettingDataPageFragment"
android:label="fragment_setting_data_page"
tools:layout="@layout/fragment_setting_data_page" />
<fragment
android:id="@+id/settingDisplayPageFragment"
android:name="one.nem.lacerta.setting.SettingDisplayPageFragment"
android:label="fragment_setting_display_page"
tools:layout="@layout/fragment_setting_display_page" />
<fragment
android:id="@+id/settingScanPageFragment"
android:name="one.nem.lacerta.setting.SettingScanPageFragment"
android:label="fragment_setting_scan_page"
tools:layout="@layout/fragment_setting_scan_page" />
</navigation>
@@ -0,0 +1,4 @@
<resources>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
@@ -0,0 +1,17 @@
package one.nem.lacerta.setting;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
@@ -0,0 +1,7 @@
package one.nem.lacerta.model;
import androidx.fragment.app.Fragment;
public interface FragmentNavigation {
void navigateToFragment(Fragment fragment);
}
@@ -1,5 +1,7 @@
package one.nem.lacerta.model;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
@@ -29,11 +31,26 @@ public class PublicPath {
private void resolveInternal(String path) {
if (path.equals("..")) {
this.path.remove(this.path.size() - 1);
} else if (path.equals(".")) {
// do nothing
} else {
add(path);
this.path.add(path);
}
}
public PublicPath parse(String path) {
if (path.startsWith("/")) {
this.path.clear();
path = path.substring(1);
}
String[] pathArray = path.split("/");
for (String p : pathArray) {
Log.d("PublicPath", "parse: " + p);
resolveInternal(p);
}
return this;
}
public PublicPath resolve(String path) {
resolveInternal(path);
return this;
@@ -0,0 +1,30 @@
package one.nem.lacerta.model.pref;
public enum FeatureSwitchOverride {
ENABLE_DEBUG_MENU("enableDebugMenu"),
ENABLE_SEARCH("enableSearch"),
SHOW_DISPLAY_MENU("showDisplayMenu"),
SHOW_DATA_MENU("showDataMenu"),
SHOW_SCAN_MENU("showScanMenu");
private final String key;
FeatureSwitchOverride(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public static FeatureSwitchOverride fromKey(String key) {
for (FeatureSwitchOverride value : values()) {
if (value.getKey().equals(key)) {
return value;
}
}
return null;
}
}
@@ -7,13 +7,13 @@ import one.nem.lacerta.model.document.DocumentDetail;
public interface DocumentProcessor {
// ページ操作
void addNewPageToLast(Bitmap bitmap) throws Exception;
void addNewPagesToLast(Bitmap[] bitmaps) throws Exception;
void insertPageAtIndex(Bitmap bitmap, int index) throws Exception;
void removePageAtIndex(int index) throws Exception;
DocumentProcessor addNewPageToLast(Bitmap bitmap) throws Exception;
DocumentProcessor addNewPagesToLast(Bitmap[] bitmaps) throws Exception;
DocumentProcessor insertPageAtIndex(Bitmap bitmap, int index) throws Exception;
DocumentProcessor removePageAtIndex(int index) throws Exception;
// 更新
void updatePageAtIndex(Bitmap bitmap, int index);
DocumentProcessor updatePageAtIndex(Bitmap bitmap, int index);
// ページ取得
Bitmap getPageAtIndex(int index);
@@ -70,7 +70,7 @@ public class DocumentProcessorImpl implements DocumentProcessor{
@Override
public void addNewPageToLast(Bitmap bitmap) throws Exception{
public DocumentProcessor addNewPageToLast(Bitmap bitmap) throws Exception{
logger.debug("addNewPageToLast", "called");
String filename = UUID.randomUUID().toString() + ".png"; // TODO-rca: 拡張子を動的にする
@@ -85,19 +85,23 @@ public class DocumentProcessorImpl implements DocumentProcessor{
logger.info("addNewPageToLast", "finished");
logger.info("addNewPageToLast", "filename: " + filename);
return this;
}
@Override
public void addNewPagesToLast(Bitmap[] bitmaps) throws Exception{
public DocumentProcessor addNewPagesToLast(Bitmap[] bitmaps) throws Exception{
logger.debug("addNewPagesToLast", "called");
for (Bitmap bitmap : bitmaps) {
addNewPageToLast(bitmap);
} // TODO-rca: 効率悪いので改善する
return this;
}
@Override
public void insertPageAtIndex(Bitmap bitmap, int index) throws Exception {
public DocumentProcessor insertPageAtIndex(Bitmap bitmap, int index) throws Exception {
logger.debug("addNewPageAfterIndex", "called");
String filename = UUID.randomUUID().toString() + ".png"; // TODO-rca: 拡張子を動的にする
@@ -109,16 +113,18 @@ public class DocumentProcessorImpl implements DocumentProcessor{
this.documentDetail.getPages().add(index, page);
lacertaVcs.insertPage(index, filename);
return this;
}
@Override
public void removePageAtIndex(int index) {
public DocumentProcessor removePageAtIndex(int index) {
return null;
}
@Override
public void updatePageAtIndex(Bitmap bitmap, int index) {
public DocumentProcessor updatePageAtIndex(Bitmap bitmap, int index) {
return null;
}
@Override
+1
View File
@@ -31,3 +31,4 @@ include ':model'
include ':processor'
include ':shared:ui'
include ':vcs'
include ':feature:setting'
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
</set>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
</set>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
</set>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="100%p"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
android:duration="120" />
</set>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@color/colorOnBackground"
android:pathData="M90,230L90,50L270,50L270,110L150,110L150,230L90,230ZM810,230L810,110L690,110L690,50L870,50L870,230L810,230ZM90,910L90,730L150,730L150,850L270,850L270,910L90,910ZM690,910L690,850L810,850L810,730L870,730L870,910L690,910ZM270,717.69Q270,722.31 273.85,726.15Q277.69,730 282.31,730L677.69,730Q682.31,730 686.15,726.15Q690,722.31 690,717.69L690,242.31Q690,237.69 686.15,233.85Q682.31,230 677.69,230L282.31,230Q277.69,230 273.85,233.85Q270,237.69 270,242.31L270,717.69ZM282.31,790Q252,790 231,769Q210,748 210,717.69L210,242.31Q210,212 231,191Q252,170 282.31,170L677.69,170Q708,170 729,191Q750,212 750,242.31L750,717.69Q750,748 729,769Q708,790 677.69,790L282.31,790ZM370,390L590,390L590,330L370,330L370,390ZM370,510L590,510L590,450L370,450L370,510ZM370,630L590,630L590,570L370,570L370,630ZM270,717.69L270,242.31Q270,237.69 270,233.85Q270,230 270,230L270,230Q270,230 270,233.85Q270,237.69 270,242.31L270,717.69Q270,722.31 270,726.15Q270,730 270,730L270,730Q270,730 270,726.15Q270,722.31 270,717.69Z"/>
</vector>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@color/colorOnBackground"
android:pathData="M450,670L510,670L510,440L450,440L450,670ZM480,371.54Q493.73,371.54 503.02,362.25Q512.31,352.96 512.31,339.23Q512.31,325.5 503.02,316.21Q493.73,306.92 480,306.92Q466.27,306.92 456.98,316.21Q447.69,325.5 447.69,339.23Q447.69,352.96 456.98,362.25Q466.27,371.54 480,371.54ZM480.07,860Q401.23,860 331.86,830.08Q262.49,800.16 211.18,748.87Q159.87,697.58 129.93,628.24Q100,558.9 100,480.07Q100,401.23 129.92,331.86Q159.84,262.49 211.13,211.18Q262.42,159.87 331.76,129.93Q401.1,100 479.93,100Q558.77,100 628.14,129.92Q697.51,159.84 748.82,211.13Q800.13,262.42 830.07,331.76Q860,401.1 860,479.93Q860,558.77 830.08,628.14Q800.16,697.51 748.87,748.82Q697.58,800.13 628.24,830.07Q558.9,860 480.07,860ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
</vector>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@color/colorOnBackground"
android:pathData="M479.23,860Q401.46,860 332.31,830.04Q263.15,800.08 211.54,748.46Q159.92,696.84 129.96,627.5Q100,558.15 100,480Q100,400.85 130.77,331.5Q161.54,262.16 214.35,210.85Q267.15,159.54 337.89,129.77Q408.62,100 488.77,100Q563.77,100 630.92,125.58Q698.08,151.16 748.88,196.39Q799.69,241.62 829.84,303.89Q860,366.15 860,438.92Q860,542.77 798.27,601.38Q736.54,660 640,660L567.54,660Q550.46,660 540.23,671.15Q530,682.31 530,697.54Q530,716.08 545,736.08Q560,756.08 560,782Q560,821.61 538.08,840.81Q516.15,860 479.23,860ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM260,510Q281.38,510 295.69,495.69Q310,481.38 310,460Q310,438.62 295.69,424.31Q281.38,410 260,410Q238.62,410 224.31,424.31Q210,438.62 210,460Q210,481.38 224.31,495.69Q238.62,510 260,510ZM380,350Q401.38,350 415.69,335.69Q430,321.38 430,300Q430,278.62 415.69,264.31Q401.38,250 380,250Q358.62,250 344.31,264.31Q330,278.62 330,300Q330,321.38 344.31,335.69Q358.62,350 380,350ZM580,350Q601.38,350 615.69,335.69Q630,321.38 630,300Q630,278.62 615.69,264.31Q601.38,250 580,250Q558.62,250 544.31,264.31Q530,278.62 530,300Q530,321.38 544.31,335.69Q558.62,350 580,350ZM700,510Q721.38,510 735.69,495.69Q750,481.38 750,460Q750,438.62 735.69,424.31Q721.38,410 700,410Q678.62,410 664.31,424.31Q650,438.62 650,460Q650,481.38 664.31,495.69Q678.62,510 700,510ZM479.23,800Q489,800 494.5,795.19Q500,790.39 500,782Q500,768 485,750.54Q470,733.08 470,695.85Q470,653.08 499,626.54Q528,600 570,600L640,600Q710.62,600 755.31,558.61Q800,517.23 800,438.92Q800,317.54 706.92,238.77Q613.85,160 488.77,160Q351.61,160 255.81,253Q160,346 160,480Q160,613 253.5,706.5Q347,800 479.23,800Z"/>
</vector>
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@color/colorOnBackground"
android:pathData="M479.23,540Q454.69,540 436.96,522.27Q419.23,504.54 419.23,480Q419.23,455.46 436.96,437.73Q454.69,420 479.23,420Q503.77,420 521.5,437.73Q539.23,455.46 539.23,480Q539.23,504.54 521.5,522.27Q503.77,540 479.23,540ZM479.23,820Q348.69,820 252.46,734.27Q156.23,648.54 141.62,520L202.85,520Q218,623.61 296.27,691.81Q374.54,760 479.23,760Q596.23,760 677.73,678.5Q759.23,597 759.23,480Q759.23,363 677.73,281.5Q596.23,200 479.23,200Q413.69,200 356.39,229.11Q299.08,258.23 257.69,309.23L362.31,309.23L362.31,369.23L159.23,369.23L159.23,166.15L219.23,166.15L219.23,260.92Q267.92,203.46 335.85,171.73Q403.77,140 479.23,140Q550.03,140 611.86,166.77Q673.69,193.54 719.69,239.54Q765.69,285.54 792.46,347.36Q819.23,409.19 819.23,479.98Q819.23,550.77 792.46,612.61Q765.69,674.46 719.69,720.46Q673.69,766.46 611.86,793.23Q550.03,820 479.23,820Z"/>
</vector>
@@ -3,13 +3,14 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
android:paddingHorizontal="24dp"
android:paddingVertical="16dp">
<ImageView
android:id="@+id/item_icon"
android:layout_width="32dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -42,7 +43,7 @@
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="Placeholder Description"
android:textColor="@color/colorOnSurface"
android:textColor="@color/colorOnSurfaceSecondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/item_title" />
@@ -28,4 +28,5 @@
<!-- indicator icon background -->
<color name="colorIndicator">@color/material_dynamic_secondary70</color>
<color name="colorOnSurfaceSecondary">@color/material_dynamic_neutral_variant30</color>
</resources>
@@ -25,4 +25,8 @@
<color name="colorSurfaceInverse">#313033</color>
<color name="colorOnSurfaceInverse">#F4EFF4</color>
<color name="colorPrimaryInverse">#D0BCFF</color>
<!-- indicator icon background -->
<color name="colorIndicator">#d2d4bc</color>
<color name="colorOnSurfaceSecondary">#49454F</color>
</resources>
@@ -27,4 +27,5 @@
<!-- indicator icon background -->
<color name="colorIndicator">@color/material_dynamic_secondary80</color>
<color name="colorOnSurfaceSecondary">@color/material_dynamic_neutral_variant30</color>
</resources>
@@ -31,6 +31,5 @@
<item name="android:windowLightNavigationBar">true</item>
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>
+1
View File
@@ -27,4 +27,5 @@
<color name="colorPrimaryInverse">#B8D321</color>
<!-- indicator icon background -->
<color name="colorIndicator">#d2d4bc</color>
<color name="colorOnSurfaceSecondary">#46483B</color>
</resources>
+15
View File
@@ -13,6 +13,21 @@
<!-- debug -->
<string name="debug_menu_title">デバッグメニュー</string>
<!-- setting -->
<string name="setting_title">設定</string>
<string name="setting_top_scan_title">スキャン</string>
<string name="setting_top_scan_description">画質, 保存先</string>
<string name="setting_top_display_title">表示</string>
<string name="setting_top_display_description">テーマ, フォントサイズ</string>
<string name="setting_top_data_title">データ</string>
<string name="setting_top_data_description">バックアップ, リストア</string>
<string name="setting_top_about_title">このアプリについて</string>
<string name="setting_top_about_description">バージョン情報</string>
<!-- common -->
<string name="placeholder">Placeholder(TODO: Replace)</string>
@@ -6,6 +6,7 @@ import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.ArrayList;
import java.util.List;
import one.nem.lacerta.source.database.entity.DocumentEntity;
@@ -4,6 +4,9 @@ import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.ArrayList;
import java.util.List;
import one.nem.lacerta.source.database.entity.FolderEntity;
@Dao
@@ -15,6 +18,9 @@ public interface FolderDao {
@Query("SELECT * FROM Folder WHERE public_path = :publicPath")
FolderEntity findByPublicPath(String publicPath);
@Query("SELECT * FROM Folder WHERE public_path = :publicPath LIMIT :limit")
List<FolderEntity> findByPublicPathWithLimit(String publicPath, int limit);
@Insert
void insert(FolderEntity folderEntity);
@@ -37,7 +37,11 @@ public class FileManagerImpl implements FileManager {
@AssistedInject
public FileManagerImpl(LacertaLogger logger, @Assisted Path rootDir) {
this.logger = logger;
if (rootDir == null) {
throw new IllegalArgumentException("rootDir must not be null");
}
this.rootDir = rootDir;
this.path = rootDir;
}
// for generate new instance
@@ -62,6 +66,10 @@ public class FileManagerImpl implements FileManager {
try {
resolvedPath = resolvedPath.resolve(pathPart);
} catch (Exception e) {
logger.error("resolveStringPath", e.getMessage());
logger.debug("resolveStringPath", "this.path: " + this.path);
logger.debug("resolveStringPath", "pathPart: " + pathPart);
logger.debug("resolveStringPath", "resolvedPath: " + resolvedPath);
throw new IOException("Invalid path: " + path);
}
}
@@ -0,0 +1,19 @@
package one.nem.lacerta.utils;
public class FeatureSwitch {
public static class Meta {
public static boolean canOverrideSwitch = false;
}
public static class FeatureMaster {
public static boolean enableSearch = false;
public static boolean enableDebugMenu = false;
}
public static class Setting {
public static boolean showDisplayMenu = false;
public static boolean showDataMenu = false;
public static boolean showScanMenu = false;
}
}
@@ -20,7 +20,9 @@ public class DeviceInfoUtilsImpl implements DeviceInfoUtils {
@Override
public Path getExternalStorageDirectory() {
// TODO-rca: 結果がnullだった場合の処理を追加する?
if (applicationContext.getExternalFilesDir(null) == null) {
throw new RuntimeException("applicationContext.getExternalFilesDir(null) is null");
}
return Objects.requireNonNull(applicationContext.getExternalFilesDir(null)).toPath();
}
@@ -31,7 +33,9 @@ public class DeviceInfoUtilsImpl implements DeviceInfoUtils {
@Override
public Path getExternalStorageDirectory(String type) {
// TODO-rca: 結果がnullだった場合の処理を追加する?
if(applicationContext.getExternalFilesDir(type) == null) {
throw new RuntimeException("applicationContext.getExternalFilesDir(" + type + ") is null");
}
return Objects.requireNonNull(applicationContext.getExternalFilesDir(type)).toPath();
}
@@ -4,13 +4,17 @@ package one.nem.lacerta.utils.impl;
import android.content.Context;
import android.content.SharedPreferences;
import javax.inject.Inject;
import dagger.hilt.android.qualifiers.ApplicationContext;
import one.nem.lacerta.model.pref.FeatureSwitchOverride;
import one.nem.lacerta.utils.repository.SharedPrefUtils;
public class SharedPrefUtilsImpl implements SharedPrefUtils{
private final Context applicationContext;
@Inject
public SharedPrefUtilsImpl(@ApplicationContext Context applicationContext) {
this.applicationContext = applicationContext;
}
@@ -26,4 +30,34 @@ public class SharedPrefUtilsImpl implements SharedPrefUtils{
// Editorの取得
return applicationContext.getSharedPreferences(name, Context.MODE_PRIVATE).edit();
}
@Override
public SharedPreferences getSharedPreferences(String name) {
return applicationContext.getSharedPreferences(name, Context.MODE_PRIVATE);
}
@Override
public SharedPreferences getSharedPreferences() {
return applicationContext.getSharedPreferences("common", Context.MODE_PRIVATE); // TODO-rca: 決め打ちやめる?
}
@Override
public boolean getFeatureSwitchOverride(FeatureSwitchOverride featureSwitchOverride) {
return getSharedPreferences().getBoolean(featureSwitchOverride.getKey(), false);
}
@Override
public void setFeatureSwitchOverride(FeatureSwitchOverride featureSwitchOverride, boolean value) {
getEditor().putBoolean(featureSwitchOverride.getKey(), value).apply();
}
@Override
public boolean getIsFirstLaunch() {
return getSharedPreferences().getBoolean("isFirstLaunch", true);
}
@Override
public void setIsFirstLaunch(boolean value) {
getEditor().putBoolean("isFirstLaunch", value).apply();
}
}
@@ -17,6 +17,8 @@ import one.nem.lacerta.utils.LacertaLogger;
public class XmlMetaParserImpl implements XmlMetaParser{
String TAG = getClass().getSimpleName();
@Inject
LacertaLogger logger;
@@ -35,13 +37,18 @@ public class XmlMetaParserImpl implements XmlMetaParser{
meta.setRevisionId(rootElement.getElementsByTagName("revisionId").item(0).getTextContent());
ArrayList<XmlMetaPageModel> pages = new ArrayList<>();
for(int i = 0; i < rootElement.getElementsByTagName("pages").getLength(); i++) {
for (int i = 0; i < rootElement.getElementsByTagName("page").getLength(); i++) {
Element pageElement = (Element) rootElement.getElementsByTagName("page").item(i);
XmlMetaPageModel page = new XmlMetaPageModel();
page.setFilename(pageElement.getElementsByTagName("filename").item(0).getTextContent());
pages.add(page);
}
logger.debug(TAG, "Parsed Meta: " + meta.getRevisionId() + " " + pages.size() + " pages.");
for (XmlMetaPageModel page : pages) {
logger.debug(TAG, "\tPage: " + page.getFilename());
}
meta.setPages(pages);
return meta;
@@ -2,6 +2,8 @@ package one.nem.lacerta.utils.repository;
import android.content.SharedPreferences;
import one.nem.lacerta.model.pref.FeatureSwitchOverride;
public interface SharedPrefUtils {
// Shared preferences editorの取得
@@ -10,4 +12,15 @@ public interface SharedPrefUtils {
// TODO-rca: 名称をenumで管理する?
SharedPreferences.Editor getEditor(String name);
SharedPreferences getSharedPreferences(String name);
SharedPreferences getSharedPreferences();
boolean getFeatureSwitchOverride(FeatureSwitchOverride featureSwitchOverride);
void setFeatureSwitchOverride(FeatureSwitchOverride featureSwitchOverride, boolean value);
boolean getIsFirstLaunch();
void setIsFirstLaunch(boolean value);
}