Merge pull request #90 from lacerta-doc/feature/library/add

Feature/library/add
This commit is contained in:
ろむねこ 2024-01-22 10:32:47 +09:00 committed by GitHub
commit 9da41e73aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 244 additions and 111 deletions

View File

@ -31,6 +31,7 @@
app:labelVisibilityMode="selected" app:labelVisibilityMode="selected"
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"
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,7 @@
package one.nem.lacerta.data.impl; package one.nem.lacerta.data.impl;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -16,6 +17,7 @@ import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.source.database.LacertaDatabase; 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.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
public class LacertaLibraryImpl implements LacertaLibrary { public class LacertaLibraryImpl implements LacertaLibrary {
@ -60,10 +62,56 @@ 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 @Override
public CompletableFuture<LibraryItemPage> getLibraryPage(int limit) { public CompletableFuture<LibraryItemPage> getLibraryPage(int limit) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
return null; 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;
}); });
} }

View File

@ -51,5 +51,7 @@ dependencies {
implementation project(':data') implementation project(':data')
implementation project(':utils')
} }

View File

@ -0,0 +1,5 @@
package one.nem.lacerta.feature.library;
public interface DocumentSelectListener {
void onDocumentSelect(String documentId);
}

View File

@ -1,38 +0,0 @@
package one.nem.lacerta.feature.library;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
// LibraryArchiveFragment.java
//画面変移用のコード
//Fragmentへのデータの受け渡し機能
public class LibraryArchiveFragment extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_library_top);
// ここに入力された内容を表示する機能
TextView textView = findViewById(R.id.document_list);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 文字をタップしたときの処理
// 移動先のアクティビティを指定
Intent intent = new Intent(LibraryArchiveFragment.this, LibraryDocFragment.class);
// データを付加する
intent.putExtra("key_name", "value_data");
startActivity(intent);
}
});
}
}

View File

@ -3,6 +3,9 @@ package one.nem.lacerta.feature.library;
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.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -15,6 +18,9 @@ import android.widget.ListView;
import android.widget.TextView; 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 java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -22,8 +28,10 @@ import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint; import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.Document; import one.nem.lacerta.data.Document;
import one.nem.lacerta.data.LacertaLibrary;
import one.nem.lacerta.model.document.DocumentMeta; import one.nem.lacerta.model.document.DocumentMeta;
import one.nem.lacerta.model.document.tag.DocumentTag; import one.nem.lacerta.model.document.tag.DocumentTag;
import one.nem.lacerta.utils.LacertaLogger;
@ -35,36 +43,18 @@ import one.nem.lacerta.model.document.tag.DocumentTag;
@AndroidEntryPoint @AndroidEntryPoint
public class LibraryTopFragment extends Fragment { public class LibraryTopFragment extends Fragment {
// @Inject @Inject
// Document document; LacertaLibrary lacertaLibrary;
// TODO: Rename parameter arguments, choose names that match @Inject
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER LacertaLogger logger;
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public LibraryTopFragment() { public LibraryTopFragment() {
// Required empty public constructor // Required empty public constructor
} }
public static LibraryTopFragment newInstance() {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment LibraryTopFragment.
*/
// TODO: Rename and change types and number of parameters
public static LibraryTopFragment newInstance(String param1, String param2) {
LibraryTopFragment fragment = new LibraryTopFragment(); LibraryTopFragment fragment = new LibraryTopFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@ -72,10 +62,6 @@ public class LibraryTopFragment extends Fragment {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
} }
@ -84,23 +70,53 @@ public class LibraryTopFragment 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);
// Use view.findViewById instead of findViewById
RecyclerView documentRecyclerView = view.findViewById(R.id.document_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
documentRecyclerView.setLayoutManager(layoutManager);
//データを取得
// List<DocumentMeta> metas = document.getAllDocumentMetas(100);
// Toast.makeText(getContext(), "Documents: " + Integer.toString(metas.size()), Toast.LENGTH_LONG).show();
// Create and set the adapter
// DocumentAdapter adapter = new DocumentAdapter(metas);
// documentRecyclerView.setAdapter(adapter);
// Use a LinearLayoutManager to specify the layout
return view; return view;
} }
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = view.findViewById(R.id.library_item_recycler_view);
ListItemAdapter listItemAdapter = new ListItemAdapter(documentId -> {
Toast.makeText(getContext(), documentId, Toast.LENGTH_SHORT).show();
});
recyclerView.setAdapter(listItemAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> {
logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size());
listItemAdapter.setLibraryItemPage(libraryItemPage);
getActivity().runOnUiThread(() -> {
listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1);
});
});
CollapsingToolbarLayout collapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar);
Toolbar toolbar = view.findViewById(R.id.toolbar);
// Set the Toolbar
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
// Set the title of the CollapsingToolbarLayout
collapsingToolbarLayout.setTitle("Library");
AppBarLayout appBarLayout = view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) {
// Collapsed
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getActivity(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer));
} else if (verticalOffset == 0) {
// Expanded
getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getActivity(), one.nem.lacerta.shared.ui.R.color.colorSurface));
} else {
// Somewhere in between
// Here you can add a color transition if you want
}
}
});
}
} }

View File

@ -0,0 +1,74 @@
package one.nem.lacerta.feature.library;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.ListItem;
public class ListItemAdapter extends RecyclerView.Adapter<ListItemAdapter.ListItemViewHolder>{
LibraryItemPage libraryItemPage;
DocumentSelectListener listener;
public ListItemAdapter(DocumentSelectListener listener) {
this.listener = listener;
}
public void setLibraryItemPage(LibraryItemPage libraryItemPage) {
this.libraryItemPage = libraryItemPage;
}
@NonNull
@Override
public ListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(one.nem.lacerta.shared.ui.R.layout.common_list_item, parent, false);
return new ListItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ListItemViewHolder holder, int position) {
ListItem listItem = libraryItemPage.getListItems().get(position);
holder.icon.setImageResource(listItem.getItemType().getIconId());
holder.icon.setColorFilter(one.nem.lacerta.shared.ui.R.color.colorOnSurface);
holder.title.setText(listItem.getTitle());
holder.description.setText(listItem.getDescription());
holder.itemView.setOnClickListener( v -> {
// Intent intent = new Intent(v.getContext(), ViewerMainActivity.class);
// intent.putExtra("documentId", listItem.getItemId());
// v.getContext().startActivity(intent);
});
}
@Override
public int getItemCount() {
return this.libraryItemPage == null ? 0
: this.libraryItemPage.getListItems() == null ? 0 : this.libraryItemPage.getListItems().size();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder{
ImageView icon;
TextView title;
TextView description;
public ListItemViewHolder(@NonNull View itemView) {
super(itemView);
icon = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_icon);
title = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_title);
description = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.item_description);
}
}
}

View File

@ -1,32 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <FrameLayout 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"
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=".LibraryTopFragment">
<com.google.android.material.appbar.MaterialToolbar <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/tool_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:background="@color/colorPrimaryContainer"
<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" android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" app:collapsedTitleGravity="start|center_vertical"
app:layout_constraintEnd_toEndOf="parent" app:expandedTitleGravity="start|bottom"
app:layout_constraintStart_toStartOf="parent" app:expandedTitleMarginBottom="16dp"
app:layout_constraintTop_toTopOf="parent" app:expandedTitleMarginStart="16dp"
app:title="Library" app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4"
app:titleTextColor="@color/colorOnPrimaryContainer" /> app:layout_scrollFlags="scroll|exitUntilCollapsed">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title="HOGE" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/document_list" android:id="@+id/library_item_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tool_bar" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>

View File

@ -6,6 +6,7 @@ import androidx.room.Insert;
import androidx.room.Query; import androidx.room.Query;
import androidx.room.Update; import androidx.room.Update;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import one.nem.lacerta.source.database.entity.DocumentEntity; import one.nem.lacerta.source.database.entity.DocumentEntity;

View File

@ -4,6 +4,9 @@ import androidx.room.Dao;
import androidx.room.Insert; import androidx.room.Insert;
import androidx.room.Query; import androidx.room.Query;
import java.util.ArrayList;
import java.util.List;
import one.nem.lacerta.source.database.entity.FolderEntity; import one.nem.lacerta.source.database.entity.FolderEntity;
@Dao @Dao
@ -15,6 +18,9 @@ public interface FolderDao {
@Query("SELECT * FROM Folder WHERE public_path = :publicPath") @Query("SELECT * FROM Folder WHERE public_path = :publicPath")
FolderEntity findByPublicPath(String publicPath); FolderEntity findByPublicPath(String publicPath);
@Query("SELECT * FROM Folder WHERE public_path = :publicPath LIMIT :limit")
List<FolderEntity> findByPublicPathWithLimit(String publicPath, int limit);
@Insert @Insert
void insert(FolderEntity folderEntity); void insert(FolderEntity folderEntity);

View File

@ -3,12 +3,12 @@ package one.nem.lacerta.utils;
public class FeatureSwitch { public class FeatureSwitch {
public static class Meta { public static class Meta {
public static boolean canOverrideSwitch = true; public static boolean canOverrideSwitch = false;
} }
public static class FeatureMaster { public static class FeatureMaster {
public static boolean enableSearch = true; public static boolean enableSearch = true;
public static boolean enableDebugMenu = false; public static boolean enableDebugMenu = true;
} }
public static class Setting { public static class Setting {