Merge pull request #116 from lacerta-doc/tag/add

タグシステム実装 WIP
This commit is contained in:
ろむねこ 2024-01-25 16:56:03 +09:00 committed by GitHub
commit 94def7bf1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 510 additions and 81 deletions

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tag_name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -9,6 +9,7 @@ import one.nem.lacerta.model.ListItemType;
import one.nem.lacerta.model.LibraryItemPage; import one.nem.lacerta.model.LibraryItemPage;
import one.nem.lacerta.model.PublicPath; import one.nem.lacerta.model.PublicPath;
import one.nem.lacerta.model.document.DocumentDetail; import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.tag.DocumentTag;
public interface LacertaLibrary { public interface LacertaLibrary {
@ -29,4 +30,17 @@ public interface LacertaLibrary {
// Get Public Path // Get Public Path
CompletableFuture<PublicPath> getPublicPath(String itemId, ListItemType itemType); CompletableFuture<PublicPath> getPublicPath(String itemId, ListItemType itemType);
// Tag
CompletableFuture<ArrayList<DocumentTag>> getTagList();
CompletableFuture<Void> createTag(DocumentTag tag);
CompletableFuture<Void> updateTag(DocumentTag tag);
CompletableFuture<Void> deleteTag(String tagId);
CompletableFuture<Void> addTagToDocument(String documentId, String tagId);
CompletableFuture<Void> removeTagFromDocument(String documentId, String tagId);
} }

View File

@ -78,11 +78,9 @@ public class DocumentImpl implements Document {
documentEntity.id = meta.getId(); documentEntity.id = meta.getId();
documentEntity.title = meta.getTitle(); documentEntity.title = meta.getTitle();
documentEntity.author = meta.getAuthor(); documentEntity.author = meta.getAuthor();
documentEntity.defaultBranch = meta.getDefaultBranch();
documentEntity.updatedAt = meta.getUpdatedAt(); documentEntity.updatedAt = meta.getUpdatedAt();
documentEntity.createdAt = meta.getCreatedAt(); documentEntity.createdAt = meta.getCreatedAt();
documentEntity.parentId = meta.getParentId(); documentEntity.parentId = meta.getParentId();
documentEntity.tagIds = meta.getTagIds();
database.documentDao().insert(documentEntity); database.documentDao().insert(documentEntity);
@ -103,11 +101,9 @@ public class DocumentImpl implements Document {
meta.setId(UUID.randomUUID().toString()); meta.setId(UUID.randomUUID().toString());
meta.setTitle("New Document"); meta.setTitle("New Document");
meta.setAuthor("author"); meta.setAuthor("author");
meta.setDefaultBranch("master");
meta.setUpdatedAt(new Date()); meta.setUpdatedAt(new Date());
meta.setCreatedAt(new Date()); meta.setCreatedAt(new Date());
meta.setParentId(null); meta.setParentId(null);
meta.setTags(new ArrayList<>());
return createDocument(meta); return createDocument(meta);
} }
@ -168,11 +164,9 @@ public class DocumentImpl implements Document {
meta.setId(documentEntity.id); meta.setId(documentEntity.id);
meta.setTitle(documentEntity.title); meta.setTitle(documentEntity.title);
meta.setAuthor(documentEntity.author); meta.setAuthor(documentEntity.author);
meta.setDefaultBranch(documentEntity.defaultBranch);
meta.setUpdatedAt(documentEntity.updatedAt); meta.setUpdatedAt(documentEntity.updatedAt);
meta.setCreatedAt(documentEntity.createdAt); meta.setCreatedAt(documentEntity.createdAt);
meta.setParentId(documentEntity.parentId); meta.setParentId(documentEntity.parentId);
meta.setTags(new ArrayList<>()); // TODO-rca: タグを取得する
DocumentDetail detail = new DocumentDetail(); DocumentDetail detail = new DocumentDetail();

View File

@ -1,5 +1,7 @@
package one.nem.lacerta.data.impl; package one.nem.lacerta.data.impl;
import android.nfc.Tag;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -18,10 +20,13 @@ import one.nem.lacerta.model.ListItem;
import one.nem.lacerta.model.ListItemType; import one.nem.lacerta.model.ListItemType;
import one.nem.lacerta.model.PublicPath; import one.nem.lacerta.model.PublicPath;
import one.nem.lacerta.model.document.DocumentDetail; import one.nem.lacerta.model.document.DocumentDetail;
import one.nem.lacerta.model.document.tag.DocumentTag;
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.source.database.entity.FolderEntity;
import one.nem.lacerta.source.database.entity.TagEntity;
import one.nem.lacerta.source.database.entity.ToxiDocumentTagEntity;
import one.nem.lacerta.utils.FeatureSwitch; import one.nem.lacerta.utils.FeatureSwitch;
import one.nem.lacerta.utils.LacertaLogger; import one.nem.lacerta.utils.LacertaLogger;
@ -205,6 +210,86 @@ public class LacertaLibraryImpl implements LacertaLibrary {
}); });
} }
// Converter
private DocumentTag convertTagEntityToDocumentTag(TagEntity tagEntity) {
DocumentTag documentTag = new DocumentTag();
documentTag.setId(tagEntity.id);
documentTag.setName(tagEntity.tagName);
documentTag.setColor(tagEntity.color);
return documentTag;
}
private TagEntity convertDocumentTagToTagEntity(DocumentTag documentTag) {
TagEntity tagEntity = new TagEntity();
tagEntity.id = documentTag.getId();
tagEntity.tagName = documentTag.getName();
tagEntity.color = documentTag.getColor();
return tagEntity;
}
@Override
public CompletableFuture<ArrayList<DocumentTag>> getTagList() {
return CompletableFuture.supplyAsync(() -> {
List<TagEntity> tagEntities = database.tagDao().findAll();
logger.debug("LacertaLibraryImpl", "Database Query: Get TagEntity List (Size: " + tagEntities.size() + ")");
ArrayList<DocumentTag> documentTags = new ArrayList<>();
for (TagEntity tagEntity : tagEntities) {
documentTags.add(convertTagEntityToDocumentTag(tagEntity));
}
return documentTags;
});
}
@Override
public CompletableFuture<Void> createTag(DocumentTag tag) {
return CompletableFuture.supplyAsync(() -> {
TagEntity tagEntity = convertDocumentTagToTagEntity(tag);
database.tagDao().insert(tagEntity);
logger.debug("LacertaLibraryImpl", "Database Query: Inserted TagEntity (" + tag.getId() + ")");
return null;
});
}
@Override
public CompletableFuture<Void> updateTag(DocumentTag tag) {
return CompletableFuture.supplyAsync(() -> {
TagEntity tagEntity = convertDocumentTagToTagEntity(tag);
database.tagDao().update(tagEntity);
logger.debug("LacertaLibraryImpl", "Database Query: Updated TagEntity (" + tag.getId() + ")");
return null;
});
}
@Override
public CompletableFuture<Void> deleteTag(String tagId) {
return CompletableFuture.supplyAsync(() -> {
database.tagDao().deleteById(tagId);
logger.debug("LacertaLibraryImpl", "Database Query: Deleted TagEntity (" + tagId + ")");
return null;
});
}
@Override
public CompletableFuture<Void> addTagToDocument(String documentId, String tagId) {
return CompletableFuture.supplyAsync(() -> {
ToxiDocumentTagEntity toxiDocumentTagEntity = new ToxiDocumentTagEntity();
toxiDocumentTagEntity.documentId = documentId;
toxiDocumentTagEntity.tagId = tagId;
database.toxiDocumentTagDao().insert(toxiDocumentTagEntity);
logger.debug("LacertaLibraryImpl", "Database Query: Inserted ToxiDocumentTagEntity");
return null;
});
}
@Override
public CompletableFuture<Void> removeTagFromDocument(String documentId, String tagId) {
return CompletableFuture.supplyAsync(() -> {
database.toxiDocumentTagDao().deleteByDocumentIdAndTagId(documentId, tagId);
logger.debug("LacertaLibraryImpl", "Database Query: Deleted ToxiDocumentTagEntity");
return null;
});
}
/** /**
* 再帰的にパスを解決する * 再帰的にパスを解決する
* *

View File

@ -1,5 +1,6 @@
plugins { plugins {
alias(libs.plugins.com.android.library) alias(libs.plugins.com.android.library)
id 'com.google.dagger.hilt.android'
} }
android { android {
@ -45,6 +46,10 @@ dependencies {
// shared // shared
implementation project(':shared:ui') implementation project(':shared:ui')
implementation project(':data')
implementation project(':model')
// https://mvnrepository.com/artifact/androidx.preference/preference // https://mvnrepository.com/artifact/androidx.preference/preference
implementation 'androidx.preference:preference:1.2.1' implementation 'androidx.preference:preference:1.2.1'

View File

@ -0,0 +1,112 @@
package one.nem.lacerta.setting;
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;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.data.LacertaLibrary;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SettingTagManageFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class SettingTagManageFragment extends Fragment {
@Inject
LacertaLibrary lacertaLibrary;
public SettingTagManageFragment() {
// Required empty public constructor
}
public static SettingTagManageFragment newInstance() {
SettingTagManageFragment fragment = new SettingTagManageFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_setting_tag_manage, container, false);
// Toolbar
Toolbar toolbar = view.findViewById(R.id.tag_manage_toolbar);
toolbarSetup(toolbar, true, "タグ管理");
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = view.findViewById(R.id.tag_item_recycler_view);
TagListItemAdapter adapter = new TagListItemAdapter((tagId, tagName, tagColor) -> {
Toast.makeText(getContext(), "Tag Clicked", Toast.LENGTH_SHORT).show();
});
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
lacertaLibrary.getTagList().thenAccept(documentTags -> {
adapter.setDocumentTags(documentTags);
adapter.notifyDataSetChanged();
});
}
/**
* ToolbarをInitする
*
* @param toolbar Toolbar
* @param showBackButton 戻るボタンを表示するか
* @param title タイトル
*/
private void toolbarSetup(Toolbar toolbar, boolean showBackButton, String title) {
getActivity().runOnUiThread(() -> {
if (showBackButton) {
toolbar.setNavigationIcon(one.nem.lacerta.shared.ui.R.drawable.arrow_back_24px);
toolbar.setNavigationOnClickListener(v -> {
//this.libraryItemPage = lacertaLibrary.getLibraryPage(this.libraryItemPage.getParentId(), 10).join();
// Back
Navigation.findNavController(requireView()).popBackStack();
});
} else {
toolbar.setNavigationIcon(null);
}
toolbar.setTitle(title);
toolbar.getMenu().clear();
toolbar.inflateMenu(R.menu.setting_tag_manage_menu);
toolbar.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.setting_tag_manage_menu_add) {
Toast.makeText(getContext(), "Add Clicked", Toast.LENGTH_SHORT).show();
return true;
} else {
return false;
}
});
});
}
}

View File

@ -74,6 +74,15 @@ public class SettingTopFragment extends Fragment {
) )
); );
settingListItems.add(
new SettingListItem(
"タグ管理", // TODO-rca: リソースに移動
"タグの追加・編集・削除", // TODO-rca: リソースに移動
ContextCompat.getDrawable(getContext(), one.nem.lacerta.shared.ui.R.drawable.sell_24px),
R.id.action_settingTopFragment_to_settingTagManageFragment
)
);
settingListItems.add( settingListItems.add(
new SettingListItem( new SettingListItem(
getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_about_title), getResources().getString(one.nem.lacerta.shared.ui.R.string.setting_top_about_title),

View File

@ -0,0 +1,69 @@
package one.nem.lacerta.setting;
import android.graphics.Color;
import android.media.Image;
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.document.tag.DocumentTag;
public class TagListItemAdapter extends RecyclerView.Adapter<TagListItemAdapter.TagListItemViewHolder> {
ArrayList<DocumentTag> documentTags;
TagListItemSelectListener listener;
public TagListItemAdapter(TagListItemSelectListener listener) {
this.listener = listener;
}
public void setDocumentTags(ArrayList<DocumentTag> documentTags) {
this.documentTags = documentTags;
}
@NonNull
@Override
public TagListItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(one.nem.lacerta.shared.ui.R.layout.tag_list_full_item, parent, false);
return new TagListItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull TagListItemViewHolder holder, int position) {
DocumentTag documentTag = documentTags.get(position);
holder.tag_name.setText(documentTag.getName());
try {
holder.tag_icon.setColorFilter(Color.parseColor(documentTag.getColor()));
} catch (Exception e) {
holder.tag_name.setText("Sorry, Parse Error occurred");
}
}
@Override
public int getItemCount() {
return documentTags == null ? 0 : documentTags.size();
}
public static class TagListItemViewHolder extends RecyclerView.ViewHolder {
ImageView tag_icon;
TextView tag_name;
public TagListItemViewHolder(@NonNull View itemView) {
super(itemView);
tag_icon = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.tag_icon);
tag_name = itemView.findViewById(one.nem.lacerta.shared.ui.R.id.tag_name);
}
}
}

View File

@ -0,0 +1,6 @@
package one.nem.lacerta.setting;
public interface TagListItemSelectListener {
void onTagListItemSelect(String tagId, String tagName, String tagColor);
}

View File

@ -0,0 +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:background="@color/colorSurface">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="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/tag_manage_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title="@string/setting_top_display_title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tag_item_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/setting_tag_manage_menu_add"
android:icon="@drawable/outline_developer_mode_24"
android:title="@string/placeholder"
app:showAsAction="ifRoom"/>
</menu>

View File

@ -37,6 +37,9 @@
app:exitAnim="@anim/slide_to_left" app:exitAnim="@anim/slide_to_left"
app:popEnterAnim="@anim/slide_from_left" app:popEnterAnim="@anim/slide_from_left"
app:popExitAnim="@anim/slide_to_right" /> app:popExitAnim="@anim/slide_to_right" />
<action
android:id="@+id/action_settingTopFragment_to_settingTagManageFragment"
app:destination="@id/settingTagManageFragment" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/settingAboutPageFragment" android:id="@+id/settingAboutPageFragment"
@ -58,4 +61,8 @@
android:name="one.nem.lacerta.setting.SettingScanPageFragment" android:name="one.nem.lacerta.setting.SettingScanPageFragment"
android:label="fragment_setting_scan_page" android:label="fragment_setting_scan_page"
tools:layout="@layout/fragment_setting_scan_page" /> tools:layout="@layout/fragment_setting_scan_page" />
<fragment
android:id="@+id/settingTagManageFragment"
android:name="one.nem.lacerta.setting.SettingTagManageFragment"
android:label="SettingTagManageFragment" />
</navigation> </navigation>

View File

@ -32,17 +32,10 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
*/ */
Date createdAt; Date createdAt;
/**
* ドキュメントのタグ(DocumentTagインスタンスのリスト)
*/
List<DocumentTag> tags;
String parentId; String parentId;
String author; String author;
String defaultBranch;
// Constructor // Constructor
public DocumentMeta() { public DocumentMeta() {
@ -51,49 +44,33 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
public DocumentMeta(String title) { public DocumentMeta(String title) {
this.id = UUID.randomUUID().toString(); this.id = UUID.randomUUID().toString();
this.title = title; this.title = title;
this.tags = new ArrayList<>(); this.author = ""; // TODO-rca: 作者のデフォルト値を指定できるように
this.author = ""; // TODO-rca: 作者のデフォルト値を設定できるようにする
this.defaultBranch = "main"; // TODO-rca: デフォルトブランチのデフォルト値を設定できるようにする
this.parentId = null; this.parentId = null;
this.updatedAt = new Date(); this.updatedAt = new Date();
this.createdAt = new Date(); this.createdAt = new Date();
} }
public DocumentMeta(String title, List<DocumentTag> tags, String author, String defaultBranch) { public DocumentMeta(String title, String author) {
this.id = UUID.randomUUID().toString(); this.id = UUID.randomUUID().toString();
this.title = title; this.title = title;
this.tags = tags;
this.author = author; this.author = author;
this.defaultBranch = defaultBranch;
} }
public DocumentMeta(String id, String title, List<DocumentTag> tags, String author, String defaultBranch) { public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, String author) {
this.id = id;
this.title = title;
this.tags = tags;
this.author = author;
this.defaultBranch = defaultBranch;
}
public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, List<DocumentTag> tags, String author, String defaultBranch) {
this.id = id; this.id = id;
this.title = title; this.title = title;
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
this.createdAt = createdAt; this.createdAt = createdAt;
this.tags = tags;
this.author = author; this.author = author;
this.defaultBranch = defaultBranch;
} }
public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, List<DocumentTag> tags, String parentId, String author, String defaultBranch) { public DocumentMeta(String id, String title, Date updatedAt, Date createdAt, String parentId, String author) {
this.id = id; this.id = id;
this.title = title; this.title = title;
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
this.createdAt = createdAt; this.createdAt = createdAt;
this.tags = tags;
this.parentId = parentId; this.parentId = parentId;
this.author = author; this.author = author;
this.defaultBranch = defaultBranch;
} }
// Getter // Getter
@ -126,24 +103,6 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
return createdAt; return createdAt;
} }
/**
* ドキュメントのタグ(DocumentTagインスタンスのリスト)を取得する
*/
public List<DocumentTag> getTags() {
return tags;
}
/**
* ドキュメントのタグ(DocumentTagインスタンスのリスト)のID(String)を取得する
*/
public List<String> getTagIds() {
List<String> tagIds = new ArrayList<>();
for (DocumentTag tag : tags) {
tagIds.add(tag.getId());
}
return tagIds;
}
/** /**
* ドキュメントの親フォルダのID(String)を取得する * ドキュメントの親フォルダのID(String)を取得する
*/ */
@ -158,13 +117,6 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
return author; return author;
} }
/**
* ドキュメントのデフォルトブランチ(String)を取得する
*/
public String getDefaultBranch() {
return defaultBranch;
}
// Setter // Setter
/** /**
@ -199,14 +151,6 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
this.createdAt = createdAt; this.createdAt = createdAt;
} }
/**
* ドキュメントのタグ(DocumentTagインスタンスのリスト)を設定する
* @param tags ドキュメントのタグ(DocumentTagインスタンスのリスト)
*/
public void setTags(List<DocumentTag> tags) {
this.tags = tags;
}
/** /**
* ドキュメントの親フォルダのID(String)を設定する * ドキュメントの親フォルダのID(String)を設定する
* @param parentId ドキュメントの親フォルダのID * @param parentId ドキュメントの親フォルダのID
@ -223,14 +167,6 @@ public class DocumentMeta { // TODO-rca: JavaDoc対応
this.author = author; this.author = author;
} }
/**
* ドキュメントのデフォルトブランチ(String)を設定する
* @param defaultBranch ドキュメントのデフォルトブランチ
*/
public void setDefaultBranch(String defaultBranch) {
this.defaultBranch = defaultBranch;
}
/** /**
* updatedAtを現在時刻に設定する * updatedAtを現在時刻に設定する
*/ */

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@color/colorOnSurface"
android:pathData="M556.15,842.15Q538.89,859.38 513.37,859.38Q487.85,859.38 470.62,842.15L118.62,490.15Q109.92,481.46 104.96,470.14Q100,458.83 100,446L100,160Q100,135.46 117.73,117.73Q135.46,100 160,100L446,100Q458.38,100 469.73,104.84Q481.07,109.67 489.38,117.85L841.38,470.46Q859,488.08 859.19,513.5Q859.38,538.92 842.15,556.15L556.15,842.15ZM513.21,800L799.39,514L446.17,160L160,160L160,446L513.21,800ZM259.95,310Q280.77,310 295.38,295.43Q310,280.86 310,260.04Q310,239.23 295.43,224.62Q280.86,210 260.05,210Q239.23,210 224.62,224.57Q210,239.14 210,259.96Q210,280.77 224.57,295.38Q239.14,310 259.95,310ZM160,160L160,160L160,160L160,160L160,160L160,160Z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@color/colorOnSurface"
android:pathData="M556.15,842.15Q538.89,859.38 513.37,859.38Q487.85,859.38 470.62,842.15L118.62,490.15Q109.92,481.46 104.96,470.14Q100,458.83 100,446L100,160Q100,135.46 117.73,117.73Q135.46,100 160,100L446,100Q458.38,100 469.73,104.84Q481.07,109.67 489.38,117.85L841.38,470.46Q859,488.08 859.19,513.5Q859.38,538.92 842.15,556.15L556.15,842.15ZM259.95,310Q280.77,310 295.38,295.43Q310,280.86 310,260.04Q310,239.23 295.43,224.62Q280.86,210 260.05,210Q239.23,210 224.62,224.57Q210,239.14 210,259.96Q210,280.77 224.57,295.38Q239.14,310 259.95,310Z"/>
</vector>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:paddingVertical="16dp">
<ImageView
android:id="@+id/tag_icon"
android:layout_width="32dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/item_text_container"
app:srcCompat="@drawable/sell_fill24px"
android:contentDescription="icon" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/item_text_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tag_icon"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tag_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_marginEnd="8dp"
android:text="Placeholder Title"
android:textColor="@color/colorOnSurface"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -5,10 +5,12 @@ import androidx.room.RoomDatabase;
// Entities // Entities
import one.nem.lacerta.source.database.dao.FolderDao; import one.nem.lacerta.source.database.dao.FolderDao;
import one.nem.lacerta.source.database.dao.ToxiDocumentTagDao;
import one.nem.lacerta.source.database.entity.FolderEntity; import one.nem.lacerta.source.database.entity.FolderEntity;
import one.nem.lacerta.source.database.entity.TagEntity; import one.nem.lacerta.source.database.entity.TagEntity;
import one.nem.lacerta.source.database.entity.DocumentEntity; import one.nem.lacerta.source.database.entity.DocumentEntity;
import one.nem.lacerta.source.database.entity.LibraryEntity; import one.nem.lacerta.source.database.entity.LibraryEntity;
import one.nem.lacerta.source.database.entity.ToxiDocumentTagEntity;
import one.nem.lacerta.source.database.entity.VcsRevEntity; import one.nem.lacerta.source.database.entity.VcsRevEntity;
import one.nem.lacerta.source.database.entity.VcsLogEntity; import one.nem.lacerta.source.database.entity.VcsLogEntity;
@ -19,10 +21,11 @@ import one.nem.lacerta.source.database.dao.LibraryDao;
import one.nem.lacerta.source.database.dao.VcsRevDao; import one.nem.lacerta.source.database.dao.VcsRevDao;
import one.nem.lacerta.source.database.dao.VcsLogDao; import one.nem.lacerta.source.database.dao.VcsLogDao;
@Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class, VcsRevEntity.class, VcsLogEntity.class, FolderEntity.class}, version = 4) @Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class, VcsRevEntity.class, VcsLogEntity.class, FolderEntity.class, ToxiDocumentTagEntity.class}, version = 6)
public abstract class LacertaDatabase extends RoomDatabase { public abstract class LacertaDatabase extends RoomDatabase {
public abstract TagDao tagDao(); public abstract TagDao tagDao();
public abstract DocumentDao documentDao(); public abstract DocumentDao documentDao();
public abstract ToxiDocumentTagDao toxiDocumentTagDao();
public abstract LibraryDao libraryDao(); public abstract LibraryDao libraryDao();
public abstract VcsRevDao vcsRevDao(); public abstract VcsRevDao vcsRevDao();
public abstract VcsLogDao vcsLogDao(); public abstract VcsLogDao vcsLogDao();

View File

@ -0,0 +1,37 @@
package one.nem.lacerta.source.database.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
import one.nem.lacerta.source.database.entity.ToxiDocumentTagEntity;
@Dao
public interface ToxiDocumentTagDao {
@Query("SELECT * FROM toxi_document_tag WHERE document_id = :documentId")
List<ToxiDocumentTagEntity> findByDocumentId(String documentId);
@Query("SELECT * FROM toxi_document_tag WHERE tag_id = :tagId")
List<ToxiDocumentTagEntity> findByTagId(String tagId);
@Insert
void insert(ToxiDocumentTagEntity toxiDocumentTag);
@Insert
void insertAll(ToxiDocumentTagEntity... toxiDocumentTags);
@Insert
void insertAll(List<ToxiDocumentTagEntity> toxiDocumentTags);
@Query("DELETE FROM toxi_document_tag WHERE document_id = :documentId")
void deleteByDocumentId(String documentId);
@Query("DELETE FROM toxi_document_tag WHERE tag_id = :tagId")
void deleteByTagId(String tagId);
@Query("DELETE FROM toxi_document_tag WHERE document_id = :documentId AND tag_id = :tagId")
void deleteByDocumentIdAndTagId(String documentId, String tagId);
}

View File

@ -34,12 +34,6 @@ public class DocumentEntity {
@ColumnInfo(name = "author") @ColumnInfo(name = "author")
public String author; // 作成者 public String author; // 作成者
@ColumnInfo(name = "default_branch")
public String defaultBranch; // デフォルトブランチ
@ColumnInfo(name = "tag_ids")
public List<String> tagIds; // タグ
@ColumnInfo(name = "parent_id") @ColumnInfo(name = "parent_id")
public String parentId; // 親フォルダID public String parentId; // 親フォルダID
} }

View File

@ -0,0 +1,18 @@
package one.nem.lacerta.source.database.entity;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(primaryKeys = {"document_id", "tag_id"}, tableName = "toxi_document_tag")
public class ToxiDocumentTagEntity {
@NonNull
@ColumnInfo(name = "document_id")
public String documentId; // ドキュメントID
@NonNull
@ColumnInfo(name = "tag_id")
public String tagId; // タグID
}