diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a5ae62e6..1680ef09 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,7 +17,7 @@
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
- android:icon="@mipmap/ic_launcher"
+ android:icon="@mipmap/ic_launcher_temp_round"
android:name=".LacertaApplication"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
diff --git a/app/src/main/ic_launcher_temp-playstore.png b/app/src/main/ic_launcher_temp-playstore.png
new file mode 100644
index 00000000..f83a7d3a
Binary files /dev/null and b/app/src/main/ic_launcher_temp-playstore.png differ
diff --git a/app/src/main/java/one/nem/lacerta/LacertaApplication.java b/app/src/main/java/one/nem/lacerta/LacertaApplication.java
index 448349b5..78dae9ae 100644
--- a/app/src/main/java/one/nem/lacerta/LacertaApplication.java
+++ b/app/src/main/java/one/nem/lacerta/LacertaApplication.java
@@ -6,6 +6,7 @@ import android.util.Log;
import com.google.android.material.color.DynamicColors;
import dagger.hilt.android.HiltAndroidApp;
+import one.nem.lacerta.utils.FeatureSwitch;
@HiltAndroidApp
public class LacertaApplication extends Application {
@@ -15,7 +16,11 @@ public class LacertaApplication extends Application {
if (DynamicColors.isDynamicColorAvailable()) {
Log.d("DynamicColors", "DynamicColors is available. Applying to activities...");
- DynamicColors.applyToActivitiesIfAvailable(this);
+ if (FeatureSwitch.Meta.disableDynamicColor) {
+ Log.d("DynamicColors", "DynamicColors is disabled by FeatureSwitch.");
+ } else {
+ DynamicColors.applyToActivitiesIfAvailable(this);
+ }
} else {
Log.d("DynamicColors", "DynamicColors is not available.");
}
diff --git a/app/src/main/java/one/nem/lacerta/MainActivity.java b/app/src/main/java/one/nem/lacerta/MainActivity.java
index f74b20a7..d7fac694 100644
--- a/app/src/main/java/one/nem/lacerta/MainActivity.java
+++ b/app/src/main/java/one/nem/lacerta/MainActivity.java
@@ -1,5 +1,6 @@
package one.nem.lacerta;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
@@ -11,6 +12,7 @@ import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
@@ -85,6 +87,21 @@ public class MainActivity extends AppCompatActivity implements FragmentNavigatio
});
}
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 1) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ Toast.makeText(this, "Permission granted", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, "カメラの権限は必須です.", Toast.LENGTH_LONG).show();
+ finish(); // Exit app
+ }
+ }
+ }
+
private void initializeApp() {
Log.d("Init", "Initializing app");
// Set feature switch override to default value
diff --git a/app/src/main/res/drawable/ic_launcher_temp_foreground.xml b/app/src/main/res/drawable/ic_launcher_temp_foreground.xml
new file mode 100644
index 00000000..3cf3c7d5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_temp_foreground.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp.xml
new file mode 100644
index 00000000..08dacb68
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp_round.xml
new file mode 100644
index 00000000..08dacb68
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_temp.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_temp.webp
new file mode 100644
index 00000000..83854c1d
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_temp.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_temp_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_temp_round.webp
new file mode 100644
index 00000000..6dbf2e77
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_temp_round.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_temp.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_temp.webp
new file mode 100644
index 00000000..9b879b55
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_temp.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_temp_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_temp_round.webp
new file mode 100644
index 00000000..dfd24231
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_temp_round.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_temp.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_temp.webp
new file mode 100644
index 00000000..b4efa44e
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_temp.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_temp_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_temp_round.webp
new file mode 100644
index 00000000..bcb26698
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_temp_round.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_temp.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_temp.webp
new file mode 100644
index 00000000..ccd89e0a
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_temp.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_temp_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_temp_round.webp
new file mode 100644
index 00000000..f4b04e3a
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_temp_round.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp.webp
new file mode 100644
index 00000000..91502f73
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp_round.webp
new file mode 100644
index 00000000..9d824496
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp_round.webp differ
diff --git a/app/src/main/res/values/ic_launcher_temp_background.xml b/app/src/main/res/values/ic_launcher_temp_background.xml
new file mode 100644
index 00000000..94a6cd1e
--- /dev/null
+++ b/app/src/main/res/values/ic_launcher_temp_background.xml
@@ -0,0 +1,4 @@
+
+
+ #A386EB
+
\ No newline at end of file
diff --git a/component/scanner/src/main/java/one/nem/lacerta/component/scanner/ScannerManagerActivity.java b/component/scanner/src/main/java/one/nem/lacerta/component/scanner/ScannerManagerActivity.java
index dcfc89fa..80cf6ae5 100644
--- a/component/scanner/src/main/java/one/nem/lacerta/component/scanner/ScannerManagerActivity.java
+++ b/component/scanner/src/main/java/one/nem/lacerta/component/scanner/ScannerManagerActivity.java
@@ -1,6 +1,8 @@
package one.nem.lacerta.component.scanner;
+import android.Manifest;
import android.app.ProgressDialog;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
@@ -11,6 +13,8 @@ import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
@@ -92,6 +96,14 @@ public class ScannerManagerActivity extends AppCompatActivity {
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);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
@@ -116,11 +128,12 @@ public class ScannerManagerActivity extends AppCompatActivity {
Toast.makeText(this, "保存処理", Toast.LENGTH_SHORT).show();
saveNewDocument();
return true;
- } else if (item.getItemId() == R.id.action_insert_exist) {
- // 既存ドキュメントに挿入
- Toast.makeText(this, "Work in progress", Toast.LENGTH_SHORT).show();
- insertToExistDocument();
- return true;
+// }
+// else if (item.getItemId() == R.id.action_insert_exist) {
+// // 既存ドキュメントに挿入
+// Toast.makeText(this, "Work in progress", Toast.LENGTH_SHORT).show();
+// insertToExistDocument();
+// return true;
} else if (item.getItemId() == android.R.id.home) {
finish();
return true;
diff --git a/component/scanner/src/main/res/menu/scanner_result_toolbar.xml b/component/scanner/src/main/res/menu/scanner_result_toolbar.xml
index 3321aadc..dc815d7b 100644
--- a/component/scanner/src/main/res/menu/scanner_result_toolbar.xml
+++ b/component/scanner/src/main/res/menu/scanner_result_toolbar.xml
@@ -6,9 +6,9 @@
android:icon="@drawable/save_24px"
android:title="Save"
app:showAsAction="ifRoom"/>
-
+
+
+
+
+
\ No newline at end of file
diff --git a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/RevAdapter.java b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/RevAdapter.java
index eb5c634f..4ad968c1 100644
--- a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/RevAdapter.java
+++ b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/RevAdapter.java
@@ -12,6 +12,7 @@ import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import one.nem.lacerta.component.viewer.model.RevSelectListener;
import one.nem.lacerta.model.VcsRevModel;
import one.nem.lacerta.utils.FeatureSwitch;
@@ -19,11 +20,14 @@ public class RevAdapter extends RecyclerView.Adapter{
private ArrayList revModels;
+ private RevSelectListener revSelectListener;
+
public RevAdapter(ArrayList revModels) {
this.revModels = revModels;
}
- public RevAdapter() {
+ public RevAdapter(RevSelectListener revSelectListener) {
+ this.revSelectListener = revSelectListener;
}
public void setRevModels(ArrayList revModels) {
@@ -52,6 +56,13 @@ public class RevAdapter extends RecyclerView.Adapter{
}
holder.revId.setText("RevID: " + revModel.getId());
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ revSelectListener.onRevSelect(revModel.getId());
+ }
+ });
+
}
@Override
diff --git a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ComponentViewerTopFragment.java b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerListFragment.java
similarity index 68%
rename from component/viewer/src/main/java/one/nem/lacerta/component/viewer/ComponentViewerTopFragment.java
rename to component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerListFragment.java
index 6e456d16..4c306755 100644
--- a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ComponentViewerTopFragment.java
+++ b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerListFragment.java
@@ -1,12 +1,10 @@
package one.nem.lacerta.component.viewer;
import android.app.AlertDialog;
-import android.graphics.Bitmap;
import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
-import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -16,24 +14,24 @@ import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
-import java.util.concurrent.CompletableFuture;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.Document;
-import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.page.Page;
import one.nem.lacerta.utils.FeatureSwitch;
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 ComponentViewerTopFragment#newInstance} factory method to
+ * Use the {@link ViewerListFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
-public class ComponentViewerTopFragment extends Fragment {
+public class ViewerListFragment extends Fragment {
@Inject
Document document;
@@ -41,17 +39,21 @@ public class ComponentViewerTopFragment extends Fragment {
@Inject
LacertaLogger logger;
+ @Inject
+ LacertaVcsFactory lacertaVcsFactory;
+
private static final String TAG = "ComponentViewerTopFragment";
private String documentId;
private String documentName;
+ private String revisionId;
- public ComponentViewerTopFragment() {
+ public ViewerListFragment() {
// Required empty public constructor
}
- public static ComponentViewerTopFragment newInstance(String documentId, String documentName) {
- ComponentViewerTopFragment fragment = new ComponentViewerTopFragment();
+ public static ViewerListFragment newInstance(String documentId, String documentName) {
+ ViewerListFragment fragment = new ViewerListFragment();
Bundle args = new Bundle();
args.putString("documentId", documentId);
args.putString("documentName", documentName);
@@ -59,12 +61,23 @@ public class ComponentViewerTopFragment extends Fragment {
return fragment;
}
+ public static ViewerListFragment newInstance(String documentId, String documentName, String revisionId) {
+ ViewerListFragment fragment = new ViewerListFragment();
+ Bundle args = new Bundle();
+ args.putString("documentId", documentId);
+ args.putString("documentName", documentName);
+ args.putString("revisionId", revisionId);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
documentId = getArguments().getString("documentId");
documentName = getArguments().getString("documentName");
+ revisionId = getArguments().getString("revisionId");
}
}
@@ -85,16 +98,34 @@ public class ComponentViewerTopFragment extends Fragment {
});
recyclerView.setAdapter(viewerBodyAdapter);
- if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.VISIBLE);
- document.getDocument(documentId).thenAccept(documentDetail -> {
- ArrayList pages = documentDetail.getPages();
- logger.debug(TAG, "pages.size(): " + pages.size());
- viewerBodyAdapter.setPages(pages);
- getActivity().runOnUiThread(() -> {
- viewerBodyAdapter.notifyItemRangeChanged(0, pages.size());
- if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.GONE);
+ if (revisionId == null) {
+ logger.debug(TAG, "revisionId is empty, loading latest revision");
+ if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.VISIBLE);
+ document.getDocument(documentId).thenAccept(documentDetail -> {
+ ArrayList pages = documentDetail.getPages();
+ logger.debug(TAG, "pages.size(): " + pages.size());
+ viewerBodyAdapter.setPages(pages);
+ getActivity().runOnUiThread(() -> {
+ viewerBodyAdapter.notifyItemRangeChanged(0, pages.size());
+ if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.GONE);
+ });
});
- });
+ } else {
+ logger.debug(TAG, "revisionId: " + revisionId);
+ if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.VISIBLE);
+ LacertaVcs lacertaVcs = lacertaVcsFactory.create(documentId);
+ lacertaVcs.getDocumentPagePathListRev(revisionId).thenAccept(documentPathList -> {
+ logger.debug(TAG, "documentPathList.size(): " + documentPathList.size());
+ document.getDocumentPageListByFileNameList(documentId, documentPathList).thenAccept(pages -> {
+ logger.debug(TAG, "pages.size(): " + pages.size());
+ viewerBodyAdapter.setPages(pages);
+ getActivity().runOnUiThread(() -> {
+ viewerBodyAdapter.notifyItemRangeChanged(0, pages.size());
+ if (FeatureSwitch.Viewer.showProgressBarWhenLoading) view.findViewById(R.id.loading_progress_bar).setVisibility(View.GONE);
+ });
+ });
+ });
+ }
return view;
}
@@ -123,7 +154,7 @@ public class ComponentViewerTopFragment extends Fragment {
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))
+ .replace(R.id.nav_host_fragment, ViewerVcsRevListFragment.newInstance(documentId, documentName))
.commit();
return true;
} else if (item.getItemId() == R.id.action_rename) {
diff --git a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerMainActivity.java b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerMainActivity.java
index 435e472c..6c079c11 100644
--- a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerMainActivity.java
+++ b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerMainActivity.java
@@ -2,7 +2,6 @@ package one.nem.lacerta.component.viewer;
import android.content.Intent;
import android.os.Bundle;
-import android.util.Log;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
@@ -10,12 +9,6 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
-import androidx.fragment.app.FragmentManager;
-import androidx.navigation.NavController;
-import androidx.navigation.fragment.NavHostFragment;
-import androidx.navigation.ui.NavigationUI;
-
-import com.google.android.material.bottomnavigation.BottomNavigationView;
import javax.inject.Inject;
@@ -62,7 +55,7 @@ public class ViewerMainActivity extends AppCompatActivity {
// Navigation
getSupportFragmentManager().beginTransaction()
- .replace(R.id.nav_host_fragment, ComponentViewerTopFragment.newInstance(documentId, documentName))
+ .replace(R.id.nav_host_fragment, ViewerListFragment.newInstance(documentId, documentName))
.commit();
}
}
\ No newline at end of file
diff --git a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerVcsRevListFragment.java b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerVcsRevListFragment.java
index 237c1564..a86d7e88 100644
--- a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerVcsRevListFragment.java
+++ b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/ViewerVcsRevListFragment.java
@@ -34,15 +34,17 @@ public class ViewerVcsRevListFragment extends Fragment {
LacertaVcs lacertaVcs;
private String documentId;
+ private String documentName;
public ViewerVcsRevListFragment() {
// Required empty public constructor
}
- public static ViewerVcsRevListFragment newInstance(String documentId) {
+ public static ViewerVcsRevListFragment newInstance(String documentId, String documentName) {
ViewerVcsRevListFragment fragment = new ViewerVcsRevListFragment();
Bundle args = new Bundle();
args.putString("documentId", documentId);
+ args.putString("documentName", documentName);
fragment.setArguments(args);
return fragment;
}
@@ -66,17 +68,22 @@ public class ViewerVcsRevListFragment extends Fragment {
// Init arg
if (getArguments() != null) {
this.documentId = getArguments().getString("documentId");
- logger.debug("ViewerVcsRevListFragment", "documentId: " + documentId);
+ logger.debug("ViewerVcsRevListFragment", "documentId: " + this.documentId);
}
// Init vcs
- lacertaVcs = lacertaVcsFactory.create(documentId);
+ lacertaVcs = lacertaVcsFactory.create(this.documentId);
// Init view
RecyclerView recyclerView = view.findViewById(R.id.rev_list);
// Init adapter
- RevAdapter revAdapter = new RevAdapter();
+ RevAdapter revAdapter = new RevAdapter(revisionId -> {
+ logger.debug("ViewerVcsRevListFragment", "Selected revisionId: " + revisionId);
+ getParentFragmentManager().beginTransaction()
+ .replace(R.id.nav_host_fragment, ViewerListFragment.newInstance(this.documentId, this.documentName, revisionId))
+ .commit();
+ });
// Set adapter
recyclerView.setAdapter(revAdapter);
diff --git a/component/viewer/src/main/java/one/nem/lacerta/component/viewer/model/RevSelectListener.java b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/model/RevSelectListener.java
new file mode 100644
index 00000000..f1a69486
--- /dev/null
+++ b/component/viewer/src/main/java/one/nem/lacerta/component/viewer/model/RevSelectListener.java
@@ -0,0 +1,5 @@
+package one.nem.lacerta.component.viewer.model;
+
+public interface RevSelectListener {
+ void onRevSelect(String revisionId);
+}
diff --git a/component/viewer/src/main/res/layout/activity_viewer_main.xml b/component/viewer/src/main/res/layout/activity_viewer_main.xml
index 73290603..f077ceec 100644
--- a/component/viewer/src/main/res/layout/activity_viewer_main.xml
+++ b/component/viewer/src/main/res/layout/activity_viewer_main.xml
@@ -9,7 +9,7 @@
+ app:startDestination="@id/viewerListFragment">
updateDocument(DocumentDetail detail);
CompletableFuture getDocument(String documentId);
+
+ CompletableFuture> getDocumentPageListByFileNameList(String documentId, ArrayList fileNameList);
}
diff --git a/data/src/main/java/one/nem/lacerta/data/impl/DocumentImpl.java b/data/src/main/java/one/nem/lacerta/data/impl/DocumentImpl.java
index 7a303ec5..523c7277 100644
--- a/data/src/main/java/one/nem/lacerta/data/impl/DocumentImpl.java
+++ b/data/src/main/java/one/nem/lacerta/data/impl/DocumentImpl.java
@@ -173,6 +173,34 @@ public class DocumentImpl implements Document {
});
}
+ @Override
+ public CompletableFuture> getDocumentPageListByFileNameList(String documentId, ArrayList fileNameList) {
+ return CompletableFuture.supplyAsync(() -> {
+ ArrayList pages = new ArrayList<>();
+ FileManager fileManager;
+ try {
+ fileManager = fileManagerFactory.create(deviceInfoUtils.getExternalStorageDirectory()).resolve(documentId).resolve("raw");
+ } catch (IOException e) {
+ logger.error(TAG, "FileManager resolve error");
+ logger.trace(TAG, e.getMessage());
+ logger.e_code("1210ae5b-dd2f-42ef-bc15-40b9a9bbdb16");
+ return null;
+ }
+
+ fileNameList.forEach(fileName -> {
+ try {
+ pages.add(new Page(fileName, fileManager.loadBitmap(fileName)));
+ } catch (IOException e) {
+ logger.error(TAG, "Bitmap decode error");
+ logger.trace(TAG, e.getMessage());
+ logger.e_code("6f9ba0dc-ac63-401c-8f50-a2bd9ff5cb91");
+ }
+ });
+
+ return pages;
+ });
+ }
+
private CompletableFuture> getPagesByXmlMeta(String documentId) {
return CompletableFuture.supplyAsync(() -> {
FileManager fileManager = fileManagerFactory.create(deviceInfoUtils.getExternalStorageDirectory());
diff --git a/model/src/main/java/one/nem/lacerta/model/VcsLogModel.java b/model/src/main/java/one/nem/lacerta/model/VcsLogModel.java
new file mode 100644
index 00000000..366f7a22
--- /dev/null
+++ b/model/src/main/java/one/nem/lacerta/model/VcsLogModel.java
@@ -0,0 +1,64 @@
+package one.nem.lacerta.model;
+
+import java.util.Date;
+
+public class VcsLogModel {
+
+ String id;
+ String documentId;
+ String branchName;
+ String action;
+ Date createdAt;
+
+ public VcsLogModel(String id, String documentId, String branchName, String action, Date createdAt) {
+ this.id = id;
+ this.documentId = documentId;
+ this.branchName = branchName;
+ this.action = action;
+ this.createdAt = createdAt;
+ }
+
+ // Empty constructor
+ public VcsLogModel() {
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getDocumentId() {
+ return documentId;
+ }
+
+ public String getBranchName() {
+ return branchName;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public Date getCreatedAt() {
+ return createdAt;
+ }
+
+ 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 setAction(String action) {
+ this.action = action;
+ }
+
+ public void setCreatedAt(Date createdAt) {
+ this.createdAt = createdAt;
+ }
+}
diff --git a/processor/src/main/java/one/nem/lacerta/processor/impl/DocumentProcessorImpl.java b/processor/src/main/java/one/nem/lacerta/processor/impl/DocumentProcessorImpl.java
index d2312b91..fea8396f 100644
--- a/processor/src/main/java/one/nem/lacerta/processor/impl/DocumentProcessorImpl.java
+++ b/processor/src/main/java/one/nem/lacerta/processor/impl/DocumentProcessorImpl.java
@@ -74,18 +74,24 @@ public class DocumentProcessorImpl implements DocumentProcessor{
logger.debug("addNewPageToLast", "called");
String filename = UUID.randomUUID().toString() + ".png"; // TODO-rca: 拡張子を動的にする
- Page page = new Page();
- page.setFileName(filename);
- page.setBitmap(bitmap);
- this.documentDetail.getPages().add(page);
+ lacertaVcs.insertPage(this.documentDetail.getPages().size(), filename);
- lacertaVcs.insertPage(documentDetail.getPages().size(), filename);
+ try {
+ Page page = new Page();
+ page.setFileName(filename);
+ page.setBitmap(bitmap);
+ this.documentDetail.getPages().add(page);
- this.fileManager.getNewInstance().createDirectoryIfNotExist(DEFAULT_SAVE_DIR).resolve(DEFAULT_SAVE_DIR).saveBitmap(bitmap, filename);
-
- logger.info("addNewPageToLast", "finished");
- logger.info("addNewPageToLast", "filename: " + filename);
+ this.fileManager.getNewInstance().createDirectoryIfNotExist(DEFAULT_SAVE_DIR).resolve(DEFAULT_SAVE_DIR).saveBitmap(bitmap, filename);
+ logger.info("addNewPageToLast", "finished");
+ logger.info("addNewPageToLast", "filename: " + filename);
+ } catch (Exception e) {
+ logger.error("addNewPageToLast", "failed: Unknown error");
+ logger.e_code("d9191286-6092-40b3-80ed-9239106a8c65");
+ // Recover (Undo latest action)
+ lacertaVcs.undo();
+ }
return this;
}
diff --git a/source/src/main/java/one/nem/lacerta/source/database/LacertaDatabase.java b/source/src/main/java/one/nem/lacerta/source/database/LacertaDatabase.java
index e3d6a6b9..47e0e4bb 100644
--- a/source/src/main/java/one/nem/lacerta/source/database/LacertaDatabase.java
+++ b/source/src/main/java/one/nem/lacerta/source/database/LacertaDatabase.java
@@ -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.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 TagDao tagDao();
public abstract DocumentDao documentDao();
diff --git a/source/src/main/java/one/nem/lacerta/source/database/dao/VcsLogDao.java b/source/src/main/java/one/nem/lacerta/source/database/dao/VcsLogDao.java
index 7721555f..b8923de9 100644
--- a/source/src/main/java/one/nem/lacerta/source/database/dao/VcsLogDao.java
+++ b/source/src/main/java/one/nem/lacerta/source/database/dao/VcsLogDao.java
@@ -52,4 +52,11 @@ public interface VcsLogDao {
@Update
void updateAll(List vcsLogs);
+
+ // Delete
+ @Query("DELETE FROM vcs_log WHERE id = :id")
+ void deleteById(String id);
+
+ @Query("DELETE FROM vcs_log WHERE id = (SELECT id FROM vcs_log WHERE document_id = :documentId ORDER BY created_at DESC LIMIT 1)")
+ void deleteLatestByDocumentId(String documentId);
}
diff --git a/source/src/main/java/one/nem/lacerta/source/database/dao/VcsRevDao.java b/source/src/main/java/one/nem/lacerta/source/database/dao/VcsRevDao.java
index 3213ca28..2df991fe 100644
--- a/source/src/main/java/one/nem/lacerta/source/database/dao/VcsRevDao.java
+++ b/source/src/main/java/one/nem/lacerta/source/database/dao/VcsRevDao.java
@@ -21,7 +21,7 @@ public interface VcsRevDao {
@Query("SELECT * FROM vcs_rev WHERE id IN (:ids)")
List findByIds(List ids);
- @Query("SELECT * FROM vcs_rev WHERE document_id = :documentId")
+ @Query("SELECT * FROM vcs_rev WHERE document_id = :documentId ORDER BY created_at ASC")
List findByDocumentId(String documentId);
@Query("SELECT * FROM vcs_rev WHERE document_id = :documentId ORDER BY created_at DESC LIMIT 1")
diff --git a/source/src/main/java/one/nem/lacerta/source/database/entity/VcsLogEntity.java b/source/src/main/java/one/nem/lacerta/source/database/entity/VcsLogEntity.java
index 17628e8e..152d5333 100644
--- a/source/src/main/java/one/nem/lacerta/source/database/entity/VcsLogEntity.java
+++ b/source/src/main/java/one/nem/lacerta/source/database/entity/VcsLogEntity.java
@@ -40,6 +40,12 @@ public class VcsLogEntity {
@ColumnInfo(name = "created_at")
public Date createdAt;
+ /**
+ * アクションタイプ
+ */
+ @ColumnInfo(name = "action_type")
+ public String actionType;
+
/**
* 発生アクション
*/
diff --git a/utils/src/main/java/one/nem/lacerta/utils/FeatureSwitch.java b/utils/src/main/java/one/nem/lacerta/utils/FeatureSwitch.java
index 5c808841..aae02397 100644
--- a/utils/src/main/java/one/nem/lacerta/utils/FeatureSwitch.java
+++ b/utils/src/main/java/one/nem/lacerta/utils/FeatureSwitch.java
@@ -4,6 +4,8 @@ public class FeatureSwitch {
public static class Meta {
public static boolean canOverrideSwitch = false;
+
+ public static boolean disableDynamicColor = false;
}
public static class RecyclerView {
diff --git a/vcs/src/main/java/one/nem/lacerta/vcs/LacertaVcs.java b/vcs/src/main/java/one/nem/lacerta/vcs/LacertaVcs.java
index 664c45e1..cccc44ac 100644
--- a/vcs/src/main/java/one/nem/lacerta/vcs/LacertaVcs.java
+++ b/vcs/src/main/java/one/nem/lacerta/vcs/LacertaVcs.java
@@ -3,7 +3,9 @@ package one.nem.lacerta.vcs;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
+import one.nem.lacerta.model.VcsLogModel;
import one.nem.lacerta.model.VcsRevModel;
+import one.nem.lacerta.model.document.DocumentDetail;
public interface LacertaVcs {
@@ -14,12 +16,20 @@ public interface LacertaVcs {
public void deletePage(int index);
+ public void undo();
+
public void createDocument(String documentId);
public void generateRevisionAtCurrent(String message);
public CompletableFuture> getRevisionHistory();
+ public CompletableFuture> getLogHistory();
+
+ public CompletableFuture> getLogHistoryInRev(String revId);
+
+ public CompletableFuture> getDocumentPagePathListRev(String revId);
+
// debug
public void printLog();
diff --git a/vcs/src/main/java/one/nem/lacerta/vcs/impl/LacertaVcsImpl.java b/vcs/src/main/java/one/nem/lacerta/vcs/impl/LacertaVcsImpl.java
index 93d701d2..5e193bcd 100644
--- a/vcs/src/main/java/one/nem/lacerta/vcs/impl/LacertaVcsImpl.java
+++ b/vcs/src/main/java/one/nem/lacerta/vcs/impl/LacertaVcsImpl.java
@@ -1,15 +1,13 @@
package one.nem.lacerta.vcs.impl;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
-import javax.inject.Inject;
-
import dagger.assisted.Assisted;
import dagger.assisted.AssistedInject;
+import one.nem.lacerta.model.VcsLogModel;
import one.nem.lacerta.model.VcsRevModel;
import one.nem.lacerta.source.database.LacertaDatabase;
import one.nem.lacerta.source.database.entity.VcsLogEntity;
@@ -18,7 +16,9 @@ import one.nem.lacerta.utils.LacertaLogger;
import one.nem.lacerta.vcs.ActionType;
import one.nem.lacerta.vcs.LacertaVcs;
import one.nem.lacerta.vcs.internal.JsonUtils;
+import one.nem.lacerta.vcs.model.action.DeletePage;
import one.nem.lacerta.vcs.model.action.InsertPage;
+import one.nem.lacerta.vcs.model.action.UpdatePage;
public class LacertaVcsImpl implements LacertaVcs {
@@ -57,6 +57,7 @@ public class LacertaVcsImpl implements LacertaVcs {
vcsLogEntity.documentId = documentId;
vcsLogEntity.branchName = "master";
vcsLogEntity.createdAt = new java.util.Date();
+ vcsLogEntity.actionType = ActionType.INSERT_PAGE.getValue();
vcsLogEntity.action = JsonUtils.toJson(insertPage);
database.vcsLogDao().insert(vcsLogEntity);
}
@@ -66,6 +67,11 @@ public class LacertaVcsImpl implements LacertaVcs {
}
+ @Override
+ public void undo() {
+ database.vcsLogDao().deleteLatestByDocumentId(documentId);
+ }
+
@Override
public void createDocument(String documentId) {
logger.debug(TAG, "createDocument");
@@ -75,7 +81,8 @@ public class LacertaVcsImpl implements LacertaVcs {
vcsLogEntity.documentId = documentId;
vcsLogEntity.branchName = "master";
vcsLogEntity.createdAt = new java.util.Date();
- vcsLogEntity.action = "ph-createDocument";
+ vcsLogEntity.actionType = ActionType.CREATE_DOCUMENT.getValue();
+ vcsLogEntity.action = "";
database.vcsLogDao().insert(vcsLogEntity);
}
@@ -147,6 +154,108 @@ public class LacertaVcsImpl implements LacertaVcs {
});
}
+ @Override
+ public CompletableFuture> getLogHistory() {
+ return null;
+ }
+
+ @Override
+ public CompletableFuture> getLogHistoryInRev(String revId) {
+ return CompletableFuture.supplyAsync(() -> {
+ logger.debug(TAG, "getLogHistoryInRev");
+ ArrayList vcsLogModels = new ArrayList<>();
+
+ VcsRevEntity vcsRevEntity = database.vcsRevDao().findById(revId);
+ ArrayList vcsLogEntities = getLogInRevAsync(vcsRevEntity).join(); // TODO-rca: リファクタリング
+ vcsLogEntities.forEach(vcsLogEntity -> {
+ VcsLogModel vcsLogModel = new VcsLogModel();
+ vcsLogModel.setId(vcsLogEntity.id);
+ vcsLogModel.setDocumentId(vcsLogEntity.documentId);
+ vcsLogModel.setBranchName(vcsLogEntity.branchName);
+ vcsLogModel.setCreatedAt(vcsLogEntity.createdAt);
+ vcsLogModel.setAction(vcsLogEntity.action);
+ vcsLogModels.add(vcsLogModel);
+ });
+
+ return vcsLogModels;
+ });
+ }
+
+ private CompletableFuture> getRevBeforeTargetIdAsync(String revId){
+ return CompletableFuture.supplyAsync(() -> {
+ ArrayList vcsRevEntities = new ArrayList<>(database.vcsRevDao().findByDocumentId(this.documentId));
+ ArrayList vcsRevEntitiesBeforeTarget = new ArrayList<>();
+ vcsRevEntities.forEach(vcsRevEntity -> {
+ if(vcsRevEntity.id.equals(revId)){
+ vcsRevEntitiesBeforeTarget.add(vcsRevEntity);
+ return;
+ }
+ vcsRevEntitiesBeforeTarget.add(vcsRevEntity);
+ });
+ logger.debug(TAG, "getRevBeforeTargetIdAsync finished\nResult size: " + vcsRevEntitiesBeforeTarget.size());
+ return vcsRevEntitiesBeforeTarget;
+ });
+ }
+
+ private CompletableFuture> getLogInRevsAsync(ArrayList vcsRevEntities){
+ return CompletableFuture.supplyAsync(() -> {
+ List logIds = new ArrayList<>();
+ vcsRevEntities.forEach(vcsRevEntity -> {
+ logIds.addAll(vcsRevEntity.logIds);
+ });
+ // TODO-rca: ソートしないといけないかも(順番が保証されているわけではない + 順番が変わるとほぼ確実に壊れる)
+ ArrayList vcsLogEntities = new ArrayList<>(database.vcsLogDao().findByIds(logIds));
+ logger.debug(TAG, "getLogInRevsAsync finished\nResult size: " + vcsLogEntities.size());
+ return vcsLogEntities;
+ });
+ }
+
+ private CompletableFuture> getLogInRevAsync(VcsRevEntity revEntity) {
+ return CompletableFuture.supplyAsync(() -> {
+ ArrayList vcsLogEntities = new ArrayList<>(database.vcsLogDao().findByIds(revEntity.logIds));
+ logger.debug(TAG, "getLogInRevAsync finished\nResult size: " + vcsLogEntities.size());
+ return vcsLogEntities;
+ });
+ }
+
+ @Override
+ public CompletableFuture> getDocumentPagePathListRev(String revId) {
+ return CompletableFuture.supplyAsync(() -> {
+ logger.debug(TAG, "getDocumentPagePathListRev");
+ ArrayList vcsLogEntities = getRevBeforeTargetIdAsync(revId).thenCompose(this::getLogInRevsAsync).join();
+
+ ArrayList fileNameList = new ArrayList<>();
+ for(VcsLogEntity vcsLogEntity : vcsLogEntities){
+ logger.debug(TAG, "getDocumentPagePathListRev: processing " + vcsLogEntity.id + "(Type: " + vcsLogEntity.actionType + ")");
+ if (vcsLogEntity.actionType.equals(ActionType.INSERT_PAGE.getValue())){
+ InsertPage insertPage = (InsertPage) JsonUtils.fromJson(vcsLogEntity.action, ActionType.INSERT_PAGE);
+ logger.debug(TAG, "getDocumentPagePathListRev: Inserting " + insertPage.getFileName() + " at " + insertPage.getIndex());
+ if (fileNameList.size() <= insertPage.getIndex()) {
+ logger.debug(TAG, "Index out of range, appending");
+ fileNameList.add(insertPage.getFileName());
+ } else {
+ fileNameList.add(insertPage.getIndex(), insertPage.getFileName());
+ }
+ } else if (vcsLogEntity.actionType.equals(ActionType.UPDATE_PAGE.getValue())){
+ UpdatePage updatePage = (UpdatePage) JsonUtils.fromJson(vcsLogEntity.action, ActionType.UPDATE_PAGE);
+ logger.debug(TAG, "getDocumentPagePathListRev: Updating " + updatePage.getFileName() + " at " + updatePage.getIndex());
+ fileNameList.set(updatePage.getIndex(), updatePage.getFileName());
+ } else if (vcsLogEntity.actionType.equals(ActionType.DELETE_PAGE.getValue())){
+ DeletePage deletePage = (DeletePage) JsonUtils.fromJson(vcsLogEntity.action, ActionType.DELETE_PAGE);
+ logger.debug(TAG, "getDocumentPagePathListRev: Deleting " + deletePage.getIndex());
+ fileNameList.remove(deletePage.getIndex());
+ } else if (vcsLogEntity.actionType.equals(ActionType.CREATE_DOCUMENT.getValue())) {
+ // Ignore
+ logger.debug(TAG, "getDocumentPagePathListRev: Ignored action type: " + vcsLogEntity.actionType);
+ } else {
+ logger.error(TAG, "getDocumentPagePathListRev: Unknown action type");
+ }
+ }
+
+ return fileNameList;
+ });
+ }
+
@Override
public void printLog() {
logger.debug(TAG, "printLog");