神马笔记 版本1.8.0——删除笔记/文件夹·代码篇
一、目标
完成神马笔记管理功能的最后一块拼图——删除文件/文件夹。
二、体验地址
神马笔记最新版本下载:【神马笔记 版本1.8.0——删除笔记/文件夹功能.apk】
三、功能设计
1. 实现删除功能
删除功能包括以下几个操作
- 删除到最近删除
- 从最近删除恢复到原来位置
- 从最近删除彻底删除笔记/文件夹
删除及恢复操作,实际上是一个移动操作。只是移动到最近删除,或者从最近删除移动到原来位置。
彻底删除操作则将数据从数据记录中移除,并且删除相关的文件。
2. 处理最近删除的可见性
另外需要处理的一个问题时当笔记/文件夹位于最近删除时,是否可见?
位置 | 最近删除是否可见? |
---|---|
搜索 | 是。搜索结果包括最近删除的笔记/文件夹。 |
我的笔记 | 否。已经移动到最近删除。 |
最近项目 | 否。 |
最近删除 | 是。只显示删除的笔记/文件夹。 |
标签 | 否。 |
个人收藏 | 否。隐藏位于最近删除的文件夹,恢复后重新显示。 |
四、实现过程
1. 删除到最近删除
public boolean trash() {
if (this.isTrash()) {
return false;
}
if (entry == null) {
return false;
}
String parentId = ROOT_TRASH;
if (this.getParent().equals(parentId)) {
return false;
}
// set deleted now
this.setDeleted(DateTime.now());
// set name
String name = RecordUtils.getName(context, entry, parentId, true);
if (this.isAlias()) {
entry.setAlias(name);
} else {
entry.setName(name);
}
// set ancestor for recover
entry.setAncestor(entry.getParent());
// set parent
entry.setParent(parentId);
return true;
}
- 在最近删除中寻找新的名字,避免重名
- 记录原来的位置,以进行恢复操作
- 设置新的位置——最近删除
2. 从最近删除恢复
public boolean recover() {
if (!this.isTrash()) {
return true;
}
if (entry == null) {
return true;
}
String parentId = entry.getAncestor().orElse("");
// check parent exist or not
if (!TextUtils.isEmpty(parentId)) {
if (!parentId.equals(ROOT_NOTE)) {
RecordEntity parent = RecordEntity.create(parentId).orElse(null);
parentId = (parent == null || parent.isTrash())? "": parent.getId();
}
}
// if parent is not exist, we move record to root
if (TextUtils.isEmpty(parentId)) {
parentId = ROOT_NOTE;
}
// set deleted null
this.setDeleted(null);
// set name
String name = RecordUtils.getName(context, entry, parentId, true);
if (this.isAlias()) {
entry.setAlias(name);
} else {
entry.setName(name);
}
// set ancestor null
entry.setAncestor(null);
// set parent
entry.setParent(parentId);
return true;
}
- 检查原来的位置是否存在,并且不是位于最近删除
- 寻找新的名字,避免恢复时重名
- 清空恢复位置,设置回原来位置
3. 彻底删除
public List<RecordEntity> delete() {
final RecordTable table = getManager().obtainTable(RecordTable.class);
if (!this.isDirectory()) {
// remove data
table.remove(this.entry);
// to entity
return Arrays.asList(this);
} else {
// filter descendant of this
final String parentId = this.getId();
List<RecordEntry> list = table.getList().stream()
.filter(e -> RecordUtils.isDescendantOf(table, e, parentId))
.collect(Collectors.toList());
// remove data
for (RecordEntry e : list) {
table.remove(e);
}
// to entity
return list.stream()
.map(e -> new RecordEntity(getContext(), e.getId(), e))
.collect(Collectors.toList());
}
}
final void executeDelete(RecordEntity entity) {
// delete from record database
final List<RecordEntity> list = entity.delete();
// delete database entry
{
FavoriteEntity favorite = FavoriteEntity.obtain();
for (RecordEntity e : list) {
String id = e.getId();
if (e.isDirectory()) {
// delete favorite
favorite.delete(id);
} else {
// delete recent
RecentEntity.delete(id);
// delete saved state
SavedStateEntity.delete(id);
// delete image
ImageEntity.deleteByDocument(id);
}
}
}
// delete file system files
for (RecordEntity e : list) {
if (e.isDirectory()) {
continue;
}
CompletableFuture.runAsync(() -> {
try {
// delete snapshot
File file = e.getSnapshot();
if (file.exists()) {
FileUtils.forceDelete(file);
}
// delete note document
file = e.getFile();
if (file.exists()) {
FileUtils.forceDelete(file);
}
} catch (IOException e1) {
}
});
}
}
删除文件夹时,需要删除包含的子文件夹和笔记。
我们通过遍历所有笔记数据,判断是否是当前文件夹的后代来决定是否删除。
最后返回需要删除的笔记/文件夹列表。
彻底删除需要删除以下相关数据。
- 笔记记录
- 个人收藏,仅文件夹
- 最近项目,仅笔记
- 笔记状态,仅笔记
- 图片记录,仅笔记
另外,还需要删除笔记相关的文件。
- 笔记截图
- 笔记文件夹
4. 处理文件夹收藏
public EntityList toList() {
return new EntityList(new FavoriteEntity(this).getList().stream()
.filter(e -> !e.isTrash())
.collect(Collectors.toList()));
}
当文件夹收藏位于最近删除时,隐藏显示,恢复后重新显示。
增加一个过滤接口,只显示非最近删除文件夹。
五、Finally
~撩乱春愁如柳絮~悠悠梦里无寻处~