mirror of
				https://github.com/lacerta-doc/Lacerta.git
				synced 2025-10-31 15:30:49 +00:00 
			
		
		
		
	
						commit
						ca063709dd
					
				| @ -5,12 +5,16 @@ import androidx.appcompat.widget.Toolbar; | ||||
| import androidx.core.content.ContextCompat; | ||||
| import androidx.fragment.app.Fragment; | ||||
| import androidx.fragment.app.FragmentManager; | ||||
| import androidx.fragment.app.FragmentTransaction; | ||||
| import androidx.navigation.NavController; | ||||
| import androidx.navigation.fragment.NavHostFragment; | ||||
| import androidx.navigation.ui.NavigationUI; | ||||
| 
 | ||||
| import android.graphics.Color; | ||||
| import android.os.Bundle; | ||||
| import android.util.Log; | ||||
| import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import one.nem.lacerta.model.FragmentNavigation; | ||||
| @ -21,6 +25,8 @@ import com.google.android.material.appbar.AppBarLayout; | ||||
| import com.google.android.material.bottomnavigation.BottomNavigationView; | ||||
| 
 | ||||
| 
 | ||||
| import java.io.NotActiveException; | ||||
| 
 | ||||
| import dagger.hilt.android.AndroidEntryPoint; | ||||
| import one.nem.lacerta.utils.repository.SharedPrefUtils; | ||||
| 
 | ||||
| @ -68,37 +74,7 @@ public class MainActivity extends AppCompatActivity implements FragmentNavigatio | ||||
|         // Set status bar color | ||||
|         getWindow().setStatusBarColor(ContextCompat.getColor(this, one.nem.lacerta.shared.ui.R.color.colorSurface)); | ||||
| 
 | ||||
|         // Set app bar color | ||||
|         AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout); | ||||
|         appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { | ||||
|             @Override | ||||
|             public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { | ||||
|                 if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) { | ||||
|                     // Collapsed | ||||
|                     getWindow().setStatusBarColor(ContextCompat.getColor(getApplicationContext(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer)); | ||||
|                 } else if (verticalOffset == 0) { | ||||
|                     // Expanded | ||||
|                     getWindow().setStatusBarColor(ContextCompat.getColor(getApplicationContext(), one.nem.lacerta.shared.ui.R.color.colorSurface)); | ||||
|                 } else { | ||||
|                     // Somewhere in between | ||||
|                     // Here you can add a color transition if you want | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         Toolbar toolbar = findViewById(R.id.toolbar); | ||||
|         setSupportActionBar(toolbar); | ||||
|     } | ||||
| 
 | ||||
|     // Public | ||||
|     public void setActionBarTitle(String title) { | ||||
|         getSupportActionBar().setTitle(title); | ||||
|     } | ||||
| 
 | ||||
|     public void setActionBarBackButton(boolean isEnabled) { | ||||
|         getSupportActionBar().setDisplayHomeAsUpEnabled(isEnabled); | ||||
|     } | ||||
| 
 | ||||
|     private void initializeApp() { | ||||
|         Log.d("Init", "Initializing app"); | ||||
|         // Set feature switch override to default value | ||||
| @ -121,4 +97,61 @@ public class MainActivity extends AppCompatActivity implements FragmentNavigatio | ||||
|                 .addToBackStack(null) | ||||
|                 .commit(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void navigateToFragment(Fragment fragment, boolean addToBackStack) { | ||||
|         if (addToBackStack) { | ||||
|             getSupportFragmentManager().beginTransaction() | ||||
|                     .replace(R.id.nav_host_fragment, fragment) | ||||
|                     .addToBackStack(null) | ||||
|                     .commit(); | ||||
|         } else { | ||||
|             getSupportFragmentManager().beginTransaction() | ||||
|                     .replace(R.id.nav_host_fragment, fragment) | ||||
|                     .commit(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void navigateToFragment(Fragment fragment, boolean addToBackStack, boolean clearBackStack) { | ||||
|         if (clearBackStack) { | ||||
|             getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); | ||||
|         } | ||||
|         if (addToBackStack) { | ||||
|             getSupportFragmentManager().beginTransaction() | ||||
|                     .replace(R.id.nav_host_fragment, fragment) | ||||
|                     .addToBackStack(null) | ||||
|                     .commit(); | ||||
|         } else { | ||||
|             getSupportFragmentManager().beginTransaction() | ||||
|                     .replace(R.id.nav_host_fragment, fragment) | ||||
|                     .commit(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public void navigateToFragmentAlternate(Fragment fragment, boolean addToBackStack) { | ||||
|         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); | ||||
| 
 | ||||
|         // get the current fragment | ||||
|         Fragment currentFragment = getSupportFragmentManager().getPrimaryNavigationFragment(); | ||||
| 
 | ||||
|         // hide the current fragment | ||||
|         if (currentFragment != null) { | ||||
|             transaction.hide(currentFragment); | ||||
|         } | ||||
| 
 | ||||
|         // Add the new fragment | ||||
|         transaction.add(R.id.nav_host_fragment, fragment); | ||||
| 
 | ||||
|         // Add the transaction to the back stack if needed | ||||
|         if (addToBackStack) { | ||||
|             transaction.addToBackStack(null); | ||||
|         } | ||||
| 
 | ||||
|         // Commit the transaction | ||||
|         transaction.commit(); | ||||
| 
 | ||||
|         // Update the primary navigation fragment | ||||
|         getSupportFragmentManager().beginTransaction().setPrimaryNavigationFragment(fragment).commit(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,61 +1,24 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/colorSurface"> | ||||
|     android:theme="@style/Theme.Lacerta" | ||||
|     tools:context=".MainActivity"> | ||||
| 
 | ||||
|     <androidx.coordinatorlayout.widget.CoordinatorLayout | ||||
|     <androidx.fragment.app.FragmentContainerView | ||||
|         android:id="@+id/nav_host_fragment" | ||||
|         android:name="androidx.navigation.fragment.NavHostFragment" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="0dp" | ||||
|         app:layout_constraintBottom_toTopOf="@id/bottom_nav" | ||||
|         app:defaultNavHost="true" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/bottom_nav" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent"> | ||||
| 
 | ||||
|         <com.google.android.material.appbar.AppBarLayout | ||||
|             android:id="@+id/app_bar_layout" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
| 
 | ||||
|             <com.google.android.material.appbar.CollapsingToolbarLayout | ||||
|                 android:id="@+id/collapsing_toolbar" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="160dp" | ||||
|                 android:background="@color/colorSurface" | ||||
|                 android:fitsSystemWindows="true" | ||||
|                 android:minHeight="?attr/actionBarSize" | ||||
|                 app:collapsedTitleGravity="start|center_vertical" | ||||
|                 app:contentScrim="@color/colorSecondaryContainer" | ||||
|                 app:expandedTitleGravity="start|bottom" | ||||
|                 app:expandedTitleMarginBottom="16dp" | ||||
|                 app:expandedTitleMarginStart="16dp" | ||||
|                 app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4" | ||||
|                 app:layout_scrollFlags="scroll|exitUntilCollapsed"> | ||||
| 
 | ||||
|                 <androidx.appcompat.widget.Toolbar | ||||
|                     android:id="@+id/toolbar" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="?attr/actionBarSize" | ||||
|                     app:layout_collapseMode="pin" | ||||
|                     app:title="HOGE" /> | ||||
| 
 | ||||
|             </com.google.android.material.appbar.CollapsingToolbarLayout> | ||||
| 
 | ||||
|         </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|         <androidx.fragment.app.FragmentContainerView | ||||
| 
 | ||||
|             android:id="@+id/nav_host_fragment" | ||||
|             android:name="androidx.navigation.fragment.NavHostFragment" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             app:defaultNavHost="true" | ||||
|             app:navGraph="@navigation/main_nav" | ||||
|             tools:layout="@layout/fragment_home_top" | ||||
|             app:layout_behavior="@string/appbar_scrolling_view_behavior"/> | ||||
| 
 | ||||
|     </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:navGraph="@navigation/main_nav" | ||||
|         tools:layout="@layout/fragment_home_top" /> | ||||
| 
 | ||||
|     <com.google.android.material.bottomnavigation.BottomNavigationView | ||||
|         android:id="@+id/bottom_nav" | ||||
|  | ||||
| @ -7,6 +7,7 @@ import one.nem.lacerta.model.ListItem; | ||||
| import one.nem.lacerta.model.ListItemType; | ||||
| 
 | ||||
| import one.nem.lacerta.model.LibraryItemPage; | ||||
| import one.nem.lacerta.model.PublicPath; | ||||
| import one.nem.lacerta.model.document.DocumentDetail; | ||||
| 
 | ||||
| public interface LacertaLibrary { | ||||
| @ -15,13 +16,14 @@ public interface LacertaLibrary { | ||||
|     CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit); | ||||
|     CompletableFuture<ArrayList<ListItem>> getRecentDocument(int limit, int offset); | ||||
| 
 | ||||
|     // Get Library page | ||||
|     CompletableFuture<LibraryItemPage> getLibraryPage(int limit); | ||||
|     CompletableFuture<LibraryItemPage> getLibraryPage(int limit, int offset); | ||||
|     // Get Library Page | ||||
|     CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit); | ||||
|     CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit, int offset); | ||||
| 
 | ||||
|     // Create Folder | ||||
|     CompletableFuture<String> createFolder(String path, String name); | ||||
|     CompletableFuture<String> createFolder(String parentId, String name); | ||||
| 
 | ||||
|     // Get Public Path | ||||
|     CompletableFuture<PublicPath> getPublicPath(String itemId, ListItemType itemType); | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -79,7 +79,7 @@ public class DocumentImpl implements Document { | ||||
|             documentEntity.defaultBranch = meta.getDefaultBranch(); | ||||
|             documentEntity.updatedAt = meta.getUpdatedAt(); | ||||
|             documentEntity.createdAt = meta.getCreatedAt(); | ||||
|             documentEntity.publicPath = meta.getPath().getStringPath(); | ||||
|             documentEntity.parentId = meta.getParentId(); | ||||
|             documentEntity.tagIds = meta.getTagIds(); | ||||
| 
 | ||||
|             database.documentDao().insert(documentEntity); | ||||
| @ -104,7 +104,7 @@ public class DocumentImpl implements Document { | ||||
|         meta.setDefaultBranch("master"); | ||||
|         meta.setUpdatedAt(new Date()); | ||||
|         meta.setCreatedAt(new Date()); | ||||
|         meta.setPath(new PublicPath().getRoot()); // TODO-rca: 2回インスタンスを生成していて無駄なのでなんとかする | ||||
|         meta.setParentId(null); | ||||
|         meta.setTags(new ArrayList<>()); | ||||
|         return createDocument(meta); | ||||
|     } | ||||
| @ -138,7 +138,7 @@ public class DocumentImpl implements Document { | ||||
|             meta.setDefaultBranch(documentEntity.defaultBranch); | ||||
|             meta.setUpdatedAt(documentEntity.updatedAt); | ||||
|             meta.setCreatedAt(documentEntity.createdAt); | ||||
|             meta.setPath(new PublicPath().resolve(documentEntity.publicPath)); | ||||
|             meta.setParentId(documentEntity.parentId); | ||||
|             meta.setTags(new ArrayList<>()); // TODO-rca: タグを取得する | ||||
| 
 | ||||
|             DocumentDetail detail = new DocumentDetail(); | ||||
|  | ||||
| @ -4,6 +4,7 @@ import java.text.DateFormat; | ||||
| import java.time.format.DateTimeFormatter; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| @ -20,6 +21,7 @@ import one.nem.lacerta.source.database.LacertaDatabase; | ||||
| import one.nem.lacerta.source.database.common.DateTypeConverter; | ||||
| import one.nem.lacerta.source.database.entity.DocumentEntity; | ||||
| import one.nem.lacerta.source.database.entity.FolderEntity; | ||||
| import one.nem.lacerta.utils.FeatureSwitch; | ||||
| import one.nem.lacerta.utils.LacertaLogger; | ||||
| 
 | ||||
| public class LacertaLibraryImpl implements LacertaLibrary { | ||||
| @ -64,95 +66,35 @@ public class LacertaLibraryImpl implements LacertaLibrary { | ||||
|         return null; // TODO-rca: Implement | ||||
|     } | ||||
| 
 | ||||
|     // Internal | ||||
|     private CompletableFuture<List<FolderEntity>> getFolderEntitiesByPublicPath(String publicPath) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
|             return database.folderDao().findByPublicPathWithLimit(publicPath, 10); // TODO-rca: ハードコーディングやめる | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private CompletableFuture<List<DocumentEntity>> getDocumentEntitiesByPublicPath(String publicPath) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
|             return database.documentDao().findByPublicPathWithLimit(publicPath, 10); // TODO-rca: ハードコーディングやめる | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public CompletableFuture<LibraryItemPage> getLibraryPage(int limit) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
| 
 | ||||
|             // 5秒フリーズさせる | ||||
|             try { | ||||
|                 Thread.sleep(1000); | ||||
|             } catch (InterruptedException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } | ||||
| 
 | ||||
|             LibraryItemPage libraryItemPage = new LibraryItemPage(); | ||||
| 
 | ||||
|             List<FolderEntity> folderEntities = getFolderEntitiesByPublicPath("/").join(); | ||||
|             logger.debug("LacertaLibraryImpl", "folderEntities.size(): " + folderEntities.size()); | ||||
|             List<DocumentEntity> documentEntities = getDocumentEntitiesByPublicPath("/").join(); | ||||
|             logger.debug("LacertaLibraryImpl", "documentEntities.size(): " + documentEntities.size()); | ||||
| 
 | ||||
|             ArrayList<ListItem> listItems = new ArrayList<>(); | ||||
|             for (FolderEntity folderEntity : folderEntities) { | ||||
|                 logger.debug("LacertaLibraryImpl", "folderEntity.name: " + folderEntity.name); | ||||
|                 ListItem listItem = new ListItem(); | ||||
|                 listItem.setItemType(ListItemType.ITEM_TYPE_FOLDER); | ||||
|                 listItem.setTitle(folderEntity.name); | ||||
|                 listItem.setDescription("フォルダ"); // TODO-rca: ハードコーディングやめる | ||||
|                 listItem.setItemId(folderEntity.id); | ||||
|                 listItems.add(listItem); | ||||
|             } | ||||
|             for (DocumentEntity documentEntity : documentEntities) { | ||||
|                 logger.debug("LacertaLibraryImpl", "documentEntity.title: " + documentEntity.title); | ||||
|                 ListItem listItem = new ListItem(); | ||||
|                 listItem.setItemType(ListItemType.ITEM_TYPE_DOCUMENT); | ||||
|                 listItem.setTitle(documentEntity.title); | ||||
| //                listItem.setDescription(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm").format(documentEntity.updatedAt.toInstant())); | ||||
|                 listItem.setItemId(documentEntity.id); | ||||
|                 listItems.add(listItem); | ||||
|             } | ||||
| 
 | ||||
|             libraryItemPage.setPageTitle("/"); | ||||
|             libraryItemPage.setPageId("root"); | ||||
|             libraryItemPage.setListItems(listItems); | ||||
| 
 | ||||
|             logger.debug("LacertaLibraryImpl", "libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); | ||||
| 
 | ||||
|             return libraryItemPage; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public CompletableFuture<LibraryItemPage> getLibraryPage(int limit, int offset) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
|             return null; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public CompletableFuture<LibraryItemPage> getLibraryPage(String pageId, int limit) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
|             LibraryItemPage libraryItemPage = new LibraryItemPage(); | ||||
| 
 | ||||
|             FolderEntity folderEntity = database.folderDao().findById(pageId); | ||||
|             if (folderEntity == null) { | ||||
|                 return null; | ||||
|             List<FolderEntity> folderEntities; | ||||
|             List<DocumentEntity> documentEntities; | ||||
| 
 | ||||
|             if (pageId == null) { // When root folder | ||||
|                 libraryItemPage.setPageTitle("ライブラリ"); | ||||
|                 libraryItemPage.setPageId(null); | ||||
|                 libraryItemPage.setParentId(null); | ||||
| 
 | ||||
|                 folderEntities = database.folderDao().findRootFolders(); | ||||
|                 documentEntities = database.documentDao().findRootDocuments(); | ||||
|             } else { | ||||
|                 FolderEntity folderEntity = database.folderDao().findById(pageId); | ||||
|                 if (folderEntity == null) { | ||||
|                     logger.warn("LacertaLibraryImpl", pageId + " is not found."); | ||||
|                     return null; | ||||
|                 } | ||||
|                 libraryItemPage.setPageTitle(folderEntity.name); | ||||
|                 libraryItemPage.setPageId(folderEntity.id); | ||||
|                 libraryItemPage.setParentId(folderEntity.parentId); | ||||
| 
 | ||||
|                 folderEntities = database.folderDao().findByParentId(pageId); | ||||
|                 documentEntities = database.documentDao().findByParentId(pageId); | ||||
|             } | ||||
| 
 | ||||
|             PublicPath publicPath = new PublicPath().parse(folderEntity.publicPath); | ||||
| 
 | ||||
|             String resolvedPublicPath = publicPath.resolve(folderEntity.name).getStringPath(); | ||||
| 
 | ||||
|             logger.debug("LacertaLibraryImpl", "Resolved publicPath: " + resolvedPublicPath); | ||||
| 
 | ||||
|             List<FolderEntity> folderEntities = getFolderEntitiesByPublicPath(resolvedPublicPath).join(); | ||||
|             logger.debug("LacertaLibraryImpl", "folderEntities.size(): " + folderEntities.size()); | ||||
|             List<DocumentEntity> documentEntities = getDocumentEntitiesByPublicPath(resolvedPublicPath).join(); | ||||
|             logger.debug("LacertaLibraryImpl", "documentEntities.size(): " + documentEntities.size()); | ||||
| 
 | ||||
|             ArrayList<ListItem> listItems = new ArrayList<>(); | ||||
|             for (FolderEntity childFolderEntity : folderEntities) { | ||||
|                 logger.debug("LacertaLibraryImpl", "childFolderEntity.name: " + childFolderEntity.name); | ||||
| @ -174,8 +116,6 @@ public class LacertaLibraryImpl implements LacertaLibrary { | ||||
|                 listItems.add(listItem); | ||||
|             } | ||||
| 
 | ||||
|             libraryItemPage.setPageTitle(folderEntity.name); | ||||
|             libraryItemPage.setPageId(folderEntity.id); | ||||
|             libraryItemPage.setListItems(listItems); | ||||
| 
 | ||||
|             logger.debug("LacertaLibraryImpl", "libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); | ||||
| @ -194,21 +134,67 @@ public class LacertaLibraryImpl implements LacertaLibrary { | ||||
|     @Override | ||||
|     public CompletableFuture<String> createFolder(String parentId, String name) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
| 
 | ||||
|             FolderEntity parentFolderEntity = database.folderDao().findById(parentId); | ||||
|             PublicPath publicPath; | ||||
|             if (parentFolderEntity == null) { | ||||
|                 publicPath = new PublicPath().resolve("/"); | ||||
|             } else { | ||||
|                 publicPath = new PublicPath().resolve(parentFolderEntity.publicPath); | ||||
|             } | ||||
| 
 | ||||
|             FolderEntity folderEntity = new FolderEntity(); | ||||
|             folderEntity.id = UUID.randomUUID().toString(); | ||||
|             folderEntity.name = name; | ||||
|             folderEntity.publicPath = publicPath.getStringPath(); | ||||
|             folderEntity.parentId = parentId; | ||||
|             database.folderDao().insert(folderEntity); | ||||
|             return folderEntity.id; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public CompletableFuture<PublicPath> getPublicPath(String itemId, ListItemType itemType) { | ||||
|         return CompletableFuture.supplyAsync(() -> { | ||||
|             if (itemType == ListItemType.ITEM_TYPE_DOCUMENT) { | ||||
|                 DocumentEntity documentEntity = database.documentDao().findById(itemId); | ||||
|                 if (documentEntity == null) { | ||||
|                     logger.warn("LacertaLibraryImpl", itemId + " is not found."); | ||||
|                     return null; | ||||
|                 } | ||||
|                 PublicPath publicPath = recursiveResolve(documentEntity.parentId); | ||||
|                 publicPath.resolve(documentEntity.title); | ||||
|                 return publicPath; | ||||
|             } else if (itemType == ListItemType.ITEM_TYPE_FOLDER) { | ||||
|                 FolderEntity folderEntity = database.folderDao().findById(itemId); | ||||
|                 if (folderEntity == null) { | ||||
|                     return null; | ||||
|                 } | ||||
|                 return recursiveResolve(folderEntity.id); | ||||
|             } else { | ||||
|                 logger.warn("LacertaLibraryImpl", "Unknown ListItemType: " + itemType); | ||||
|                 return null; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 再帰的にパスを解決する | ||||
|      * | ||||
|      * @param folderId | ||||
|      * @return | ||||
|      */ | ||||
|     private PublicPath recursiveResolve(String folderId) { | ||||
|         String current = folderId; | ||||
|         boolean continueFlag = true; | ||||
|         ArrayList<String> folderNames = new ArrayList<>(); | ||||
|         while (continueFlag) { | ||||
|             FolderEntity folderEntity = database.folderDao().findById(current); | ||||
|             if (folderEntity == null) { // 存在しないフォルダIDが指定された場合 | ||||
|                 continueFlag = false; | ||||
|             } else { | ||||
|                 folderNames.add(folderEntity.name); | ||||
|                 current = folderEntity.parentId; | ||||
|                 if (current == null) { // ルートフォルダに到達した場合 | ||||
|                     continueFlag = false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // フォルダ名を逆順にしてListに変換 | ||||
|         Collections.reverse(folderNames); | ||||
|         List<String> folderNamesReversed = new ArrayList<>(folderNames); | ||||
| 
 | ||||
|         return new PublicPath(folderNamesReversed); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,50 @@ | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent"> | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/colorSurface"> | ||||
| 
 | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/home_item_recycler_view" | ||||
|     <androidx.coordinatorlayout.widget.CoordinatorLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" /> | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.google.android.material.appbar.AppBarLayout | ||||
|             android:id="@+id/app_bar_layout" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
| 
 | ||||
|             <com.google.android.material.appbar.CollapsingToolbarLayout | ||||
|                 android:id="@+id/collapsing_toolbar" | ||||
|                 app:contentScrim="@color/colorSecondaryContainer" | ||||
|                 android:background="@color/colorSurface" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="160dp" | ||||
|                 android:fitsSystemWindows="true" | ||||
|                 android:minHeight="?attr/actionBarSize" | ||||
|                 app:collapsedTitleGravity="start|center_vertical" | ||||
|                 app:expandedTitleGravity="start|bottom" | ||||
|                 app:expandedTitleMarginBottom="16dp" | ||||
|                 app:expandedTitleMarginStart="16dp" | ||||
|                 app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4" | ||||
|                 app:layout_scrollFlags="scroll|exitUntilCollapsed"> | ||||
| 
 | ||||
|                 <androidx.appcompat.widget.Toolbar | ||||
|                     android:id="@+id/toolbar" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="?attr/actionBarSize" | ||||
|                     app:layout_collapseMode="pin" | ||||
|                     app:title="HOGE" /> | ||||
| 
 | ||||
|             </com.google.android.material.appbar.CollapsingToolbarLayout> | ||||
| 
 | ||||
|         </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|         <androidx.recyclerview.widget.RecyclerView | ||||
|             android:id="@+id/home_item_recycler_view" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             app:layout_behavior="@string/appbar_scrolling_view_behavior" /> | ||||
| 
 | ||||
|     </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||
| 
 | ||||
| </FrameLayout> | ||||
| @ -4,7 +4,11 @@ import android.app.AlertDialog; | ||||
| import android.os.Bundle; | ||||
| 
 | ||||
| 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.navigation.Navigation; | ||||
| import androidx.recyclerview.widget.LinearLayoutManager; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| @ -14,13 +18,28 @@ import android.view.MenuInflater; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.ArrayAdapter; | ||||
| import android.widget.ListView; | ||||
| import android.widget.TextView; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import com.google.android.material.appbar.AppBarLayout; | ||||
| import com.google.android.material.appbar.CollapsingToolbarLayout; | ||||
| 
 | ||||
| import org.w3c.dom.Text; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| import javax.inject.Inject; | ||||
| 
 | ||||
| import dagger.hilt.android.AndroidEntryPoint; | ||||
| import one.nem.lacerta.data.Document; | ||||
| import one.nem.lacerta.data.LacertaLibrary; | ||||
| import one.nem.lacerta.model.FragmentNavigation; | ||||
| import one.nem.lacerta.model.LibraryItemPage; | ||||
| import one.nem.lacerta.model.PublicPath; | ||||
| import one.nem.lacerta.utils.LacertaLogger; | ||||
| 
 | ||||
| 
 | ||||
| @ -32,8 +51,15 @@ import one.nem.lacerta.utils.LacertaLogger; | ||||
| @AndroidEntryPoint | ||||
| public class LibraryPageFragment extends Fragment { | ||||
| 
 | ||||
|     // Param | ||||
|     private String folderId; | ||||
|     // Variables | ||||
|     // このインスタンスで表示されているページ | ||||
|     LibraryItemPage libraryItemPage; | ||||
| 
 | ||||
|     // Arguments | ||||
|     String folderId; | ||||
|     String title; | ||||
|     String parentId; | ||||
| 
 | ||||
| 
 | ||||
|     @Inject | ||||
|     LacertaLibrary lacertaLibrary; | ||||
| @ -43,15 +69,26 @@ public class LibraryPageFragment extends Fragment { | ||||
| 
 | ||||
|     ListItemAdapter listItemAdapter; | ||||
| 
 | ||||
|     int currentTotalItemCount = 0; | ||||
| 
 | ||||
|     public LibraryPageFragment() { | ||||
|         // Required empty public constructor | ||||
|     } | ||||
|     public static LibraryPageFragment newInstance(String folderId) { | ||||
| 
 | ||||
|     public static LibraryPageFragment newInstance(String folderId, String title, String parentId) { | ||||
|         LibraryPageFragment fragment = new LibraryPageFragment(); | ||||
|         Bundle args = new Bundle(); | ||||
|         args.putString("folderId", folderId); | ||||
|         args.putString("title", title); | ||||
|         args.putString("publicPath", parentId); | ||||
|         fragment.setArguments(args); | ||||
|         return fragment; | ||||
|     } | ||||
| 
 | ||||
|     public static LibraryPageFragment newInstance(String folderId) { // Back action | ||||
|         LibraryPageFragment fragment = new LibraryPageFragment(); | ||||
|         Bundle args = new Bundle(); | ||||
|         args.putString("folderId", folderId); | ||||
|         args.putString("title", null); | ||||
|         args.putString("publicPath", null); | ||||
|         fragment.setArguments(args); | ||||
|         return fragment; | ||||
|     } | ||||
| @ -60,6 +97,8 @@ public class LibraryPageFragment extends Fragment { | ||||
|         LibraryPageFragment fragment = new LibraryPageFragment(); | ||||
|         Bundle args = new Bundle(); | ||||
|         args.putString("folderId", null); | ||||
|         args.putString("title", null); | ||||
|         args.putString("publicPath", null); | ||||
|         fragment.setArguments(args); | ||||
|         return fragment; | ||||
|     } | ||||
| @ -75,8 +114,23 @@ public class LibraryPageFragment extends Fragment { | ||||
|         // Inflate the layout for this fragment | ||||
|         View view = inflater.inflate(R.layout.fragment_library_top, container, false); | ||||
| 
 | ||||
|         setHasOptionsMenu(true); | ||||
| 
 | ||||
|         // Set status bar color | ||||
|         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(getContext(), one.nem.lacerta.shared.ui.R.color.colorSecondaryContainer)); | ||||
|                 } else if (verticalOffset == 0) { | ||||
|                     // Expanded | ||||
|                     getActivity().getWindow().setStatusBarColor(ContextCompat.getColor(getContext(), one.nem.lacerta.shared.ui.R.color.colorSurface)); | ||||
|                 } else { | ||||
|                     // Somewhere in between | ||||
|                     // Here you can add a color transition if you want | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         return view; | ||||
|     } | ||||
| 
 | ||||
| @ -84,16 +138,42 @@ public class LibraryPageFragment extends Fragment { | ||||
|     public void onViewCreated(View view, Bundle savedInstanceState) { | ||||
|         super.onViewCreated(view, savedInstanceState); | ||||
| 
 | ||||
|         RecyclerView recyclerView = view.findViewById(R.id.library_item_recycler_view); | ||||
|         if (getArguments() != null) { | ||||
|             this.folderId = getArguments().getString("folderId"); // Required | ||||
|             if (getArguments().getString("title") == null && getArguments().getString("publicPath") == null) { | ||||
|                 this.libraryItemPage = new LibraryItemPage(); | ||||
|             } else { | ||||
|                 this.title = getArguments().getString("title"); | ||||
|                 this.parentId = getArguments().getString("publicPath"); | ||||
|             } | ||||
|         } else { | ||||
|             logger.debug("LibraryTopFragment", "getArguments() is null(maybe root)"); | ||||
|             this.libraryItemPage = new LibraryItemPage(); | ||||
|         } | ||||
| 
 | ||||
|         // Toolbar Setup | ||||
|         toolbarSetup(view.findViewById(R.id.library_toolbar), this.folderId != null, this.title != null ? this.title : "ライブラリ"); | ||||
| 
 | ||||
|         // RecyclerView Setup | ||||
| 
 | ||||
|         RecyclerView recyclerView = view.findViewById(R.id.library_item_recycler_view); | ||||
|         this.listItemAdapter = new ListItemAdapter(new DocumentSelectListener() { | ||||
|             @Override | ||||
|             public void onFolderSelected(String folderId, String folderName) { | ||||
|                 logger.debug("LibraryTopFragment", "Folder selected! folderId: " + folderId + ", folderName: " + folderName); | ||||
|                 // 画面遷移 | ||||
|                 FragmentNavigation fragmentNavigation = (FragmentNavigation) getActivity(); | ||||
|                 assert fragmentNavigation != null; | ||||
|                 fragmentNavigation.navigateToFragment(LibraryPageFragment.newInstance(folderId)); | ||||
| //                // 画面遷移 | ||||
| //                FragmentNavigation fragmentNavigation = (FragmentNavigation) getActivity(); | ||||
| //                // folderId: 推移先で表示するフォルダのID, folderName: 推移先で表示するフォルダの名前, parentId: このフラグメントで表示しているフォルダのID(推移先の親) | ||||
| //                fragmentNavigation.navigateToFragment(LibraryPageFragment.newInstance(folderId, folderName, libraryItemPage != null ? libraryItemPage.getParentId() : null), false); | ||||
|                 Bundle bundle = new Bundle(); | ||||
|                 bundle.putString("folderId", folderId); | ||||
|                 bundle.putString("title", folderName); | ||||
|                 bundle.putString("publicPath", libraryItemPage != null ? libraryItemPage.getParentId() : null); | ||||
|                 try { | ||||
|                     Navigation.findNavController(requireView()).navigate(R.id.action_feature_library_top_fragment_self, bundle); | ||||
|                 } catch (IllegalStateException e) { | ||||
|                     logger.error("LibraryTopFragment", "IllegalStateException: " + e.getMessage()); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
| @ -101,86 +181,103 @@ public class LibraryPageFragment extends Fragment { | ||||
|                 Toast.makeText(getContext(), "Document selected! documentId: " + documentId + ", documentName: " + documentName, Toast.LENGTH_SHORT).show(); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         recyclerView.setAdapter(listItemAdapter); | ||||
|         recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); | ||||
| 
 | ||||
|         if (getArguments() != null) { | ||||
|             this.folderId = getArguments().getString("folderId"); | ||||
|         } | ||||
|         // Get library page and update RecyclerView items | ||||
|         lacertaLibrary.getLibraryPage(this.folderId, 10).thenAccept(libraryItemPage -> { | ||||
|             this.libraryItemPage = libraryItemPage; | ||||
| 
 | ||||
|         if (this.folderId == null) { // Root | ||||
|             lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> { | ||||
|                 logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); | ||||
|                 listItemAdapter.setLibraryItemPage(libraryItemPage); | ||||
|                 getActivity().runOnUiThread(() -> { | ||||
|                     // ActionBarのタイトルを変更する | ||||
|                     getActivity().setTitle("ライブラリ"); | ||||
|                     // ActionBarに戻るボタンを非表示にする | ||||
| //                    getActivity().getActionBar().setDisplayHomeAsUpEnabled(false); | ||||
|                     listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1); | ||||
|                 }); | ||||
|                 this.currentTotalItemCount = libraryItemPage.getListItems().size(); | ||||
|             if (this.parentId == null) { | ||||
|                 this.parentId = libraryItemPage.getParentId(); | ||||
|             } | ||||
|             if (this.title == null) { | ||||
|                 this.title = libraryItemPage.getPageTitle(); | ||||
|                 // Toolbar init again | ||||
|                 toolbarSetup(view.findViewById(R.id.library_toolbar), this.folderId != null, this.title != null ? this.title : "ライブラリ"); | ||||
|             } | ||||
| 
 | ||||
|             logger.debug("LibraryTopFragment", "Item selected! Total item page: " + this.libraryItemPage.getListItems().size()); | ||||
|             getActivity().runOnUiThread(() -> { // TODO-rca: 実行条件を考える? | ||||
|                 listItemAdapter.notifyItemRangeRemoved(0, this.libraryItemPage.getListItems().size() - 1); | ||||
|             }); | ||||
|         } else { // Root以外 | ||||
|             lacertaLibrary.getLibraryPage(this.folderId, 10).thenAccept(libraryItemPage -> { | ||||
|                 logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); | ||||
|                 listItemAdapter.setLibraryItemPage(libraryItemPage); | ||||
|                 getActivity().runOnUiThread(() -> { | ||||
|                     // ActionBarのタイトルを変更する | ||||
|                     getActivity().setTitle(libraryItemPage.getPageTitle()); | ||||
|                     // ActionBarに戻るボタンを表示する | ||||
| //                    getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); | ||||
|                     listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1); | ||||
|                 }); | ||||
|                 this.currentTotalItemCount = libraryItemPage.getListItems().size(); | ||||
|             listItemAdapter.setLibraryItemPage(this.libraryItemPage); | ||||
|             getActivity().runOnUiThread(() -> { | ||||
|                 listItemAdapter.notifyItemRangeInserted(0, this.libraryItemPage.getListItems().size() - 1); | ||||
|             }); | ||||
|         } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { | ||||
|         inflater.inflate(R.menu.dir_menu, menu); | ||||
|         super.onCreateOptionsMenu(menu, inflater); | ||||
|     } | ||||
| 
 | ||||
|     // Selected | ||||
|     @Override | ||||
|     public boolean onOptionsItemSelected(@NonNull MenuItem item) { | ||||
|         if (item.getItemId() == R.id.menu_item_create_new_folder) { | ||||
|             AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); | ||||
|             builder.setTitle("フォルダの作成"); | ||||
|             builder.setMessage("フォルダ名を入力してください"); | ||||
|             final android.widget.EditText input = new android.widget.EditText(getContext()); | ||||
|             input.setText("フォルダ名"); | ||||
|             builder.setView(input); | ||||
|             builder.setPositiveButton("作成", (dialog, which) -> { | ||||
|                 lacertaLibrary.createFolder(null, input.getText().toString()).thenAccept(folderId -> { | ||||
|                     logger.debug("LibraryTopFragment", "folderId: " + folderId); | ||||
|                 }); | ||||
|     /** | ||||
|      * Currentにフォルダを作成する | ||||
|      */ | ||||
|     private void createFolder(String pageId) { | ||||
|         // TODO-rca: デザインをMaterial Design 3に合わせたカスタムダイアログにする | ||||
|         AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); | ||||
|         builder.setTitle("フォルダの作成"); | ||||
|         builder.setMessage("フォルダ名を入力してください"); | ||||
|         final android.widget.EditText input = new android.widget.EditText(getContext()); | ||||
|         input.setText("フォルダ名"); | ||||
|         builder.setView(input); | ||||
|         builder.setPositiveButton("作成", (dialog, which) -> { | ||||
|             lacertaLibrary.createFolder(pageId, input.getText().toString()).thenAccept(folderId -> { | ||||
|                 // Refresh | ||||
|                 updateItem(); | ||||
|                 updateItem(pageId); | ||||
|             }); | ||||
|             builder.setNegativeButton("キャンセル", (dialog, which) -> { | ||||
|                 dialog.cancel(); | ||||
|             }); | ||||
|             builder.show(); | ||||
|             return true; | ||||
|         } else { | ||||
|             return super.onOptionsItemSelected(item); | ||||
|         } | ||||
|         }); | ||||
|         builder.setNegativeButton("キャンセル", (dialog, which) -> { | ||||
|             dialog.cancel(); | ||||
|         }); | ||||
|         builder.show(); | ||||
|     } | ||||
| 
 | ||||
|     private void updateItem() { | ||||
|         lacertaLibrary.getLibraryPage(10).thenAccept(libraryItemPage -> { | ||||
|     /** | ||||
|      * RecyclerViewのアイテムを更新する | ||||
|      */ | ||||
|     private void updateItem(String pageId) { | ||||
|         lacertaLibrary.getLibraryPage(pageId, 10).thenAccept(libraryItemPage -> { | ||||
|             this.libraryItemPage = libraryItemPage; | ||||
|             logger.debug("LibraryTopFragment", "Item selected! libraryItemPage.getListItems().size(): " + libraryItemPage.getListItems().size()); | ||||
|             getActivity().runOnUiThread(() -> { | ||||
|                 listItemAdapter.notifyItemRangeRemoved(0, this.currentTotalItemCount - 1); | ||||
|                 listItemAdapter.notifyItemRangeRemoved(0, libraryItemPage.getListItems().size() - 1); | ||||
|             }); | ||||
|             listItemAdapter.setLibraryItemPage(libraryItemPage); | ||||
|             getActivity().runOnUiThread(() -> { | ||||
|                 listItemAdapter.notifyItemRangeInserted(0, libraryItemPage.getListItems().size() - 1); | ||||
|             }); | ||||
|             this.currentTotalItemCount = libraryItemPage.getListItems().size(); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * ToolbarをInitする | ||||
|      * | ||||
|      * @param toolbar Toolbar | ||||
|      * @param showBackButton 戻るボタンを表示するか | ||||
|      * @param title タイトル | ||||
|      */ | ||||
|     private void toolbarSetup(Toolbar toolbar, boolean showBackButton, String title) { | ||||
|         getActivity().runOnUiThread(() -> { | ||||
|             if (showBackButton) { | ||||
|                 toolbar.setNavigationIcon(one.nem.lacerta.shared.ui.R.drawable.arrow_back_24px); | ||||
|                 toolbar.setNavigationOnClickListener(v -> { | ||||
|                     //this.libraryItemPage = lacertaLibrary.getLibraryPage(this.libraryItemPage.getParentId(), 10).join(); | ||||
|                     // Back | ||||
|                     Navigation.findNavController(requireView()).popBackStack(); | ||||
|                 }); | ||||
|             } else { | ||||
|                 toolbar.setNavigationIcon(null); | ||||
|             } | ||||
|             toolbar.setTitle(title); | ||||
|             toolbar.inflateMenu(R.menu.dir_menu); | ||||
|             toolbar.setOnMenuItemClickListener(item -> { | ||||
|                 if (item.getItemId() == R.id.menu_item_create_new_folder) { | ||||
|                     createFolder(this.folderId); | ||||
|                     return true; | ||||
|                 } else { | ||||
|                     return false; | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,50 @@ | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent"> | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/colorSurface"> | ||||
| 
 | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/library_item_recycler_view" | ||||
|     <androidx.coordinatorlayout.widget.CoordinatorLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" /> | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.google.android.material.appbar.AppBarLayout | ||||
|             android:id="@+id/app_bar_layout" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
| 
 | ||||
|             <com.google.android.material.appbar.CollapsingToolbarLayout | ||||
|                 android:id="@+id/collapsing_toolbar" | ||||
|                 app:contentScrim="@color/colorSecondaryContainer" | ||||
|                 android:background="@color/colorSurface" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="160dp" | ||||
|                 android:fitsSystemWindows="true" | ||||
|                 android:minHeight="?attr/actionBarSize" | ||||
|                 app:collapsedTitleGravity="start|center_vertical" | ||||
|                 app:expandedTitleGravity="start|bottom" | ||||
|                 app:expandedTitleMarginBottom="16dp" | ||||
|                 app:expandedTitleMarginStart="16dp" | ||||
|                 app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4" | ||||
|                 app:layout_scrollFlags="scroll|exitUntilCollapsed"> | ||||
| 
 | ||||
|                 <androidx.appcompat.widget.Toolbar | ||||
|                     android:id="@+id/library_toolbar" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="?attr/actionBarSize" | ||||
|                     app:layout_collapseMode="pin" | ||||
|                     app:title="HOGE" /> | ||||
| 
 | ||||
|             </com.google.android.material.appbar.CollapsingToolbarLayout> | ||||
| 
 | ||||
|         </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|         <androidx.recyclerview.widget.RecyclerView | ||||
|             android:id="@+id/library_item_recycler_view" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             app:layout_behavior="@string/appbar_scrolling_view_behavior" /> | ||||
| 
 | ||||
|     </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||
| 
 | ||||
| </FrameLayout> | ||||
| @ -8,5 +8,15 @@ | ||||
|         android:id="@+id/feature_library_top_fragment" | ||||
|         android:name="one.nem.lacerta.feature.library.LibraryPageFragment" | ||||
|         android:label="fragment_library_top" | ||||
|         tools:layout="@layout/fragment_library_top" /> | ||||
|         tools:layout="@layout/fragment_library_top" > | ||||
|         <action | ||||
|             android:id="@+id/action_feature_library_top_fragment_self" | ||||
|             app:destination="@id/feature_library_top_fragment" | ||||
|             app:enterAnim="@anim/nav_default_enter_anim" | ||||
|             app:exitAnim="@anim/nav_default_exit_anim" | ||||
|             app:popEnterAnim="@anim/nav_default_pop_enter_anim" | ||||
|             app:popExitAnim="@anim/nav_default_pop_exit_anim" | ||||
|             app:popUpTo="@id/feature_library_top_fragment" | ||||
|             app:popUpToInclusive="false"/> | ||||
|     </fragment> | ||||
| </navigation> | ||||
| @ -1,11 +1,50 @@ | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent"> | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="@color/colorSurface"> | ||||
| 
 | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/setting_item_recycler_view" | ||||
|     <androidx.coordinatorlayout.widget.CoordinatorLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" /> | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <com.google.android.material.appbar.AppBarLayout | ||||
|             android:id="@+id/app_bar_layout" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
| 
 | ||||
|             <com.google.android.material.appbar.CollapsingToolbarLayout | ||||
|                 android:id="@+id/collapsing_toolbar" | ||||
|                 app:contentScrim="@color/colorSecondaryContainer" | ||||
|                 android:background="@color/colorSurface" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="160dp" | ||||
|                 android:fitsSystemWindows="true" | ||||
|                 android:minHeight="?attr/actionBarSize" | ||||
|                 app:collapsedTitleGravity="start|center_vertical" | ||||
|                 app:expandedTitleGravity="start|bottom" | ||||
|                 app:expandedTitleMarginBottom="16dp" | ||||
|                 app:expandedTitleMarginStart="16dp" | ||||
|                 app:expandedTitleTextAppearance="@style/TextAppearance.MaterialComponents.Headline4" | ||||
|                 app:layout_scrollFlags="scroll|exitUntilCollapsed"> | ||||
| 
 | ||||
|                 <androidx.appcompat.widget.Toolbar | ||||
|                     android:id="@+id/toolbar" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="?attr/actionBarSize" | ||||
|                     app:layout_collapseMode="pin" | ||||
|                     app:title="@string/setting_title" /> | ||||
| 
 | ||||
|             </com.google.android.material.appbar.CollapsingToolbarLayout> | ||||
| 
 | ||||
|         </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|         <androidx.recyclerview.widget.RecyclerView | ||||
|             android:id="@+id/setting_item_recycler_view" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             app:layout_behavior="@string/appbar_scrolling_view_behavior" /> | ||||
| 
 | ||||
|     </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||
| 
 | ||||
| </FrameLayout> | ||||
| @ -4,4 +4,10 @@ import androidx.fragment.app.Fragment; | ||||
| 
 | ||||
| public interface FragmentNavigation { | ||||
|     void navigateToFragment(Fragment fragment); | ||||
| 
 | ||||
|     void navigateToFragment(Fragment fragment, boolean addToBackStack); | ||||
| 
 | ||||
|     void navigateToFragment(Fragment fragment, boolean addToBackStack, boolean clearBackStack); | ||||
| 
 | ||||
|     void navigateToFragmentAlternate(Fragment fragment, boolean addToBackStack); | ||||
| } | ||||
|  | ||||
| @ -6,10 +6,18 @@ public class LibraryItemPage { | ||||
| 
 | ||||
|     String pageTitle; | ||||
|     String pageId; | ||||
|     String parentId; | ||||
|     ArrayList<ListItem> listItems; | ||||
| 
 | ||||
|     // Constructor | ||||
| 
 | ||||
|     public LibraryItemPage(String pageTitle, String pageId, ArrayList<ListItem> listItems, String parentId) { | ||||
|         this.pageTitle = pageTitle; | ||||
|         this.pageId = pageId; | ||||
|         this.listItems = listItems; | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
| 
 | ||||
|     public LibraryItemPage(String pageTitle, String pageId, ArrayList<ListItem> listItems) { | ||||
|         this.pageTitle = pageTitle; | ||||
|         this.pageId = pageId; | ||||
| @ -30,6 +38,10 @@ public class LibraryItemPage { | ||||
|         return pageId; | ||||
|     } | ||||
| 
 | ||||
|     public String getParentId() { | ||||
|         return parentId; | ||||
|     } | ||||
| 
 | ||||
|     public ArrayList<ListItem> getListItems() { | ||||
|         return listItems; | ||||
|     } | ||||
| @ -44,6 +56,10 @@ public class LibraryItemPage { | ||||
|         this.pageId = pageId; | ||||
|     } | ||||
| 
 | ||||
|     public void setParentId(String parentId) { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
| 
 | ||||
|     public void setListItems(ArrayList<ListItem> listItems) { | ||||
|         this.listItems = listItems; | ||||
|     } | ||||
|  | ||||
| @ -39,14 +39,19 @@ public class PublicPath { | ||||
|     } | ||||
| 
 | ||||
|     public PublicPath parse(String path) { | ||||
|         if (path.startsWith("/")) { | ||||
|         if (path == null) { | ||||
|             this.path.clear(); | ||||
|             path = path.substring(1); | ||||
|         } | ||||
|         String[] pathArray = path.split("/"); | ||||
|         for (String p : pathArray) { | ||||
|             Log.d("PublicPath", "parse: " + p); | ||||
|             resolveInternal(p); | ||||
|             this.path.add("/"); | ||||
|         } else { | ||||
|             if (path.startsWith("/")) { | ||||
|                 this.path.clear(); | ||||
|                 path = path.substring(1); | ||||
|             } | ||||
|             String[] pathArray = path.split("/"); | ||||
|             for (String p : pathArray) { | ||||
|                 Log.d("PublicPath", "parse: " + p); | ||||
|                 resolveInternal(p); | ||||
|             } | ||||
|         } | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
| @ -37,7 +37,7 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応 | ||||
|      */ | ||||
|     List<DocumentTag> tags; | ||||
| 
 | ||||
|     PublicPath path; | ||||
|     String parentId; | ||||
| 
 | ||||
|     String author; | ||||
| 
 | ||||
| @ -54,7 +54,7 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応 | ||||
|         this.tags = new ArrayList<>(); | ||||
|         this.author = ""; // TODO-rca: 作者のデフォルト値を設定できるようにする | ||||
|         this.defaultBranch = "main"; // TODO-rca: デフォルトブランチのデフォルト値を設定できるようにする | ||||
|         this.path = new PublicPath().getRoot(); | ||||
|         this.parentId = null; | ||||
|         this.updatedAt = new Date(); | ||||
|         this.createdAt = new Date(); | ||||
|     } | ||||
| @ -85,13 +85,13 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応 | ||||
|         this.defaultBranch = defaultBranch; | ||||
|     } | ||||
| 
 | ||||
|     public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, List<DocumentTag> tags, PublicPath path, String author, String defaultBranch) { | ||||
|     public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, List<DocumentTag> tags, String parentId, String author, String defaultBranch) { | ||||
|         this.id = id; | ||||
|         this.title = title; | ||||
|         this.updatedAt = updatedAt; | ||||
|         this.createdAt = createdAt; | ||||
|         this.tags = tags; | ||||
|         this.path = path; | ||||
|         this.parentId = parentId; | ||||
|         this.author = author; | ||||
|         this.defaultBranch = defaultBranch; | ||||
|     } | ||||
| @ -145,10 +145,10 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * PublicPathを取得する | ||||
|      * ドキュメントの親フォルダのID(String)を取得する | ||||
|      */ | ||||
|     public PublicPath getPath() { | ||||
|         return path; | ||||
|     public String getParentId() { | ||||
|         return parentId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -208,11 +208,11 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * PublicPathを設定する | ||||
|      * @param path PublicPath | ||||
|      * ドキュメントの親フォルダのID(String)を設定する | ||||
|      * @param parentId ドキュメントの親フォルダのID | ||||
|      */ | ||||
|     public void setPath(PublicPath path) { | ||||
|         this.path = path; | ||||
|     public void setParentId(String parentId) { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -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 = 4) | ||||
| @Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class, VcsRevEntity.class, VcsLogEntity.class, FolderEntity.class}, version = 5) | ||||
| public abstract class LacertaDatabase extends RoomDatabase { | ||||
|     public abstract TagDao tagDao(); | ||||
|     public abstract DocumentDao documentDao(); | ||||
|  | ||||
| @ -29,8 +29,11 @@ public interface DocumentDao { | ||||
|     @Query("SELECT * FROM Document WHERE id IN (:ids)") | ||||
|     List<DocumentEntity> findByIds(List<String> ids); | ||||
| 
 | ||||
|     @Query("SELECT * FROM Document WHERE public_path = :publicPath LIMIT :limit") | ||||
|     List<DocumentEntity> findByPublicPathWithLimit(String publicPath, int limit); | ||||
|     @Query("SELECT * FROM Document WHERE parent_id = :parentId") | ||||
|     List<DocumentEntity> findByParentId(String parentId); | ||||
| 
 | ||||
|     @Query("SELECT * FROM Document WHERE parent_id IS NULL") | ||||
|     List<DocumentEntity> findRootDocuments(); | ||||
| 
 | ||||
|     @Query("SELECT * FROM Document ORDER BY created_at DESC LIMIT :limit") | ||||
|     List<DocumentEntity> getRecentDocument(int limit); | ||||
|  | ||||
| @ -15,11 +15,11 @@ public interface FolderDao { | ||||
|     @Query("SELECT * FROM Folder WHERE id = :id") | ||||
|     FolderEntity findById(String id); | ||||
| 
 | ||||
|     @Query("SELECT * FROM Folder WHERE public_path = :publicPath") | ||||
|     FolderEntity findByPublicPath(String publicPath); | ||||
|     @Query("SELECT * FROM Folder WHERE parent_id = :parentId") | ||||
|     List<FolderEntity> findByParentId(String parentId); | ||||
| 
 | ||||
|     @Query("SELECT * FROM Folder WHERE public_path = :publicPath LIMIT :limit") | ||||
|     List<FolderEntity> findByPublicPathWithLimit(String publicPath, int limit); | ||||
|     @Query("SELECT * FROM Folder WHERE parent_id IS NULL") | ||||
|     List<FolderEntity> findRootFolders(); | ||||
| 
 | ||||
|     @Insert | ||||
|     void insert(FolderEntity folderEntity); | ||||
|  | ||||
| @ -40,6 +40,6 @@ public class DocumentEntity { | ||||
|     @ColumnInfo(name = "tag_ids") | ||||
|     public List<String> tagIds; // タグ | ||||
| 
 | ||||
|     @ColumnInfo(name = "public_path") | ||||
|     public String publicPath; // 公開パス | ||||
|     @ColumnInfo(name = "parent_id") | ||||
|     public String parentId; // 親フォルダID | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,7 @@ public class FolderEntity { | ||||
|     @ColumnInfo(name = "title") | ||||
|     public String name; // フォルダ名 | ||||
| 
 | ||||
|     @ColumnInfo(name = "public_path") | ||||
|     public String publicPath; // 公開パス | ||||
|     @ColumnInfo(name = "parent_id") | ||||
|     public String parentId; // 親フォルダID | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user