Compare commits

..
2 Commits
Author SHA1 Message Date
r-ca 65c6ca77ed Works 2024-01-22 13:41:55 +09:00
r-ca f02440348b レイアウト復元 2024-01-22 13:31:35 +09:00
77 changed files with 457 additions and 1656 deletions

No files matched your search

+32 -17
View File
@@ -1,10 +1,8 @@
# Lacerta # Lacerta
学習に便利な機能とGit-like VCSを持ったドキュメントスキャナ (Work In Progress) WIP
(グループワーク)
## モジュール設計 ## モジュール設計
![Untitled Diagram(2)(1) drawio(1)](https://github.com/lacerta-doc/Lacerta/assets/66072112/f9b9c40f-bed0-4ade-95c1-50e28df68f35)
![Untitled Diagram(2)](https://github.com/lacerta-doc/Lacerta/assets/66072112/9daabaca-5cdc-49f8-ac66-196c588a47c9)
## メモ ## メモ
- アイコン: Google Material Icons https://fonts.google.com/icons (Weight:300, Grade:0, Optical size: 24px) - アイコン: Google Material Icons https://fonts.google.com/icons (Weight:300, Grade:0, Optical size: 24px)
@@ -13,28 +11,45 @@
### モジュール一覧 ### モジュール一覧
- `component` : コンポーネント - `component` : コンポーネント
- `common` : 共通コンポーネント - `common` : 共通コンポーネント
- `scanner` : スキャナー - UIの中で共通で使う要素(メニューアイテムとか)
- `scanner` : スキャナー
- スキャナーの実装
- `viewer` : ビューワー - `viewer` : ビューワー
- `data` : UIからデータを取得/保存するためのラッパーモジュール - ドキュメントビューワーの実装
- `data` : データ
- UIからデータを取得/保存するためのラッパーモジュール
- `Document` : ドキュメント関係
- WIP(JavaDocを参照してください, 余裕があったら追記します)
- `feature` : 機能モジュール(ナビゲーションからみた機能で分割) - `feature` : 機能モジュール(ナビゲーションからみた機能で分割)
- `common`: 共通機能 - `common`: 共通機能
- 設定画面とか、どこからでも呼ばれうる画面
- `debug`: デバッグメニュー - `debug`: デバッグメニュー
- `home`: ホーム画面 - `home`: ホーム画面
- `library`: ライブラリ画面 - `library`: ライブラリ画面
- `scan`: スキャン画面 (廃止予定) - `scan`: スキャン画面
- `search`: 検索画面 - `search`: 検索画面
- `model` : データモデルをまとめたモジュール - `model` : モデル
- `processor` : プロセッサ(例: `DocumentProcessor` : ドキュメント処理(ドキュメントにページを追加したり更新したり)) - データモデルをまとめたモジュール (WIP)
- `shared`: 共有リソース - `document` : ドキュメント
- `ui`: UI要素(Theme, Drawable, Colorなど) - `meta` : メタデータ
- `source` : ソース(DB/FileManagerなど) - `processor` : プロセッサ
- `utils` : ユーティリティ(ちょっとしたユーティリティをまとめたモジュール) - いくつかの処理をまとめたモジュール
- `DocumentProcessor` : ドキュメント処理(ドキュメントにページを追加したり更新したり)
- `shared` :
- 共有リソース
- `source` : ソース
- (バックエンドが使うのでとりあえず後回し、フロントから直接操作することは絶対にありません)
- `utils` : ユーティリティ
- ちょっとしたユーティリティをまとめたモジュール
- `LacertaLogger` : ロガー
- `XmlMetaParser` : XMLメタデータパーサー(フロントから直接操作することは絶対にありません)
## コーディング規則/推奨(WIP) ## コーディング規則/推奨(WIP)
### 規則
- `// TODO`コメントには任意のsuffixを付ける - `// TODO`コメントには任意のsuffixを付ける
- 全員が同じ`// TODO:`を使っていると検索がむずかしくなるため - 全員が同じ`// TODO:`を使っていると検索がむずかしくなるため
- (例: `// TODO-rca:`) - (例: `// TODO-rca:`)
### 推奨
## Thanks for - マジックナンバーは控える(必要な場合もあるので)
- [SDA-SE/document-scanner-android](https://github.com/SDA-SE/document-scanner-android)
-
-2
View File
@@ -82,6 +82,4 @@ dependencies {
implementation project(':model') implementation project(':model')
implementation project(':utils') implementation project(':utils')
implementation project(':component:scanner')
} }
+1 -1
View File
@@ -17,7 +17,7 @@
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher_temp_round" android:icon="@mipmap/ic_launcher"
android:name=".LacertaApplication" android:name=".LacertaApplication"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

@@ -6,7 +6,6 @@ import android.util.Log;
import com.google.android.material.color.DynamicColors; import com.google.android.material.color.DynamicColors;
import dagger.hilt.android.HiltAndroidApp; import dagger.hilt.android.HiltAndroidApp;
import one.nem.lacerta.utils.FeatureSwitch;
@HiltAndroidApp @HiltAndroidApp
public class LacertaApplication extends Application { public class LacertaApplication extends Application {
@@ -16,11 +15,7 @@ public class LacertaApplication extends Application {
if (DynamicColors.isDynamicColorAvailable()) { if (DynamicColors.isDynamicColorAvailable()) {
Log.d("DynamicColors", "DynamicColors is available. Applying to activities..."); Log.d("DynamicColors", "DynamicColors is available. Applying to activities...");
if (FeatureSwitch.Meta.disableDynamicColor) { DynamicColors.applyToActivitiesIfAvailable(this);
Log.d("DynamicColors", "DynamicColors is disabled by FeatureSwitch.");
} else {
DynamicColors.applyToActivitiesIfAvailable(this);
}
} else { } else {
Log.d("DynamicColors", "DynamicColors is not available."); Log.d("DynamicColors", "DynamicColors is not available.");
} }
@@ -1,37 +1,26 @@
package one.nem.lacerta; package one.nem.lacerta;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI; import androidx.navigation.ui.NavigationUI;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import one.nem.lacerta.component.scanner.ScannerManagerActivity;
import one.nem.lacerta.model.FragmentNavigation; import one.nem.lacerta.model.FragmentNavigation;
import one.nem.lacerta.model.pref.FeatureSwitchOverride; import one.nem.lacerta.model.pref.FeatureSwitchOverride;
import one.nem.lacerta.utils.FeatureSwitch; import one.nem.lacerta.utils.FeatureSwitch;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.io.NotActiveException;
import dagger.hilt.android.AndroidEntryPoint; import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.utils.repository.SharedPrefUtils; import one.nem.lacerta.utils.repository.SharedPrefUtils;
@@ -79,27 +68,35 @@ public class MainActivity extends AppCompatActivity implements FragmentNavigatio
// Set status bar color // Set status bar color
getWindow().setStatusBarColor(ContextCompat.getColor(this, one.nem.lacerta.shared.ui.R.color.colorSurface)); getWindow().setStatusBarColor(ContextCompat.getColor(this, one.nem.lacerta.shared.ui.R.color.colorSurface));
// Fab // Set app bar color
findViewById(R.id.scanFab).setOnClickListener(v -> { AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout);
Toast.makeText(this, "Scan", Toast.LENGTH_SHORT).show(); appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
Intent intent = new Intent(this.getApplicationContext(), ScannerManagerActivity.class); @Override
startActivity(intent); 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);
} }
@Override // Public
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { public void setActionBarTitle(String title) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults); getSupportActionBar().setTitle(title);
if (requestCode == 1) { }
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission granted", Toast.LENGTH_SHORT).show(); public void setActionBarBackButton(boolean isEnabled) {
} else { getSupportActionBar().setDisplayHomeAsUpEnabled(isEnabled);
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "カメラの権限は必須です.", Toast.LENGTH_LONG).show();
finish(); // Exit app
}
}
} }
private void initializeApp() { private void initializeApp() {
@@ -124,61 +121,4 @@ public class MainActivity extends AppCompatActivity implements FragmentNavigatio
.addToBackStack(null) .addToBackStack(null)
.commit(); .commit();
} }
@Override
public void navigateToFragment(Fragment fragment, boolean addToBackStack) {
if (addToBackStack) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, fragment)
.addToBackStack(null)
.commit();
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, fragment)
.commit();
}
}
@Override
public void navigateToFragment(Fragment fragment, boolean addToBackStack, boolean clearBackStack) {
if (clearBackStack) {
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
if (addToBackStack) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, fragment)
.addToBackStack(null)
.commit();
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, fragment)
.commit();
}
}
public void navigateToFragmentAlternate(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// get the current fragment
Fragment currentFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
// hide the current fragment
if (currentFragment != null) {
transaction.hide(currentFragment);
}
// Add the new fragment
transaction.add(R.id.nav_host_fragment, fragment);
// Add the transaction to the back stack if needed
if (addToBackStack) {
transaction.addToBackStack(null);
}
// Commit the transaction
transaction.commit();
// Update the primary navigation fragment
getSupportFragmentManager().beginTransaction().setPrimaryNavigationFragment(fragment).commit();
}
} }
@@ -1,15 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#5F4769">
<group android:scaleX="0.377"
android:scaleY="0.377"
android:translateX="7.476"
android:translateY="7.476">
<path
android:fillColor="@android:color/white"
android:pathData="M7,3H4v3H2V1h5V3zM22,6V1h-5v2h3v3H22zM7,21H4v-3H2v5h5V21zM20,18v3h-3v2h5v-5H20zM19,18c0,1.1 -0.9,2 -2,2H7c-1.1,0 -2,-0.9 -2,-2V6c0,-1.1 0.9,-2 2,-2h10c1.1,0 2,0.9 2,2V18zM15,8H9v2h6V8zM15,11H9v2h6V11zM15,14H9v2h6V14z"/>
</group>
</vector>
+48 -24
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" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:theme="@style/Theme.Lacerta" android:background="@color/colorSurface">
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="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_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent">
app:navGraph="@navigation/main_nav"
tools:layout="@layout/fragment_home_top" /> <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 <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav" android:id="@+id/bottom_nav"
@@ -34,17 +71,4 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_nav_menu" /> app:menu="@menu/bottom_nav_menu" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/scanFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp"
android:clickable="true"
app:layout_constraintBottom_toTopOf="@+id/bottom_nav"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_baseline_add_24" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_temp_background"/>
<foreground android:drawable="@drawable/ic_launcher_temp_foreground"/>
</adaptive-icon>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_temp_background"/>
<foreground android:drawable="@drawable/ic_launcher_temp_foreground"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_temp_background">#A386EB</color>
</resources>
@@ -1,20 +1,19 @@
package one.nem.lacerta.component.scanner; package one.nem.lacerta.component.scanner;
import android.Manifest;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
import androidx.annotation.AnimatorRes;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
@@ -29,11 +28,11 @@ import java.util.concurrent.CompletableFuture;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint; import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.Document;
import one.nem.lacerta.model.document.DocumentDetail; import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.DocumentMeta; import one.nem.lacerta.model.document.DocumentMeta;
import one.nem.lacerta.processor.factory.DocumentProcessorFactory; import one.nem.lacerta.processor.factory.DocumentProcessorFactory;
import one.nem.lacerta.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
import one.nem.lacerta.data.Document;
import one.nem.lacerta.vcs.factory.LacertaVcsFactory; import one.nem.lacerta.vcs.factory.LacertaVcsFactory;
@AndroidEntryPoint @AndroidEntryPoint
@@ -96,14 +95,6 @@ public class ScannerManagerActivity extends AppCompatActivity {
return insets; return insets;
}); });
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1); // TODO-rca: リクエストコードを定数にする
}
MaterialToolbar toolbar = findViewById(R.id.top_toolbar); MaterialToolbar toolbar = findViewById(R.id.top_toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
@@ -128,12 +119,11 @@ public class ScannerManagerActivity extends AppCompatActivity {
Toast.makeText(this, "保存処理", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "保存処理", Toast.LENGTH_SHORT).show();
saveNewDocument(); saveNewDocument();
return true; return true;
// } } else if (item.getItemId() == R.id.action_insert_exist) {
// else if (item.getItemId() == R.id.action_insert_exist) { // 既存ドキュメントに挿入
// // 既存ドキュメントに挿入 Toast.makeText(this, "挿入処理", Toast.LENGTH_SHORT).show();
// Toast.makeText(this, "Work in progress", Toast.LENGTH_SHORT).show(); insertToExistDocument();
// insertToExistDocument(); return true;
// return true;
} else if (item.getItemId() == android.R.id.home) { } else if (item.getItemId() == android.R.id.home) {
finish(); finish();
return true; return true;
@@ -149,6 +139,7 @@ public class ScannerManagerActivity extends AppCompatActivity {
if (this.croppedImages.isEmpty()) { if (this.croppedImages.isEmpty()) {
logger.debug(TAG, "this.resultImages is empty"); logger.debug(TAG, "this.resultImages is empty");
logger.e_code("7cb0584e-74ef-48ec-848a-c4d14e75e15a"); logger.e_code("7cb0584e-74ef-48ec-848a-c4d14e75e15a");
// TODO-rca: なんかする
} else { } else {
logger.debug(TAG, "this.resultImages is not empty"); logger.debug(TAG, "this.resultImages is not empty");
updateResultView(this.croppedImages); updateResultView(this.croppedImages);
@@ -6,9 +6,9 @@
android:icon="@drawable/save_24px" android:icon="@drawable/save_24px"
android:title="Save" android:title="Save"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<!-- <item--> <item
<!-- android:id="@+id/action_insert_exist"--> android:id="@+id/action_insert_exist"
<!-- android:icon="@drawable/description_24px"--> android:icon="@drawable/ic_baseline_add_24"
<!-- android:title="Insert"--> android:title="Save"
<!-- app:showAsAction="ifRoom"/>--> app:showAsAction="ifRoom"/>
</menu> </menu>
-2
View File
@@ -54,6 +54,4 @@ dependencies {
implementation project(':model') implementation project(':model')
implementation project(':vcs')
} }
@@ -1,12 +1,9 @@
package one.nem.lacerta.component.viewer; package one.nem.lacerta.component.viewer;
import android.app.AlertDialog;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@@ -24,7 +21,6 @@ import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.Document; import one.nem.lacerta.data.Document;
import one.nem.lacerta.model.document.DocumentDetail; import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.page.Page; import one.nem.lacerta.model.document.page.Page;
import one.nem.lacerta.utils.FeatureSwitch;
import one.nem.lacerta.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
/** /**
@@ -44,17 +40,15 @@ public class ComponentViewerTopFragment extends Fragment {
private static final String TAG = "ComponentViewerTopFragment"; private static final String TAG = "ComponentViewerTopFragment";
private String documentId; private String documentId;
private String documentName;
public ComponentViewerTopFragment() { public ComponentViewerTopFragment() {
// Required empty public constructor // Required empty public constructor
} }
public static ComponentViewerTopFragment newInstance(String documentId, String documentName) { public static ComponentViewerTopFragment newInstance(String documentId) {
ComponentViewerTopFragment fragment = new ComponentViewerTopFragment(); ComponentViewerTopFragment fragment = new ComponentViewerTopFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("documentId", documentId); args.putString("documentId", documentId);
args.putString("documentName", documentName);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@@ -64,7 +58,6 @@ public class ComponentViewerTopFragment extends Fragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getArguments() != null) { if (getArguments() != null) {
documentId = getArguments().getString("documentId"); documentId = getArguments().getString("documentId");
documentName = getArguments().getString("documentName");
} }
} }
@@ -74,10 +67,6 @@ public class ComponentViewerTopFragment extends Fragment {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_component_viewer_top, container, false); View view = inflater.inflate(R.layout.fragment_component_viewer_top, container, false);
// Toolbar
Toolbar toolbar = view.findViewById(R.id.toolbar);
toolbarSetup(toolbar, true, this.documentName == null ? "Document" : this.documentName);
RecyclerView recyclerView = view.findViewById(R.id.body_recycler_view); RecyclerView recyclerView = view.findViewById(R.id.body_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
ViewerBodyAdapter viewerBodyAdapter = new ViewerBodyAdapter(fileName -> { ViewerBodyAdapter viewerBodyAdapter = new ViewerBodyAdapter(fileName -> {
@@ -85,94 +74,15 @@ public class ComponentViewerTopFragment extends Fragment {
}); });
recyclerView.setAdapter(viewerBodyAdapter); recyclerView.setAdapter(viewerBodyAdapter);
if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.VISIBLE);
document.getDocument(documentId).thenAccept(documentDetail -> { document.getDocument(documentId).thenAccept(documentDetail -> {
ArrayList<Page> pages = documentDetail.getPages(); ArrayList<Page> pages = documentDetail.getPages();
logger.debug(TAG, "pages.size(): " + pages.size()); logger.debug(TAG, "pages.size(): " + pages.size());
viewerBodyAdapter.setPages(pages); viewerBodyAdapter.setPages(pages);
getActivity().runOnUiThread(() -> { getActivity().runOnUiThread(() -> {
viewerBodyAdapter.notifyItemRangeChanged(0, pages.size()); viewerBodyAdapter.notifyItemRangeChanged(0, pages.size());
if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.GONE);
}); });
}); });
return view; return view;
} }
/**
* ToolbarをInitする
*
* @param toolbar Toolbar
* @param showBackButton 戻るボタンを表示するか
* @param title タイトル
*/
private void toolbarSetup(Toolbar toolbar, boolean showBackButton, String title) {
getActivity().runOnUiThread(() -> {
if (showBackButton) {
toolbar.setNavigationIcon(one.nem.lacerta.shared.ui.R.drawable.arrow_back_24px);
toolbar.setNavigationOnClickListener(v -> {
// Stop Activity
getActivity().finish();
});
} else {
toolbar.setNavigationIcon(null);
}
toolbar.setTitle(title);
toolbar.inflateMenu(R.menu.viewer_menu);
toolbar.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.action_open_vcs_rev_list) {
// Open vcs rev list
getParentFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, ViewerVcsRevListFragment.newInstance(documentId))
.commit();
return true;
} else if (item.getItemId() == R.id.action_rename) {
// TODO-rca: デザインをMaterial Design 3に合わせたカスタムダイアログにする
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("ファイル名の変更");
builder.setMessage("ファイル名を入力してください");
final android.widget.EditText input = new android.widget.EditText(getContext());
input.setText(documentName);
builder.setView(input);
builder.setPositiveButton("作成", (dialog, which) -> {
document.renameDocument(documentId, input.getText().toString()).thenAccept(aVoid -> {
getActivity().runOnUiThread(() -> {
toolbar.setTitle(input.getText().toString());
documentName = input.getText().toString();
});
});
});
builder.setNegativeButton("キャンセル", (dialog, which) -> {
dialog.cancel();
});
builder.show();
return true;
} else if (item.getItemId() == R.id.action_delete) {
// TODO-rca: デザインをMaterial Design 3に合わせたカスタムダイアログにする
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("ファイルの削除");
builder.setMessage("ファイルを削除しますか?");
builder.setPositiveButton("削除", (dialog, which) -> {
document.deleteDocument(documentId).thenAccept(aVoid -> {
getActivity().runOnUiThread(() -> {
// Stop Activity
getActivity().finish();
});
});
});
builder.setNegativeButton("キャンセル", (dialog, which) -> {
dialog.cancel();
});
builder.show();
return true;
} else if (item.getItemId() == R.id.action_move) {
Toast.makeText(getContext(), "Work in progress", Toast.LENGTH_SHORT).show();
return true;
} else {
return false;
}
});
});
}
} }
@@ -1,82 +0,0 @@
package one.nem.lacerta.component.viewer;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import one.nem.lacerta.model.VcsRevModel;
import one.nem.lacerta.utils.FeatureSwitch;
public class RevAdapter extends RecyclerView.Adapter<RevAdapter.RevViewHolder>{
private ArrayList<VcsRevModel> revModels;
public RevAdapter(ArrayList<VcsRevModel> revModels) {
this.revModels = revModels;
}
public RevAdapter() {
}
public void setRevModels(ArrayList<VcsRevModel> revModels) {
this.revModels = revModels;
}
@NonNull
@Override
public RevAdapter.RevViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.viewer_rev_list_item, parent, false);
return new RevAdapter.RevViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RevAdapter.RevViewHolder holder, int position) {
VcsRevModel revModel = revModels.get(position);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
holder.title.setText(revModel.getCommitMessage());
if (FeatureSwitch.Vcs.disableBranchDisplay) {
// holder.detail.setText(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(revModel.getCreatedAt().toInstant()));
holder.detail.setText(simpleDateFormat.format(revModel.getCreatedAt()));
} else {
// holder.detail.setText(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(revModel.getCreatedAt().toInstant()) + " " + revModel.getBranchName());
holder.detail.setText(simpleDateFormat.format(revModel.getCreatedAt())+ " " + revModel.getBranchName());
}
holder.revId.setText("RevID: " + revModel.getId());
}
@Override
public int getItemCount() {
if (revModels == null) {
return 0;
} else {
return revModels.size();
}
}
class RevViewHolder extends RecyclerView.ViewHolder {
TextView title;
TextView detail;
TextView revId;
public RevViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.rev_item_title);
detail = itemView.findViewById(R.id.rev_item_detail);
revId = itemView.findViewById(R.id.rev_item_id);
}
}
}
@@ -35,7 +35,6 @@ public class ViewerMainActivity extends AppCompatActivity {
// Variables // Variables
private static final String TAG = "ViewerMainActivity"; private static final String TAG = "ViewerMainActivity";
String documentId; String documentId;
String documentName;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -51,7 +50,6 @@ public class ViewerMainActivity extends AppCompatActivity {
Intent intent = getIntent(); Intent intent = getIntent();
try { try {
documentId = intent.getStringExtra("documentId"); documentId = intent.getStringExtra("documentId");
documentName = intent.getStringExtra("documentName");
} }
catch (Exception e) { catch (Exception e) {
logger.error(TAG, "Failed to get documentId from intent"); logger.error(TAG, "Failed to get documentId from intent");
@@ -60,9 +58,8 @@ public class ViewerMainActivity extends AppCompatActivity {
finish(); finish();
} }
// Navigation
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, ComponentViewerTopFragment.newInstance(documentId, documentName)) .replace(R.id.nav_host_fragment, ComponentViewerTopFragment.newInstance(documentId))
.commit(); .commitNow();
} }
} }
@@ -1,95 +0,0 @@
package one.nem.lacerta.component.viewer;
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 javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.utils.LacertaLogger;
import one.nem.lacerta.vcs.LacertaVcs;
import one.nem.lacerta.vcs.factory.LacertaVcsFactory;
/**
* A simple {@link Fragment} subclass.
* Use the {@link ViewerVcsRevListFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class ViewerVcsRevListFragment extends Fragment {
@Inject
LacertaVcsFactory lacertaVcsFactory;
@Inject
LacertaLogger logger;
LacertaVcs lacertaVcs;
private String documentId;
public ViewerVcsRevListFragment() {
// Required empty public constructor
}
public static ViewerVcsRevListFragment newInstance(String documentId) {
ViewerVcsRevListFragment fragment = new ViewerVcsRevListFragment();
Bundle args = new Bundle();
args.putString("documentId", documentId);
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_viewer_vcs_rev_list, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Init arg
if (getArguments() != null) {
this.documentId = getArguments().getString("documentId");
logger.debug("ViewerVcsRevListFragment", "documentId: " + documentId);
}
// Init vcs
lacertaVcs = lacertaVcsFactory.create(documentId);
// Init view
RecyclerView recyclerView = view.findViewById(R.id.rev_list);
// Init adapter
RevAdapter revAdapter = new RevAdapter();
// Set adapter
recyclerView.setAdapter(revAdapter);
// Set layout manager
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
lacertaVcs.getRevisionHistory().thenAccept(revModels -> {
logger.debug("ViewerVcsRevListFragment", "revModels.size(): " + revModels.size());
getActivity().runOnUiThread(() -> {
revAdapter.setRevModels(revModels);
revAdapter.notifyDataSetChanged();
});
});
}
}
@@ -37,16 +37,6 @@
</com.google.android.material.appbar.CollapsingToolbarLayout> </com.google.android.material.appbar.CollapsingToolbarLayout>
<ProgressBar
android:id="@+id/loading_progress_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:indeterminate="true"
android:background="@color/colorSurface"
android:visibility="gone" />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@@ -1,12 +0,0 @@
<?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=".ViewerVcsRevListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rev_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
@@ -11,7 +11,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:elevation="8dp" android:elevation="8dp"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:paddingVertical="16dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/item_text_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/rev_item_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_marginEnd="8dp"
android:text="Placeholder Title"
android:textColor="@color/colorOnSurface"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/rev_item_detail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="2023/01/01 00:00:00 - hogehoge"
android:textColor="@color/colorOnSurfaceSecondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rev_item_title" />
<TextView
android:id="@+id/rev_item_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="12sp"
android:text="dd76a029-51f1-40f7-b316-a0c74bbfebb1(Example)"
android:textColor="@color/colorOnSurfaceSecondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rev_item_detail" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_open_vcs_rev_list"
android:title="Open VCS Rev List" />
<item
android:id="@+id/action_rename"
android:title="リネーム" />
<item
android:id="@+id/action_delete"
android:title="削除" />
<item
android:id="@+id/action_move"
android:title="移動" />
</menu>
@@ -1,21 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android" <navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/component_viewer_navigation" android:id="@+id/component_viewer_navigation"
app:startDestination="@id/componentViewerTopFragment"> app:startDestination="@id/componentViewerTopFragment">
<fragment <fragment
android:id="@+id/componentViewerTopFragment" android:id="@+id/componentViewerTopFragment"
android:name="one.nem.lacerta.component.viewer.ComponentViewerTopFragment" android:name="one.nem.lacerta.component.viewer.ComponentViewerTopFragment"
android:label="ComponentViewerTopFragment" > android:label="ComponentViewerTopFragment" />
<action
android:id="@+id/action_componentViewerTopFragment_to_viewerVcsRevListFragment"
app:destination="@id/viewerVcsRevListFragment" />
</fragment>
<fragment
android:id="@+id/viewerVcsRevListFragment"
android:name="one.nem.lacerta.component.viewer.ViewerVcsRevListFragment"
android:label="fragment_viewer_vcs_rev_list"
tools:layout="@layout/fragment_viewer_vcs_rev_list" />
</navigation> </navigation>
@@ -18,8 +18,6 @@ public interface Document {
CompletableFuture<DocumentDetail> createDocument(); CompletableFuture<DocumentDetail> createDocument();
CompletableFuture<Void> renameDocument(String documentId, String name);
CompletableFuture<Void> deleteDocument(String documentId); CompletableFuture<Void> deleteDocument(String documentId);
CompletableFuture<Void> updateDocument(DocumentDetail detail); CompletableFuture<Void> updateDocument(DocumentDetail detail);
@@ -7,7 +7,6 @@ import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType; import one.nem.lacerta.model.ListItemType;
import one.nem.lacerta.model.LibraryItemPage; import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.PublicPath;
import one.nem.lacerta.model.document.DocumentDetail; import one.nem.lacerta.model.document.DocumentDetail;
public interface LacertaLibrary { public interface LacertaLibrary {
@@ -16,14 +15,13 @@ public interface LacertaLibrary {
CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit); CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit);
CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit, int offset); CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit, int offset);
// Get Library Page // Get Library page
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);
CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit, int offset); CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit, int offset);
// Create Folder // Create Folder
CompletableFuture<String> createFolder(String parentId, String name); CompletableFuture<String> createFolder(String path, String name);
// Get Public Path
CompletableFuture<PublicPath> getPublicPath(String itemId, ListItemType itemType);
} }
@@ -1,7 +1,5 @@
package one.nem.lacerta.data.impl; package one.nem.lacerta.data.impl;
import androidx.room.Update;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@@ -81,7 +79,7 @@ public class DocumentImpl implements Document {
documentEntity.defaultBranch = meta.getDefaultBranch(); documentEntity.defaultBranch = meta.getDefaultBranch();
documentEntity.updatedAt = meta.getUpdatedAt(); documentEntity.updatedAt = meta.getUpdatedAt();
documentEntity.createdAt = meta.getCreatedAt(); documentEntity.createdAt = meta.getCreatedAt();
documentEntity.parentId = meta.getParentId(); documentEntity.publicPath = meta.getPath().getStringPath();
documentEntity.tagIds = meta.getTagIds(); documentEntity.tagIds = meta.getTagIds();
database.documentDao().insert(documentEntity); database.documentDao().insert(documentEntity);
@@ -106,7 +104,7 @@ public class DocumentImpl implements Document {
meta.setDefaultBranch("master"); meta.setDefaultBranch("master");
meta.setUpdatedAt(new Date()); meta.setUpdatedAt(new Date());
meta.setCreatedAt(new Date()); meta.setCreatedAt(new Date());
meta.setParentId(null); meta.setPath(new PublicPath().getRoot()); // TODO-rca: 2回インスタンスを生成していて無駄なのでなんとかする
meta.setTags(new ArrayList<>()); meta.setTags(new ArrayList<>());
return createDocument(meta); return createDocument(meta);
} }
@@ -114,11 +112,6 @@ public class DocumentImpl implements Document {
@Override @Override
public CompletableFuture<Void> deleteDocument(String documentId) { public CompletableFuture<Void> deleteDocument(String documentId) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
DocumentEntity documentEntity = database.documentDao().findById(documentId);
if (documentEntity == null) {
throw new IllegalArgumentException("documentId is not found");
}
database.documentDao().delete(documentEntity);
return null; return null;
}); });
} }
@@ -131,19 +124,6 @@ public class DocumentImpl implements Document {
}); });
} }
@Override
public CompletableFuture<Void> renameDocument(String documentId, String name) {
return CompletableFuture.supplyAsync(() -> {
DocumentEntity documentEntity = database.documentDao().findById(documentId);
if (documentEntity == null) {
throw new IllegalArgumentException("documentId is not found");
}
documentEntity.title = name;
database.documentDao().update(documentEntity);
return null;
});
}
@Override @Override
public CompletableFuture<DocumentDetail> getDocument(String documentId) { public CompletableFuture<DocumentDetail> getDocument(String documentId) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
@@ -158,7 +138,7 @@ public class DocumentImpl implements Document {
meta.setDefaultBranch(documentEntity.defaultBranch); meta.setDefaultBranch(documentEntity.defaultBranch);
meta.setUpdatedAt(documentEntity.updatedAt); meta.setUpdatedAt(documentEntity.updatedAt);
meta.setCreatedAt(documentEntity.createdAt); meta.setCreatedAt(documentEntity.createdAt);
meta.setParentId(documentEntity.parentId); meta.setPath(new PublicPath().resolve(documentEntity.publicPath));
meta.setTags(new ArrayList<>()); // TODO-rca: タグを取得する meta.setTags(new ArrayList<>()); // TODO-rca: タグを取得する
DocumentDetail detail = new DocumentDetail(); DocumentDetail detail = new DocumentDetail();
@@ -1,11 +1,9 @@
package one.nem.lacerta.data.impl; package one.nem.lacerta.data.impl;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -22,7 +20,6 @@ import one.nem.lacerta.source.database.LacertaDatabase;
import one.nem.lacerta.source.database.common.DateTypeConverter; import one.nem.lacerta.source.database.common.DateTypeConverter;
import one.nem.lacerta.source.database.entity.DocumentEntity; import one.nem.lacerta.source.database.entity.DocumentEntity;
import one.nem.lacerta.source.database.entity.FolderEntity; import one.nem.lacerta.source.database.entity.FolderEntity;
import one.nem.lacerta.utils.FeatureSwitch;
import one.nem.lacerta.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
public class LacertaLibraryImpl implements LacertaLibrary { public class LacertaLibraryImpl implements LacertaLibrary {
@@ -39,6 +36,13 @@ public class LacertaLibraryImpl implements LacertaLibrary {
@Override @Override
public CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit) { public CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
// 5秒フリーズさせる
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<DocumentEntity> documentEntities = database.documentDao().getRecentDocument(limit); List<DocumentEntity> documentEntities = database.documentDao().getRecentDocument(limit);
ArrayList<ListItem> listItems = new ArrayList<>(); ArrayList<ListItem> listItems = new ArrayList<>();
@@ -60,35 +64,95 @@ public class LacertaLibraryImpl implements LacertaLibrary {
return null; // TODO-rca: Implement return null; // TODO-rca: Implement
} }
// 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 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 CompletableFuture<LibraryItemPage> getLibraryPage(int limit, int offset) {
return CompletableFuture.supplyAsync(() -> {
return null;
});
}
@Override @Override
public CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit) { public CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
LibraryItemPage libraryItemPage = new LibraryItemPage(); LibraryItemPage libraryItemPage = new LibraryItemPage();
List<FolderEntity> folderEntities; FolderEntity folderEntity = database.folderDao().findById(pageId);
List<DocumentEntity> documentEntities; if (folderEntity == null) {
return null;
if (pageId == null) { // When root folder
libraryItemPage.setPageTitle("ライブラリ");
libraryItemPage.setPageId(null);
libraryItemPage.setParentId(null);
folderEntities = database.folderDao().findRootFolders();
documentEntities = database.documentDao().findRootDocuments();
} else {
FolderEntity folderEntity = database.folderDao().findById(pageId);
if (folderEntity == null) {
logger.warn("LacertaLibraryImpl", pageId + " is not found.");
return null;
}
libraryItemPage.setPageTitle(folderEntity.name);
libraryItemPage.setPageId(folderEntity.id);
libraryItemPage.setParentId(folderEntity.parentId);
folderEntities = database.folderDao().findByParentId(pageId);
documentEntities = database.documentDao().findByParentId(pageId);
} }
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<>(); ArrayList<ListItem> listItems = new ArrayList<>();
for (FolderEntity childFolderEntity : folderEntities) { for (FolderEntity childFolderEntity : folderEntities) {
logger.debug("LacertaLibraryImpl", "childFolderEntity.name: " + childFolderEntity.name); logger.debug("LacertaLibraryImpl", "childFolderEntity.name: " + childFolderEntity.name);
@@ -100,18 +164,18 @@ public class LacertaLibraryImpl implements LacertaLibrary {
listItems.add(listItem); listItems.add(listItem);
} }
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:");
for (DocumentEntity documentEntity : documentEntities) { for (DocumentEntity documentEntity : documentEntities) {
logger.debug("LacertaLibraryImpl", "documentEntity.title: " + documentEntity.title); logger.debug("LacertaLibraryImpl", "documentEntity.title: " + documentEntity.title);
ListItem listItem = new ListItem(); ListItem listItem = new ListItem();
listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT); listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT);
listItem.setTitle(documentEntity.title); listItem.setTitle(documentEntity.title);
listItem.setDescription(simpleDateFormat.format(documentEntity.updatedAt)); // listItem.setDescription(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm").format(documentEntity.updatedAt.toInstant()));
listItem.setItemId(documentEntity.id); listItem.setItemId(documentEntity.id);
listItems.add(listItem); listItems.add(listItem);
} }
libraryItemPage.setPageTitle(folderEntity.name);
libraryItemPage.setPageId(folderEntity.id);
libraryItemPage.setListItems(listItems); libraryItemPage.setListItems(listItems);
logger.debug("LacertaLibraryImpl", "libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); logger.debug("LacertaLibraryImpl", "libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
@@ -130,67 +194,21 @@ public class LacertaLibraryImpl implements LacertaLibrary {
@Override @Override
public CompletableFuture<String> createFolder(String parentId, String name) { public CompletableFuture<String> createFolder(String parentId, String name) {
return CompletableFuture.supplyAsync(() -> { 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 folderEntity = new FolderEntity();
folderEntity.id = UUID.randomUUID().toString(); folderEntity.id = UUID.randomUUID().toString();
folderEntity.name = name; folderEntity.name = name;
folderEntity.parentId = parentId; folderEntity.publicPath = publicPath.getStringPath();
database.folderDao().insert(folderEntity); database.folderDao().insert(folderEntity);
return folderEntity.id; return folderEntity.id;
}); });
} }
@Override
public CompletableFuture<PublicPath> getPublicPath(String itemId, ListItemType itemType) {
return CompletableFuture.supplyAsync(() -> {
if (itemType == ListItemType.ITEM_TYPE_DOCUMENT) {
DocumentEntity documentEntity = database.documentDao().findById(itemId);
if (documentEntity == null) {
logger.warn("LacertaLibraryImpl", itemId + " is not found.");
return null;
}
PublicPath publicPath = recursiveResolve(documentEntity.parentId);
publicPath.resolve(documentEntity.title);
return publicPath;
} else if (itemType == ListItemType.ITEM_TYPE_FOLDER) {
FolderEntity folderEntity = database.folderDao().findById(itemId);
if (folderEntity == null) {
return null;
}
return recursiveResolve(folderEntity.id);
} else {
logger.warn("LacertaLibraryImpl", "Unknown ListItemType: " + itemType);
return null;
}
});
}
/**
* 再帰的にパスを解決する
*
* @param folderId
* @return
*/
private PublicPath recursiveResolve(String folderId) {
String current = folderId;
boolean continueFlag = true;
ArrayList<String> folderNames = new ArrayList<>();
while (continueFlag) {
FolderEntity folderEntity = database.folderDao().findById(current);
if (folderEntity == null) { // 存在しないフォルダIDが指定された場合
continueFlag = false;
} else {
folderNames.add(folderEntity.name);
current = folderEntity.parentId;
if (current == null) { // ルートフォルダに到達した場合
continueFlag = false;
}
}
}
// フォルダ名を逆順にしてListに変換
Collections.reverse(folderNames);
List<String> folderNamesReversed = new ArrayList<>(folderNames);
return new PublicPath(folderNamesReversed);
}
} }
@@ -1,5 +1,5 @@
package one.nem.lacerta.feature.home; package one.nem.lacerta.feature.home;
public interface DocumentSelectListener { public interface DocumentSelectListener {
void onDocumentSelect(String documentId, String documentName); void onDocumentSelect(String documentId);
} }
@@ -4,24 +4,40 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.view.MenuProvider;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
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 javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint; import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.component.viewer.ViewerMainActivity; import one.nem.lacerta.component.viewer.ViewerMainActivity;
import one.nem.lacerta.data.Document;
import one.nem.lacerta.data.LacertaLibrary; import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.utils.FeatureSwitch; import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.document.DocumentMeta;
/** /**
@@ -35,8 +51,6 @@ public class HomeTopFragment extends Fragment {
@Inject @Inject
LacertaLibrary lacertaLibrary; LacertaLibrary lacertaLibrary;
private ListItemAdapter listItemAdapter;
public HomeTopFragment() { public HomeTopFragment() {
// Required empty public constructor // Required empty public constructor
} }
@@ -59,87 +73,52 @@ public class HomeTopFragment extends Fragment {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home_top, container, false); View view = inflater.inflate(R.layout.fragment_home_top, container, false);
// Set status bar color // setHasOptionsMenu(true);
AppBarLayout appBarLayout = view.findViewById(R.id.app_bar_layout); Toolbar toolbar = view.findViewById(R.id.home_toolbar);
appBarLayout.addOnOffsetChangedListener((appBarLayout1, verticalOffset) -> { toolbar.setNavigationIcon(one.nem.lacerta.shared.ui.R.drawable.arrow_back_24px);
if (Math.abs(verticalOffset) == appBarLayout1.getTotalScrollRange()) { toolbar.setNavigationOnClickListener(v -> {
// Collapsed Toast.makeText(getContext(), "Works!!!!!!!!!!!!", Toast.LENGTH_SHORT).show();
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer)); });
} else if (verticalOffset == 0) { toolbar.inflateMenu(R.menu.drawer_menu);
// Expanded toolbar.setOnMenuItemClickListener(item -> {
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSurface)); if (item.getItemId() == R.id.item_placeholder) {
Toast.makeText(getContext(), "Works!", Toast.LENGTH_SHORT).show();
return true;
} }
return false;
}); });
return view; return view;
} }
@Override // @Override
public void onViewCreated(View view, Bundle savedInstanceState) { // public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); // super.onViewCreated(view, savedInstanceState);
//
RecyclerView recyclerView = view.findViewById(R.id.home_item_recycler_view); // RecyclerView recyclerView = view.findViewById(R.id.home_item_recycler_view);
//
Toolbar toolbar = view.findViewById(R.id.home_toolbar); //
toolbarSetup(toolbar, false, "ホーム"); // ListItemAdapter listItemAdapter = new ListItemAdapter(documentId -> {
// Log.d("HomeTopFragment", "onViewCreated: " + documentId);
this.listItemAdapter = new ListItemAdapter((documentId, documentName) -> { // Intent intent = new Intent(getContext(), ViewerMainActivity.class);
Intent intent = new Intent(getContext(), ViewerMainActivity.class); // intent.putExtra("documentId", documentId);
Log.d("HomeTopFragment", "onDocumentSelect: " + documentId + " " + documentName); // startActivity(intent);
intent.putExtra("documentId", documentId); // });
intent.putExtra("documentName", documentName); // recyclerView.setAdapter(listItemAdapter);
startActivity(intent); // recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
}); //
recyclerView.setAdapter(listItemAdapter); // lacertaLibrary.getRecentDocument(10).thenAccept(listItems -> {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); // listItemAdapter.setListItems(listItems);
// getActivity().runOnUiThread(() -> {
updateList(); // listItemAdapter.notifyItemRangeInserted(0, listItems.size());
} // });
// });
@Override // }
public void onResume() { //
super.onResume(); // @Override
// public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
updateList(); // inflater.inflate(R.menu.drawer_menu, menu);
} // super.onCreateOptionsMenu(menu, inflater);
// }
private void updateList() {
lacertaLibrary.getRecentDocument(10).thenAccept(listItems -> {
if (listItems == null) {
return;
}
this.listItemAdapter.setListItems(listItems);
getActivity().runOnUiThread(() -> {
Log.d("HomeTopFragment", "onViewCreated: " + listItems.size());
if (FeatureSwitch.RecyclerView.useSimpleNotifyMethod) {
this.listItemAdapter.notifyDataSetChanged();
} else {
// IndexOutOfBoundsExceptionを吐くことがあったので いったん
this.listItemAdapter.notifyItemRangeInserted(0, listItems.size() - 1);
}
});
});
}
/**
* ToolbarをInitする
*
* @param toolbar Toolbar
* @param showBackButton 戻るボタンを表示するか
* @param title タイトル
*/
private void toolbarSetup(Toolbar toolbar, boolean showBackButton, String title) {
getActivity().runOnUiThread(() -> {
if (showBackButton) {
toolbar.setNavigationIcon(one.nem.lacerta.shared.ui.R.drawable.arrow_back_24px);
toolbar.setNavigationOnClickListener(v -> {
Navigation.findNavController(requireView()).popBackStack();
});
} else {
toolbar.setNavigationIcon(null);
}
toolbar.setTitle(title);
});
}
} }
@@ -46,17 +46,15 @@ public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListIt
holder.description.setText(listItem.getDescription()); holder.description.setText(listItem.getDescription());
holder.itemView.setOnClickListener( v -> { holder.itemView.setOnClickListener( v -> {
listener.onDocumentSelect(listItem.getItemId(), listItem.getTitle()); Intent intent = new Intent(v.getContext(), ViewerMainActivity.class);
intent.putExtra("documentId", listItem.getItemId());
v.getContext().startActivity(intent);
}); });
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
if (listItems == null) { return listItems.size();
return 0;
} else {
return listItems.size();
}
} }
public static class ListItemViewHolder extends RecyclerView.ViewHolder{ public static class ListItemViewHolder extends RecyclerView.ViewHolder{
-2
View File
@@ -53,7 +53,5 @@ dependencies {
implementation project(':utils') implementation project(':utils')
implementation project(':component:viewer')
} }
@@ -1,9 +1,5 @@
package one.nem.lacerta.feature.library; package one.nem.lacerta.feature.library;
/*
Currently, this file is not used in the app.
*/
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -1,15 +1,10 @@
package one.nem.lacerta.feature.library; package one.nem.lacerta.feature.library;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@@ -19,30 +14,13 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint; 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.data.LacertaLibrary;
import one.nem.lacerta.model.FragmentNavigation; import one.nem.lacerta.model.FragmentNavigation;
import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.PublicPath;
import one.nem.lacerta.utils.FeatureSwitch;
import one.nem.lacerta.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
@@ -54,15 +32,8 @@ import one.nem.lacerta.utils.LacertaLogger;
@AndroidEntryPoint @AndroidEntryPoint
public class LibraryPageFragment extends Fragment { public class LibraryPageFragment extends Fragment {
// Variables // Param
// このインスタンスで表示されているページ private String folderId;
LibraryItemPage libraryItemPage;
// Arguments
String folderId;
String title;
String parentId;
@Inject @Inject
LacertaLibrary lacertaLibrary; LacertaLibrary lacertaLibrary;
@@ -72,26 +43,15 @@ public class LibraryPageFragment extends Fragment {
ListItemAdapter listItemAdapter; ListItemAdapter listItemAdapter;
int currentTotalItemCount = 0;
public LibraryPageFragment() { public LibraryPageFragment() {
// Required empty public constructor // Required empty public constructor
} }
public static LibraryPageFragment newInstance(String folderId) {
public static LibraryPageFragment newInstance(String folderId, String title, String parentId) {
LibraryPageFragment fragment = new LibraryPageFragment(); LibraryPageFragment fragment = new LibraryPageFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("folderId", folderId); args.putString("folderId", folderId);
args.putString("title", title);
args.putString("publicPath", parentId);
fragment.setArguments(args);
return fragment;
}
public static LibraryPageFragment newInstance(String folderId) { // Back action
LibraryPageFragment fragment = new LibraryPageFragment();
Bundle args = new Bundle();
args.putString("folderId", folderId);
args.putString("title", null);
args.putString("publicPath", null);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@@ -100,8 +60,6 @@ public class LibraryPageFragment extends Fragment {
LibraryPageFragment fragment = new LibraryPageFragment(); LibraryPageFragment fragment = new LibraryPageFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("folderId", null); args.putString("folderId", null);
args.putString("title", null);
args.putString("publicPath", null);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@@ -117,17 +75,8 @@ public class LibraryPageFragment extends Fragment {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_library_top, container, false); View view = inflater.inflate(R.layout.fragment_library_top, container, false);
// Set status bar color setHasOptionsMenu(true);
AppBarLayout appBarLayout = view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener((appBarLayout1, verticalOffset) -> {
if (Math.abs(verticalOffset) == appBarLayout1.getTotalScrollRange()) {
// Collapsed
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer));
} else if (verticalOffset == 0) {
// Expanded
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSurface));
}
});
return view; return view;
} }
@@ -135,157 +84,103 @@ public class LibraryPageFragment extends Fragment {
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
if (getArguments() != null) {
this.folderId = getArguments().getString("folderId"); // Required
if (getArguments().getString("title") == null && getArguments().getString("publicPath") == null) {
this.libraryItemPage = new LibraryItemPage();
} else {
this.title = getArguments().getString("title");
this.parentId = getArguments().getString("publicPath");
}
} else {
logger.debug("LibraryTopFragment", "getArguments() is null(maybe root)");
this.libraryItemPage = new LibraryItemPage();
}
// Toolbar Setup
toolbarSetup(view.findViewById(R.id.library_toolbar), this.folderId != null, this.title != null ? this.title : "ライブラリ");
// RecyclerView Setup
RecyclerView recyclerView = view.findViewById(R.id.library_item_recycler_view); RecyclerView recyclerView = view.findViewById(R.id.library_item_recycler_view);
this.listItemAdapter = new ListItemAdapter(new DocumentSelectListener() { this.listItemAdapter = new ListItemAdapter(new DocumentSelectListener() {
@Override @Override
public void onFolderSelected(String folderId, String folderName) { public void onFolderSelected(String folderId, String folderName) {
logger.debug("LibraryTopFragment", "Folder selected! folderId: " + folderId + ", folderName: " + folderName); logger.debug("LibraryTopFragment", "Folder selected! folderId: " + folderId + ", folderName: " + folderName);
// // 画面遷移 // 画面遷移
// FragmentNavigation fragmentNavigation = (FragmentNavigation) getActivity(); FragmentNavigation fragmentNavigation = (FragmentNavigation) getActivity();
// // folderId: 推移先で表示するフォルダのID, folderName: 推移先で表示するフォルダの名前, parentId: このフラグメントで表示しているフォルダのID(推移先の親) assert fragmentNavigation != null;
// fragmentNavigation.navigateToFragment(LibraryPageFragment.newInstance(folderId, folderName, libraryItemPage != null ? libraryItemPage.getParentId() : null), false); fragmentNavigation.navigateToFragment(LibraryPageFragment.newInstance(folderId));
Bundle bundle = new Bundle();
bundle.putString("folderId", folderId);
bundle.putString("title", folderName);
bundle.putString("publicPath", libraryItemPage != null ? libraryItemPage.getParentId() : null);
try {
Navigation.findNavController(requireView()).navigate(R.id.action_feature_library_top_fragment_self, bundle);
} catch (IllegalStateException e) {
logger.error("LibraryTopFragment", "IllegalStateException: " + e.getMessage());
}
} }
@Override @Override
public void onDocumentSelected(String documentId, String documentName) { public void onDocumentSelected(String documentId, String documentName) {
Intent intent = new Intent(getContext(), ViewerMainActivity.class); Toast.makeText(getContext(), "Document selected! documentId: " + documentId + ", documentName: " + documentName, Toast.LENGTH_SHORT).show();
logger.debug("LibraryTopFragment", "Document selected! documentId: " + documentId + ", documentName: " + documentName);
intent.putExtra("documentId", documentId);
intent.putExtra("documentName", documentName);
startActivity(intent);
} }
}); });
recyclerView.setAdapter(listItemAdapter); recyclerView.setAdapter(listItemAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
// Get library page and update RecyclerView items if (getArguments() != null) {
lacertaLibrary.getLibraryPage(this.folderId, 10).thenAccept(libraryItemPage -> { this.folderId = getArguments().getString("folderId");
this.libraryItemPage = libraryItemPage; }
if (this.parentId == null) { if (this.folderId == null) { // Root
this.parentId = libraryItemPage.getParentId(); lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> {
} logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
if (this.title == null) { listItemAdapter.setLibraryItemPage(libraryItemPage);
this.title = libraryItemPage.getPageTitle(); getActivity().runOnUiThread(() -> {
// Toolbar init again // ActionBarのタイトルを変更する
toolbarSetup(view.findViewById(R.id.library_toolbar), this.folderId != null, this.title != null ? this.title : "ライブラリ"); getActivity().setTitle("ライブラリ");
} // ActionBarに戻るボタンを非表示にする
// getActivity().getActionBar().setDisplayHomeAsUpEnabled(false);
logger.debug("LibraryTopFragment", "Item selected! Total item page: " + this.libraryItemPage.getListItems().size()); listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1);
if (!FeatureSwitch.RecyclerView.useSimpleNotifyMethod) {
getActivity().runOnUiThread(() -> { // TODO-rca: 実行条件を考える?
listItemAdapter.notifyItemRangeRemoved(0, this.libraryItemPage.getListItems().size() - 1);
}); });
} this.currentTotalItemCount = libraryItemPage.getListItems().size();
listItemAdapter.setLibraryItemPage(this.libraryItemPage);
getActivity().runOnUiThread(() -> {
if (FeatureSwitch.RecyclerView.useSimpleNotifyMethod) {
listItemAdapter.notifyDataSetChanged();
} else {
listItemAdapter.notifyItemRangeInserted(0, this.libraryItemPage.getListItems().size() - 1);
}
}); });
}); } 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
* Currentにフォルダを作成する public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
*/ inflater.inflate(R.menu.dir_menu, menu);
private void createFolder(String pageId) { super.onCreateOptionsMenu(menu, inflater);
// TODO-rca: デザインをMaterial Design 3に合わせたカスタムダイアログにする }
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("フォルダの作成"); // Selected
builder.setMessage("フォルダ名を入力してください"); @Override
final android.widget.EditText input = new android.widget.EditText(getContext()); public boolean onOptionsItemSelected(@NonNull MenuItem item) {
input.setText("フォルダ名"); if (item.getItemId() == R.id.menu_item_create_new_folder) {
builder.setView(input); AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setPositiveButton("作成", (dialog, which) -> { builder.setTitle("フォルダの作成");
lacertaLibrary.createFolder(pageId, input.getText().toString()).thenAccept(folderId -> { 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 // Refresh
updateItem(pageId); updateItem();
}); });
}); builder.setNegativeButton("キャンセル", (dialog, which) -> {
builder.setNegativeButton("キャンセル", (dialog, which) -> { dialog.cancel();
dialog.cancel(); });
}); builder.show();
builder.show(); return true;
} else {
return super.onOptionsItemSelected(item);
}
} }
/** private void updateItem() {
* RecyclerViewのアイテムを更新する lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> {
*/
private void updateItem(String pageId) {
lacertaLibrary.getLibraryPage(pageId, 10).thenAccept(libraryItemPage -> {
this.libraryItemPage = libraryItemPage;
logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
getActivity().runOnUiThread(() -> { getActivity().runOnUiThread(() -> {
listItemAdapter.notifyItemRangeRemoved(0, libraryItemPage.getListItems().size() - 1); listItemAdapter.notifyItemRangeRemoved(0, this.currentTotalItemCount - 1);
}); });
listItemAdapter.setLibraryItemPage(libraryItemPage); listItemAdapter.setLibraryItemPage(libraryItemPage);
getActivity().runOnUiThread(() -> { getActivity().runOnUiThread(() -> {
listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1); listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1);
}); });
}); this.currentTotalItemCount = libraryItemPage.getListItems().size();
}
/**
* ToolbarをInitする
*
* @param toolbar Toolbar
* @param showBackButton 戻るボタンを表示するか
* @param title タイトル
*/
private void toolbarSetup(Toolbar toolbar, boolean showBackButton, String title) {
getActivity().runOnUiThread(() -> {
if (showBackButton) {
toolbar.setNavigationIcon(one.nem.lacerta.shared.ui.R.drawable.arrow_back_24px);
toolbar.setNavigationOnClickListener(v -> {
//this.libraryItemPage = lacertaLibrary.getLibraryPage(this.libraryItemPage.getParentId(), 10).join();
// Back
Navigation.findNavController(requireView()).popBackStack();
});
} else {
toolbar.setNavigationIcon(null);
}
toolbar.setTitle(title);
toolbar.getMenu().clear();
toolbar.inflateMenu(R.menu.dir_menu);
toolbar.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.menu_item_create_new_folder) {
createFolder(this.folderId);
return true;
} else {
return false;
}
});
}); });
} }
} }
@@ -1,5 +1,6 @@
package one.nem.lacerta.feature.library; package one.nem.lacerta.feature.library;
import android.content.Intent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -9,6 +10,8 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import one.nem.lacerta.model.LibraryItemPage; import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.ListItem; import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType; import one.nem.lacerta.model.ListItemType;
@@ -1,50 +1,11 @@
<FrameLayout 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:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="@color/colorSurface">
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.recyclerview.widget.RecyclerView
android:id="@+id/library_item_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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/library_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/library_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>
</FrameLayout> </FrameLayout>
@@ -4,8 +4,8 @@
<item <item
android:id="@+id/menu_item_create_new_folder" android:id="@+id/menu_item_create_new_folder"
android:icon="@drawable/create_new_folder_24px" android:icon="@drawable/developer_mode_24px"
android:title="@string/create_new_folder" android:title="@string/app_name"
app:showAsAction="never"/> app:showAsAction="ifRoom"/> <!-- TODO-rca: change this -->
</menu> </menu>
@@ -8,15 +8,5 @@
android:id="@+id/feature_library_top_fragment" android:id="@+id/feature_library_top_fragment"
android:name="one.nem.lacerta.feature.library.LibraryPageFragment" android:name="one.nem.lacerta.feature.library.LibraryPageFragment"
android:label="fragment_library_top" android:label="fragment_library_top"
tools:layout="@layout/fragment_library_top" > tools:layout="@layout/fragment_library_top" />
<action
android:id="@+id/action_feature_library_top_fragment_self"
app:destination="@id/feature_library_top_fragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"
app:popUpTo="@id/feature_library_top_fragment"
app:popUpToInclusive="false"/>
</fragment>
</navigation> </navigation>
@@ -1,4 +1,3 @@
<resources> <resources>
<string name="app_name">Library</string> <string name="app_name">Library</string>
<string name="create_new_folder">新しいフォルダを作成</string>
</resources> </resources>
-4
View File
@@ -45,8 +45,4 @@ dependencies {
// shared // shared
implementation project(':shared:ui') implementation project(':shared:ui')
// https://mvnrepository.com/artifact/androidx.preference/preference
implementation 'androidx.preference:preference:1.2.1'
} }
@@ -2,12 +2,8 @@ package one.nem.lacerta.setting;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.PreferenceFragmentCompat;
import android.preference.PreferenceFragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -22,11 +18,6 @@ public class SettingScanPageFragment extends Fragment {
public SettingScanPageFragment() { public SettingScanPageFragment() {
// Required empty public constructor // Required empty public constructor
} }
//
// @Override
// public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
//// addPreferencesFromResource(R.xml.scan_preferences);
// }
public static SettingScanPageFragment newInstance() { public static SettingScanPageFragment newInstance() {
SettingScanPageFragment fragment = new SettingScanPageFragment(); SettingScanPageFragment fragment = new SettingScanPageFragment();
@@ -36,14 +27,15 @@ public class SettingScanPageFragment extends Fragment {
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
// Inflate the layout for this fragment super.onCreate(savedInstanceState);
return inflater.inflate(R.layout.fragment_setting_scan_page, container, false);
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container,
super.onViewCreated(view, savedInstanceState); Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_setting_scan_page, container, false);
} }
} }
@@ -1,16 +1,15 @@
package one.nem.lacerta.setting; package one.nem.lacerta.setting;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList; import java.util.ArrayList;
@@ -88,17 +87,6 @@ public class SettingTopFragment extends Fragment {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new ListItemAdapter(settingListItems)); recyclerView.setAdapter(new ListItemAdapter(settingListItems));
// Set status bar color
AppBarLayout appBarLayout = view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener((appBarLayout1, verticalOffset) -> {
if (Math.abs(verticalOffset) == appBarLayout1.getTotalScrollRange()) {
// Collapsed
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer));
} else if (verticalOffset == 0) {
// Expanded
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSurface));
}
});
return view; return view;
} }
} }
@@ -1,79 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorSurface"> tools:context=".SettingAboutPageFragment">
<androidx.coordinatorlayout.widget.CoordinatorLayout <!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
<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="@string/setting_top_about_title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="32dp"
android:background="@drawable/rounded_secondary_container" >
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work in Progress..."
android:textSize="24sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="実装中..."
android:textSize="16sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout> </FrameLayout>
@@ -1,79 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorSurface"> tools:context=".SettingDataPageFragment">
<androidx.coordinatorlayout.widget.CoordinatorLayout <!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
<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="@string/setting_top_data_title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="32dp"
android:background="@drawable/rounded_secondary_container" >
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work in Progress..."
android:textSize="24sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="実装中..."
android:textSize="16sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout> </FrameLayout>
@@ -1,79 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorSurface"> tools:context=".SettingDisplayPageFragment">
<androidx.coordinatorlayout.widget.CoordinatorLayout <!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
<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="@string/setting_top_display_title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="32dp"
android:background="@drawable/rounded_secondary_container" >
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work in Progress..."
android:textSize="24sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="実装中..."
android:textSize="16sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout> </FrameLayout>
@@ -1,79 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorSurface"> tools:context=".SettingScanPageFragment">
<androidx.coordinatorlayout.widget.CoordinatorLayout <!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
<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="@string/setting_top_scan_title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="32dp"
android:background="@drawable/rounded_secondary_container" >
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work in Progress..."
android:textSize="24sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="実装中..."
android:textSize="16sp"
android:textColor="@color/colorOnSurfaceSecondary"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout> </FrameLayout>
@@ -1,50 +1,11 @@
<FrameLayout 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:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="@color/colorSurface">
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.recyclerview.widget.RecyclerView
android:id="@+id/setting_item_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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="@string/setting_title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/setting_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>
</FrameLayout> </FrameLayout>
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="png_quality_array">
<item name="5">5</item>
<item name="6">6</item>
<item name="7">7</item>
<item name="8">8</item>
<item name="9">9</item>
</array>
</resources>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="png_quality_default">70</integer>
<integer name="png_quality_min">5</integer>
<integer name="png_quality_max">100</integer>
</resources>
@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory android:title="@string/setting_scan_quality_title">
<SeekBarPreference
android:defaultValue="@integer/png_quality_default"
android:key="png_quality"
android:max="@integer/png_quality_max"
android:min="@integer/png_quality_min"
android:summary="@string/setting_scan_quality_png_quality_description"
android:title="@string/setting_scan_quality_png_quality_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/setting_scan_default_title">
<EditTextPreference
android:defaultValue="Untitled"
android:key="new_doc_default_title"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/setting_scan_default_document_name" />
<EditTextPreference
android:defaultValue="NewFolder"
android:key="new_dir_default_title"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/setting_scan_default_folder_name" />
</PreferenceCategory>
</PreferenceScreen>
@@ -4,10 +4,4 @@ import androidx.fragment.app.Fragment;
public interface FragmentNavigation { public interface FragmentNavigation {
void navigateToFragment(Fragment fragment); void navigateToFragment(Fragment fragment);
void navigateToFragment(Fragment fragment, boolean addToBackStack);
void navigateToFragment(Fragment fragment, boolean addToBackStack, boolean clearBackStack);
void navigateToFragmentAlternate(Fragment fragment, boolean addToBackStack);
} }
@@ -6,18 +6,10 @@ public class LibraryItemPage {
String pageTitle; String pageTitle;
String pageId; String pageId;
String parentId;
ArrayList<ListItem> listItems; ArrayList<ListItem> listItems;
// Constructor // Constructor
public LibraryItemPage(String pageTitle, String pageId, ArrayList<ListItem> listItems, String parentId) {
this.pageTitle = pageTitle;
this.pageId = pageId;
this.listItems = listItems;
this.parentId = parentId;
}
public LibraryItemPage(String pageTitle, String pageId, ArrayList<ListItem> listItems) { public LibraryItemPage(String pageTitle, String pageId, ArrayList<ListItem> listItems) {
this.pageTitle = pageTitle; this.pageTitle = pageTitle;
this.pageId = pageId; this.pageId = pageId;
@@ -38,10 +30,6 @@ public class LibraryItemPage {
return pageId; return pageId;
} }
public String getParentId() {
return parentId;
}
public ArrayList<ListItem> getListItems() { public ArrayList<ListItem> getListItems() {
return listItems; return listItems;
} }
@@ -56,10 +44,6 @@ public class LibraryItemPage {
this.pageId = pageId; this.pageId = pageId;
} }
public void setParentId(String parentId) {
this.parentId = parentId;
}
public void setListItems(ArrayList<ListItem> listItems) { public void setListItems(ArrayList<ListItem> listItems) {
this.listItems = listItems; this.listItems = listItems;
} }
@@ -39,19 +39,14 @@ public class PublicPath {
} }
public PublicPath parse(String path) { public PublicPath parse(String path) {
if (path == null) { if (path.startsWith("/")) {
this.path.clear(); this.path.clear();
this.path.add("/"); path = path.substring(1);
} else { }
if (path.startsWith("/")) { String[] pathArray = path.split("/");
this.path.clear(); for (String p : pathArray) {
path = path.substring(1); Log.d("PublicPath", "parse: " + p);
} resolveInternal(p);
String[] pathArray = path.split("/");
for (String p : pathArray) {
Log.d("PublicPath", "parse: " + p);
resolveInternal(p);
}
} }
return this; return this;
} }
@@ -1,80 +0,0 @@
package one.nem.lacerta.model;
import java.util.ArrayList;
import java.util.Date;
public class VcsRevModel {
String id;
String documentId;
String branchName;
String commitMessage;
Date createdAt;
ArrayList<String> logIds;
public VcsRevModel(String id, String documentId, String branchName, String commitMessage, Date createdAt, ArrayList<String> logIds) {
this.id = id;
this.documentId = documentId;
this.branchName = branchName;
this.commitMessage = commitMessage;
this.createdAt = createdAt;
this.logIds = logIds;
}
// Empty constructor
public VcsRevModel() {
}
public String getId() {
return id;
}
public String getDocumentId() {
return documentId;
}
public String getBranchName() {
return branchName;
}
public String getCommitMessage() {
return commitMessage;
}
public Date getCreatedAt() {
return createdAt;
}
public ArrayList<String> getLogIds() {
return logIds;
}
public void setId(String id) {
this.id = id;
}
public void setDocumentId(String documentId) {
this.documentId = documentId;
}
public void setBranchName(String branchName) {
this.branchName = branchName;
}
public void setCommitMessage(String commitMessage) {
this.commitMessage = commitMessage;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public void setLogIds(ArrayList<String> logIds) {
this.logIds = logIds;
}
}
@@ -37,7 +37,7 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
*/ */
List<DocumentTag> tags; List<DocumentTag> tags;
String parentId; PublicPath path;
String author; String author;
@@ -54,7 +54,7 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
this.tags = new ArrayList<>(); this.tags = new ArrayList<>();
this.author = ""; // TODO-rca: 作者のデフォルト値を設定できるようにする this.author = ""; // TODO-rca: 作者のデフォルト値を設定できるようにする
this.defaultBranch = "main"; // TODO-rca: デフォルトブランチのデフォルト値を設定できるようにする this.defaultBranch = "main"; // TODO-rca: デフォルトブランチのデフォルト値を設定できるようにする
this.parentId = null; this.path = new PublicPath().getRoot();
this.updatedAt = new Date(); this.updatedAt = new Date();
this.createdAt = new Date(); this.createdAt = new Date();
} }
@@ -85,13 +85,13 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
this.defaultBranch = defaultBranch; this.defaultBranch = defaultBranch;
} }
public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, List<DocumentTag> tags, String parentId, String author, String defaultBranch) { public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, List<DocumentTag> tags, PublicPath path, String author, String defaultBranch) {
this.id = id; this.id = id;
this.title = title; this.title = title;
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
this.createdAt = createdAt; this.createdAt = createdAt;
this.tags = tags; this.tags = tags;
this.parentId = parentId; this.path = path;
this.author = author; this.author = author;
this.defaultBranch = defaultBranch; this.defaultBranch = defaultBranch;
} }
@@ -145,10 +145,10 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
} }
/** /**
* ドキュメントの親フォルダのID(String)を取得する * PublicPathを取得する
*/ */
public String getParentId() { public PublicPath getPath() {
return parentId; return path;
} }
/** /**
@@ -208,11 +208,11 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
} }
/** /**
* ドキュメントの親フォルダのID(String)を設定する * PublicPathを設定する
* @param parentId ドキュメントの親フォルダのID * @param path PublicPath
*/ */
public void setParentId(String parentId) { public void setPath(PublicPath path) {
this.parentId = parentId; this.path = path;
} }
/** /**
@@ -1,10 +0,0 @@
<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/colorOnSurface"
android:pathData="M570,630L630,630L630,550L710,550L710,490L630,490L630,410L570,410L570,490L490,490L490,550L570,550L570,630ZM172.31,780Q142,780 121,759Q100,738 100,707.69L100,252.31Q100,222 121,201Q142,180 172.31,180L391.92,180L471.92,260L787.69,260Q818,260 839,281Q860,302 860,332.31L860,707.69Q860,738 839,759Q818,780 787.69,780L172.31,780ZM172.31,720L787.69,720Q793.08,720 796.54,716.54Q800,713.08 800,707.69L800,332.31Q800,326.92 796.54,323.46Q793.08,320 787.69,320L447.39,320L367.39,240L172.31,240Q166.92,240 163.46,243.46Q160,246.92 160,252.31L160,707.69Q160,713.08 163.46,716.54Q166.92,720 172.31,720ZM160,720Q160,720 160,716.54Q160,713.08 160,707.69L160,252.31Q160,246.92 160,243.46Q160,240 160,240L160,240L160,320L160,320Q160,320 160,323.46Q160,326.92 160,332.31L160,707.69Q160,713.08 160,716.54Q160,720 160,720L160,720Z"/>
</vector>
@@ -19,14 +19,6 @@
<string name="setting_top_scan_title">スキャン</string> <string name="setting_top_scan_title">スキャン</string>
<string name="setting_top_scan_description">画質, 保存先</string> <string name="setting_top_scan_description">画質, 保存先</string>
<string name="setting_scan_quality_title">画質</string>
<string name="setting_scan_quality_png_quality_title">PNG画質</string>
<string name="setting_scan_quality_png_quality_description">PNG画質を設定します. 画質が高いほどファイルサイズが大きくなります.</string>
<string name="setting_scan_default_title">保存先</string>
<string name="setting_scan_default_document_name">新規ドキュメントのデフォルトタイトル</string>
<string name="setting_scan_default_folder_name">新規フォルダのデフォルト名</string>
<string name="setting_top_display_title">表示</string> <string name="setting_top_display_title">表示</string>
<string name="setting_top_display_description">テーマ, フォントサイズ</string> <string name="setting_top_display_description">テーマ, フォントサイズ</string>
@@ -19,7 +19,7 @@ import one.nem.lacerta.source.database.dao.LibraryDao;
import one.nem.lacerta.source.database.dao.VcsRevDao; import one.nem.lacerta.source.database.dao.VcsRevDao;
import one.nem.lacerta.source.database.dao.VcsLogDao; import one.nem.lacerta.source.database.dao.VcsLogDao;
@Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class, VcsRevEntity.class, VcsLogEntity.class, FolderEntity.class}, version = 5) @Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class, VcsRevEntity.class, VcsLogEntity.class, FolderEntity.class}, version = 4)
public abstract class LacertaDatabase extends RoomDatabase { public abstract class LacertaDatabase extends RoomDatabase {
public abstract TagDao tagDao(); public abstract TagDao tagDao();
public abstract DocumentDao documentDao(); public abstract DocumentDao documentDao();
@@ -29,11 +29,8 @@ public interface DocumentDao {
@Query("SELECT * FROM Document WHERE id IN (:ids)") @Query("SELECT * FROM Document WHERE id IN (:ids)")
List<DocumentEntity> findByIds(List<String> ids); List<DocumentEntity> findByIds(List<String> ids);
@Query("SELECT * FROM Document WHERE parent_id = :parentId") @Query("SELECT * FROM Document WHERE public_path = :publicPath LIMIT :limit")
List<DocumentEntity> findByParentId(String parentId); List<DocumentEntity> findByPublicPathWithLimit(String publicPath, int limit);
@Query("SELECT * FROM Document WHERE parent_id IS NULL")
List<DocumentEntity> findRootDocuments();
@Query("SELECT * FROM Document ORDER BY created_at DESC LIMIT :limit") @Query("SELECT * FROM Document ORDER BY created_at DESC LIMIT :limit")
List<DocumentEntity> getRecentDocument(int limit); List<DocumentEntity> getRecentDocument(int limit);
@@ -15,11 +15,11 @@ public interface FolderDao {
@Query("SELECT * FROM Folder WHERE id = :id") @Query("SELECT * FROM Folder WHERE id = :id")
FolderEntity findById(String id); FolderEntity findById(String id);
@Query("SELECT * FROM Folder WHERE parent_id = :parentId") @Query("SELECT * FROM Folder WHERE public_path = :publicPath")
List<FolderEntity> findByParentId(String parentId); FolderEntity findByPublicPath(String publicPath);
@Query("SELECT * FROM Folder WHERE parent_id IS NULL") @Query("SELECT * FROM Folder WHERE public_path = :publicPath LIMIT :limit")
List<FolderEntity> findRootFolders(); List<FolderEntity> findByPublicPathWithLimit(String publicPath, int limit);
@Insert @Insert
void insert(FolderEntity folderEntity); void insert(FolderEntity folderEntity);
@@ -40,6 +40,6 @@ public class DocumentEntity {
@ColumnInfo(name = "tag_ids") @ColumnInfo(name = "tag_ids")
public List<String> tagIds; // タグ public List<String> tagIds; // タグ
@ColumnInfo(name = "parent_id") @ColumnInfo(name = "public_path")
public String parentId; // 親フォルダID public String publicPath; // 公開パス
} }
@@ -16,7 +16,7 @@ public class FolderEntity {
@ColumnInfo(name = "title") @ColumnInfo(name = "title")
public String name; // フォルダ名 public String name; // フォルダ名
@ColumnInfo(name = "parent_id") @ColumnInfo(name = "public_path")
public String parentId; // 親フォルダID public String publicPath; // 公開パス
} }
@@ -20,8 +20,8 @@ import javax.xml.transform.stream.StreamResult;
import dagger.assisted.Assisted; import dagger.assisted.Assisted;
import dagger.assisted.AssistedInject; import dagger.assisted.AssistedInject;
import one.nem.lacerta.source.file.FileManager; import one.nem.lacerta.source.file.FileManager;
import one.nem.lacerta.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
import one.nem.lacerta.utils.Store;
public class FileManagerImpl implements FileManager { public class FileManagerImpl implements FileManager {
@@ -303,16 +303,7 @@ public class FileManagerImpl implements FileManager {
private void saveBitmapInternal(Bitmap bitmap, Path path) throws IOException { private void saveBitmapInternal(Bitmap bitmap, Path path) throws IOException {
try { try {
logger.debug("saveBitmapInternal", "path: " + path); logger.debug("saveBitmapInternal", "path: " + path);
// Bitmapの長辺を1024pxにする bitmap.compress(Bitmap.CompressFormat.PNG, 100, Files.newOutputStream(path));
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scale = 1.0f;
if (width > height) {
scale = Store.Scan.MAX_RESOLUTION_LONG / width;
} else {
scale = Store.Scan.MAX_RESOLUTION_LONG / height;
}
bitmap.compress(new Store.Scan().COMPRESS_FORMAT, Store.Scan.QUALITY, Files.newOutputStream(path));
} catch (Exception e) { } catch (Exception e) {
logger.error("saveBitmapInternal", e.getMessage()); logger.error("saveBitmapInternal", e.getMessage());
throw new IOException("Failed to save bitmap"); throw new IOException("Failed to save bitmap");
@@ -4,19 +4,6 @@ public class FeatureSwitch {
public static class Meta { public static class Meta {
public static boolean canOverrideSwitch = false; public static boolean canOverrideSwitch = false;
public static boolean disableDynamicColor = false;
}
public static class RecyclerView {
public static boolean useSimpleNotifyMethod = true;
}
public static class Viewer {
// TODO-rca: 実装
public static boolean showOriginalImage = false;
public static int maxImageSize = 1024;
public static boolean showProgressBarWhenLoading = true;
} }
public static class FeatureMaster { public static class FeatureMaster {
@@ -24,12 +11,7 @@ public class FeatureSwitch {
public static boolean enableDebugMenu = false; public static boolean enableDebugMenu = false;
} }
public static class Vcs {
public static boolean disableBranchDisplay = true;
}
public static class Setting { public static class Setting {
// TODO-rca: 実装
public static boolean showDisplayMenu = false; public static boolean showDisplayMenu = false;
public static boolean showDataMenu = false; public static boolean showDataMenu = false;
public static boolean showScanMenu = false; public static boolean showScanMenu = false;
@@ -1,11 +0,0 @@
package one.nem.lacerta.utils;
import android.graphics.Bitmap;
public class Store {
public static class Scan {
public Bitmap.CompressFormat COMPRESS_FORMAT = Bitmap.CompressFormat.JPEG;
public static final int QUALITY = 60;
public static final float MAX_RESOLUTION_LONG = 2048;
}
}
@@ -1,10 +1,5 @@
package one.nem.lacerta.vcs; package one.nem.lacerta.vcs;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import one.nem.lacerta.model.VcsRevModel;
public interface LacertaVcs { public interface LacertaVcs {
// Actions // Actions
@@ -18,8 +13,6 @@ public interface LacertaVcs {
public void generateRevisionAtCurrent(String message); public void generateRevisionAtCurrent(String message);
public CompletableFuture<ArrayList<VcsRevModel>> getRevisionHistory();
// debug // debug
public void printLog(); public void printLog();
@@ -1,16 +1,13 @@
package one.nem.lacerta.vcs.impl; package one.nem.lacerta.vcs.impl;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.assisted.Assisted; import dagger.assisted.Assisted;
import dagger.assisted.AssistedInject; import dagger.assisted.AssistedInject;
import one.nem.lacerta.model.VcsRevModel;
import one.nem.lacerta.source.database.LacertaDatabase; import one.nem.lacerta.source.database.LacertaDatabase;
import one.nem.lacerta.source.database.entity.VcsLogEntity; import one.nem.lacerta.source.database.entity.VcsLogEntity;
import one.nem.lacerta.source.database.entity.VcsRevEntity; import one.nem.lacerta.source.database.entity.VcsRevEntity;
@@ -125,28 +122,6 @@ public class LacertaVcsImpl implements LacertaVcs {
logger.debug(TAG, "New revision inserted: " + vcsRevEntity.id); logger.debug(TAG, "New revision inserted: " + vcsRevEntity.id);
} }
@Override
public CompletableFuture<ArrayList<VcsRevModel>> getRevisionHistory() {
return CompletableFuture.supplyAsync(() -> {
logger.debug(TAG, "getRevisionHistoryByDocumentId");
ArrayList<VcsRevModel> vcsRevModels = new ArrayList<>();
List<VcsRevEntity> vcsRevEntities = database.vcsRevDao().findByDocumentId(this.documentId);
vcsRevEntities.forEach(vcsRevEntity -> {
VcsRevModel vcsRevModel = new VcsRevModel();
vcsRevModel.setId(vcsRevEntity.id);
vcsRevModel.setDocumentId(vcsRevEntity.documentId);
vcsRevModel.setBranchName(vcsRevEntity.branchName);
vcsRevModel.setCreatedAt(vcsRevEntity.createdAt);
vcsRevModel.setCommitMessage(vcsRevEntity.commitMessage);
vcsRevModel.setLogIds(vcsRevEntity.logIds);
vcsRevModels.add(vcsRevModel);
});
return vcsRevModels;
});
}
@Override @Override
public void printLog() { public void printLog() {
logger.debug(TAG, "printLog"); logger.debug(TAG, "printLog");