Merge remote-tracking branch 'origin/develop' into develop
|
@ -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"
|
||||
|
|
BIN
app/src/main/ic_launcher_temp-playstore.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
|
@ -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...");
|
||||
if (FeatureSwitch.Meta.disableDynamicColor) {
|
||||
Log.d("DynamicColors", "DynamicColors is disabled by FeatureSwitch.");
|
||||
} else {
|
||||
DynamicColors.applyToActivitiesIfAvailable(this);
|
||||
}
|
||||
} else {
|
||||
Log.d("DynamicColors", "DynamicColors is not available.");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
15
app/src/main/res/drawable/ic_launcher_temp_foreground.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<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>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_temp.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?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>
|
|
@ -0,0 +1,5 @@
|
|||
<?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>
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_temp.webp
Normal file
After Width: | Height: | Size: 768 B |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_temp_round.webp
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_temp.webp
Normal file
After Width: | Height: | Size: 630 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_temp_round.webp
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_temp.webp
Normal file
After Width: | Height: | Size: 1004 B |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_temp_round.webp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_temp.webp
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_temp_round.webp
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp.webp
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_temp_round.webp
Normal file
After Width: | Height: | Size: 6.9 KiB |
4
app/src/main/res/values/ic_launcher_temp_background.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_temp_background">#A386EB</color>
|
||||
</resources>
|
|
@ -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;
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
android:icon="@drawable/save_24px"
|
||||
android:title="Save"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/action_insert_exist"
|
||||
android:icon="@drawable/ic_baseline_add_24"
|
||||
android:title="Save"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/action_insert_exist"-->
|
||||
<!-- android:icon="@drawable/description_24px"-->
|
||||
<!-- android:title="Insert"-->
|
||||
<!-- app:showAsAction="ifRoom"/>-->
|
||||
</menu>
|
|
@ -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<RevAdapter.RevViewHolder>{
|
|||
|
||||
private ArrayList<VcsRevModel> revModels;
|
||||
|
||||
private RevSelectListener revSelectListener;
|
||||
|
||||
public RevAdapter(ArrayList<VcsRevModel> revModels) {
|
||||
this.revModels = revModels;
|
||||
}
|
||||
|
||||
public RevAdapter() {
|
||||
public RevAdapter(RevSelectListener revSelectListener) {
|
||||
this.revSelectListener = revSelectListener;
|
||||
}
|
||||
|
||||
public void setRevModels(ArrayList<VcsRevModel> revModels) {
|
||||
|
@ -52,6 +56,13 @@ public class RevAdapter extends RecyclerView.Adapter<RevAdapter.RevViewHolder>{
|
|||
}
|
||||
holder.revId.setText("RevID: " + revModel.getId());
|
||||
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
revSelectListener.onRevSelect(revModel.getId());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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,6 +98,8 @@ public class ComponentViewerTopFragment extends Fragment {
|
|||
});
|
||||
recyclerView.setAdapter(viewerBodyAdapter);
|
||||
|
||||
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<Page> pages = documentDetail.getPages();
|
||||
|
@ -95,6 +110,22 @@ public class ComponentViewerTopFragment extends Fragment {
|
|||
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) {
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package one.nem.lacerta.component.viewer.model;
|
||||
|
||||
public interface RevSelectListener {
|
||||
void onRevSelect(String revisionId);
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="one.nem.lacerta.component.viewer.ComponentViewerTopFragment"
|
||||
android:name="one.nem.lacerta.component.viewer.ViewerListFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:defaultNavHost="true"
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/component_viewer_navigation"
|
||||
app:startDestination="@id/componentViewerTopFragment">
|
||||
app:startDestination="@id/viewerListFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/componentViewerTopFragment"
|
||||
android:name="one.nem.lacerta.component.viewer.ComponentViewerTopFragment"
|
||||
android:id="@+id/viewerListFragment"
|
||||
android:name="one.nem.lacerta.component.viewer.ViewerListFragment"
|
||||
android:label="ComponentViewerTopFragment" >
|
||||
<action
|
||||
android:id="@+id/action_componentViewerTopFragment_to_viewerVcsRevListFragment"
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import one.nem.lacerta.model.document.DocumentMeta;
|
||||
import one.nem.lacerta.model.document.DocumentDetail;
|
||||
import one.nem.lacerta.model.document.page.Page;
|
||||
import one.nem.lacerta.model.document.path.DocumentPath;
|
||||
import one.nem.lacerta.model.document.tag.DocumentTag;
|
||||
|
||||
|
@ -25,4 +26,6 @@ public interface Document {
|
|||
CompletableFuture<Void> updateDocument(DocumentDetail detail);
|
||||
|
||||
CompletableFuture<DocumentDetail> getDocument(String documentId);
|
||||
|
||||
CompletableFuture<ArrayList<Page>> getDocumentPageListByFileNameList(String documentId, ArrayList<String> fileNameList);
|
||||
}
|
||||
|
|
|
@ -173,6 +173,34 @@ public class DocumentImpl implements Document {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ArrayList<Page>> getDocumentPageListByFileNameList(String documentId, ArrayList<String> fileNameList) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ArrayList<Page> 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<ArrayList<XmlMetaPageModel>> getPagesByXmlMeta(String documentId) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
FileManager fileManager = fileManagerFactory.create(deviceInfoUtils.getExternalStorageDirectory());
|
||||
|
|
64
model/src/main/java/one/nem/lacerta/model/VcsLogModel.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -74,18 +74,24 @@ public class DocumentProcessorImpl implements DocumentProcessor{
|
|||
logger.debug("addNewPageToLast", "called");
|
||||
String filename = UUID.randomUUID().toString() + ".png"; // TODO-rca: 拡張子を動的にする
|
||||
|
||||
lacertaVcs.insertPage(this.documentDetail.getPages().size(), filename);
|
||||
|
||||
try {
|
||||
Page page = new Page();
|
||||
page.setFileName(filename);
|
||||
page.setBitmap(bitmap);
|
||||
this.documentDetail.getPages().add(page);
|
||||
|
||||
lacertaVcs.insertPage(documentDetail.getPages().size(), 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -52,4 +52,11 @@ public interface VcsLogDao {
|
|||
|
||||
@Update
|
||||
void updateAll(List<VcsLogEntity> 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);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public interface VcsRevDao {
|
|||
@Query("SELECT * FROM vcs_rev WHERE id IN (:ids)")
|
||||
List<VcsRevEntity> findByIds(List<String> 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<VcsRevEntity> findByDocumentId(String documentId);
|
||||
|
||||
@Query("SELECT * FROM vcs_rev WHERE document_id = :documentId ORDER BY created_at DESC LIMIT 1")
|
||||
|
|
|
@ -40,6 +40,12 @@ public class VcsLogEntity {
|
|||
@ColumnInfo(name = "created_at")
|
||||
public Date createdAt;
|
||||
|
||||
/**
|
||||
* アクションタイプ
|
||||
*/
|
||||
@ColumnInfo(name = "action_type")
|
||||
public String actionType;
|
||||
|
||||
/**
|
||||
* 発生アクション
|
||||
*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<ArrayList<VcsRevModel>> getRevisionHistory();
|
||||
|
||||
public CompletableFuture<ArrayList<VcsLogModel>> getLogHistory();
|
||||
|
||||
public CompletableFuture<ArrayList<VcsLogModel>> getLogHistoryInRev(String revId);
|
||||
|
||||
public CompletableFuture<ArrayList<String>> getDocumentPagePathListRev(String revId);
|
||||
|
||||
|
||||
// debug
|
||||
public void printLog();
|
||||
|
|
|
@ -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<ArrayList<VcsLogModel>> getLogHistory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ArrayList<VcsLogModel>> getLogHistoryInRev(String revId) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
logger.debug(TAG, "getLogHistoryInRev");
|
||||
ArrayList<VcsLogModel> vcsLogModels = new ArrayList<>();
|
||||
|
||||
VcsRevEntity vcsRevEntity = database.vcsRevDao().findById(revId);
|
||||
ArrayList<VcsLogEntity> 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<ArrayList<VcsRevEntity>> getRevBeforeTargetIdAsync(String revId){
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ArrayList<VcsRevEntity> vcsRevEntities = new ArrayList<>(database.vcsRevDao().findByDocumentId(this.documentId));
|
||||
ArrayList<VcsRevEntity> 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<ArrayList<VcsLogEntity>> getLogInRevsAsync(ArrayList<VcsRevEntity> vcsRevEntities){
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
List<String> logIds = new ArrayList<>();
|
||||
vcsRevEntities.forEach(vcsRevEntity -> {
|
||||
logIds.addAll(vcsRevEntity.logIds);
|
||||
});
|
||||
// TODO-rca: ソートしないといけないかも(順番が保証されているわけではない + 順番が変わるとほぼ確実に壊れる)
|
||||
ArrayList<VcsLogEntity> vcsLogEntities = new ArrayList<>(database.vcsLogDao().findByIds(logIds));
|
||||
logger.debug(TAG, "getLogInRevsAsync finished\nResult size: " + vcsLogEntities.size());
|
||||
return vcsLogEntities;
|
||||
});
|
||||
}
|
||||
|
||||
private CompletableFuture<ArrayList<VcsLogEntity>> getLogInRevAsync(VcsRevEntity revEntity) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ArrayList<VcsLogEntity> vcsLogEntities = new ArrayList<>(database.vcsLogDao().findByIds(revEntity.logIds));
|
||||
logger.debug(TAG, "getLogInRevAsync finished\nResult size: " + vcsLogEntities.size());
|
||||
return vcsLogEntities;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ArrayList<String>> getDocumentPagePathListRev(String revId) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
logger.debug(TAG, "getDocumentPagePathListRev");
|
||||
ArrayList<VcsLogEntity> vcsLogEntities = getRevBeforeTargetIdAsync(revId).thenCompose(this::getLogInRevsAsync).join();
|
||||
|
||||
ArrayList<String> 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");
|
||||
|
|