mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #1073 from AppFlowy-IO/feat/merge_release_0052
Feat/merge release 0052
This commit is contained in:
commit
92a751b32a
@ -22,7 +22,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||
LIB_NAME = "dart_ffi"
|
||||
CURRENT_APP_VERSION = "0.0.5.1"
|
||||
CURRENT_APP_VERSION = "0.0.5.2"
|
||||
FEATURES = "flutter"
|
||||
PRODUCT_NAME = "AppFlowy"
|
||||
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
|
||||
|
@ -187,35 +187,31 @@ class _BoardContentState extends State<BoardContent> {
|
||||
}
|
||||
|
||||
Widget _buildFooter(BuildContext context, AppFlowyGroupData columnData) {
|
||||
final boardCustomData = columnData.customData as BoardCustomData;
|
||||
final group = boardCustomData.group;
|
||||
// final boardCustomData = columnData.customData as BoardCustomData;
|
||||
// final group = boardCustomData.group;
|
||||
|
||||
if (group.isDefault) {
|
||||
return const SizedBox();
|
||||
} else {
|
||||
return AppFlowyGroupFooter(
|
||||
icon: SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: svgWidget(
|
||||
"home/add",
|
||||
color: context.read<AppTheme>().iconColor,
|
||||
),
|
||||
return AppFlowyGroupFooter(
|
||||
icon: SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: svgWidget(
|
||||
"home/add",
|
||||
color: context.read<AppTheme>().iconColor,
|
||||
),
|
||||
title: FlowyText.medium(
|
||||
LocaleKeys.board_column_create_new_card.tr(),
|
||||
fontSize: 14,
|
||||
color: context.read<AppTheme>().textColor,
|
||||
),
|
||||
height: 50,
|
||||
margin: config.footerPadding,
|
||||
onAddButtonClick: () {
|
||||
context.read<BoardBloc>().add(
|
||||
BoardEvent.createBottomRow(columnData.id),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
title: FlowyText.medium(
|
||||
LocaleKeys.board_column_create_new_card.tr(),
|
||||
fontSize: 14,
|
||||
color: context.read<AppTheme>().textColor,
|
||||
),
|
||||
height: 50,
|
||||
margin: config.footerPadding,
|
||||
onAddButtonClick: () {
|
||||
context.read<BoardBloc>().add(
|
||||
BoardEvent.createBottomRow(columnData.id),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCard(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:app_flowy/plugins/grid/application/row/row_action_sheet_bloc.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
@ -151,14 +150,9 @@ extension _RowActionExtension on _RowAction {
|
||||
.add(const RowActionSheetEvent.duplicateRow());
|
||||
break;
|
||||
case _RowAction.delete:
|
||||
NavigatorAlertDialog(
|
||||
title: LocaleKeys.grid_field_deleteFieldPromptMessage.tr(),
|
||||
confirm: () {
|
||||
context
|
||||
.read<RowActionSheetBloc>()
|
||||
.add(const RowActionSheetEvent.deleteRow());
|
||||
},
|
||||
).show(context);
|
||||
context
|
||||
.read<RowActionSheetBloc>()
|
||||
.add(const RowActionSheetEvent.deleteRow());
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ impl FolderMigration {
|
||||
|
||||
let folder = FolderPad::new(workspaces, trash)?;
|
||||
KV::set_bool(&key, true);
|
||||
tracing::trace!("Run folder v1 migration");
|
||||
tracing::info!("Run folder v1 migration");
|
||||
Ok(Some(folder))
|
||||
}
|
||||
|
||||
@ -89,11 +89,10 @@ impl FolderMigration {
|
||||
}
|
||||
let _ = self.migration_folder_rev_struct(folder_id).await?;
|
||||
KV::set_bool(&key, true);
|
||||
tracing::trace!("Run folder v2 migration");
|
||||
// tracing::info!("Run folder v2 migration");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn run_v3_migration(&self, folder_id: &FolderId) -> FlowyResult<()> {
|
||||
let key = migration_flag_key(&self.user_id, V3_MIGRATION);
|
||||
if KV::get_bool(&key) {
|
||||
@ -101,7 +100,7 @@ impl FolderMigration {
|
||||
}
|
||||
let _ = self.migration_folder_rev_struct(folder_id).await?;
|
||||
KV::set_bool(&key, true);
|
||||
tracing::trace!("Run folder v3 migration");
|
||||
tracing::info!("Run folder v3 migration");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -101,8 +101,7 @@ impl FolderPersistence {
|
||||
}
|
||||
|
||||
let _ = migrations.run_v2_migration(folder_id).await?;
|
||||
|
||||
// let _ = migrations.run_v3_migration(folder_id).await?;
|
||||
let _ = migrations.run_v3_migration(folder_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,7 @@ impl GridBlockManager {
|
||||
Ok(self.get_block_editor(&block_id).await?)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, start_row_id), err)]
|
||||
pub(crate) async fn create_row(&self, row_rev: RowRevision, start_row_id: Option<String>) -> FlowyResult<i32> {
|
||||
let block_id = row_rev.block_id.clone();
|
||||
let _ = self.persistence.insert(&row_rev.block_id, &row_rev.id)?;
|
||||
|
@ -29,6 +29,7 @@ impl TypeOptionBuilder for RichTextTypeOptionBuilder {
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
||||
pub struct RichTextTypeOptionPB {
|
||||
#[pb(index = 1)]
|
||||
#[serde(default)]
|
||||
data: String, //It's not used yet
|
||||
}
|
||||
impl_type_option!(RichTextTypeOptionPB, FieldType::RichText);
|
||||
|
@ -420,6 +420,7 @@ impl GridRevisionEditor {
|
||||
|
||||
pub async fn delete_row(&self, row_id: &str) -> FlowyResult<()> {
|
||||
let row_rev = self.block_manager.delete_row(row_id).await?;
|
||||
tracing::trace!("Did delete row:{:?}", row_rev);
|
||||
if let Some(row_rev) = row_rev {
|
||||
self.view_manager.did_delete_row(row_rev).await;
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ impl GridViewRevisionEditor {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all)]
|
||||
pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) {
|
||||
// Send the group notification if the current view has groups;
|
||||
let changesets = self
|
||||
@ -116,6 +117,7 @@ impl GridViewRevisionEditor {
|
||||
.await;
|
||||
|
||||
if let Some(changesets) = changesets {
|
||||
tracing::trace!("{:?}", changesets);
|
||||
for changeset in changesets {
|
||||
self.notify_did_update_group(changeset).await;
|
||||
}
|
||||
|
@ -92,17 +92,33 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the groups without the default group
|
||||
pub(crate) fn concrete_groups(&self) -> Vec<&Group> {
|
||||
self.groups_map.values().collect()
|
||||
}
|
||||
|
||||
pub(crate) fn default_group(&self) -> &Group {
|
||||
pub(crate) fn get_default_group(&self) -> &Group {
|
||||
&self.default_group
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_default_group(&mut self) -> &mut Group {
|
||||
&mut self.default_group
|
||||
}
|
||||
|
||||
/// Returns the groups without the default group
|
||||
pub(crate) fn groups(&self) -> Vec<&Group> {
|
||||
self.groups_map.values().collect()
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut Group> {
|
||||
self.groups_map.get_mut(group_id)
|
||||
}
|
||||
|
||||
// Returns the index and group specified by the group_id
|
||||
pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &Group)> {
|
||||
match (self.groups_map.get_index_of(group_id), self.groups_map.get(group_id)) {
|
||||
(Some(index), Some(group)) => Some((index, group)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate mut the groups. The default group will be the last one that get mutated.
|
||||
pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) {
|
||||
pub(crate) fn iter_mut_all_groups(&mut self, mut each: impl FnMut(&mut Group)) {
|
||||
self.groups_map.iter_mut().for_each(|(_, group)| {
|
||||
each(group);
|
||||
});
|
||||
@ -253,22 +269,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_default_group(&mut self) -> &mut Group {
|
||||
&mut self.default_group
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut Group> {
|
||||
self.groups_map.get_mut(group_id)
|
||||
}
|
||||
|
||||
// Returns the index and group specified by the group_id
|
||||
pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &Group)> {
|
||||
match (self.groups_map.get_index_of(group_id), self.groups_map.get(group_id)) {
|
||||
(Some(index), Some(group)) => Some((index, group)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_configuration(&self) -> FlowyResult<()> {
|
||||
let configuration = (&*self.configuration).clone();
|
||||
let writer = self.writer.clone();
|
||||
|
@ -183,11 +183,11 @@ where
|
||||
|
||||
fn groups(&self) -> Vec<Group> {
|
||||
if self.use_default_group() {
|
||||
let mut groups: Vec<Group> = self.group_ctx.concrete_groups().into_iter().cloned().collect();
|
||||
groups.push(self.group_ctx.default_group().clone());
|
||||
let mut groups: Vec<Group> = self.group_ctx.groups().into_iter().cloned().collect();
|
||||
groups.push(self.group_ctx.get_default_group().clone());
|
||||
groups
|
||||
} else {
|
||||
self.group_ctx.concrete_groups().into_iter().cloned().collect()
|
||||
self.group_ctx.groups().into_iter().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ where
|
||||
let mut grouped_rows: Vec<GroupedRow> = vec![];
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev);
|
||||
let cell_data = cell_bytes.parser::<P>()?;
|
||||
for group in self.group_ctx.concrete_groups() {
|
||||
for group in self.group_ctx.groups() {
|
||||
if self.can_group(&group.filter_content, &cell_data) {
|
||||
grouped_rows.push(GroupedRow {
|
||||
row: row_rev.into(),
|
||||
@ -264,12 +264,17 @@ where
|
||||
row_rev: &RowRevision,
|
||||
field_rev: &FieldRevision,
|
||||
) -> FlowyResult<Vec<GroupChangesetPB>> {
|
||||
// if the cell_rev is none, then the row must be crated from the default group.
|
||||
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev);
|
||||
let cell_data = cell_bytes.parser::<P>()?;
|
||||
Ok(self.remove_row_if_match(row_rev, &cell_data))
|
||||
} else {
|
||||
Ok(vec![])
|
||||
let group = self.group_ctx.get_default_group();
|
||||
Ok(vec![GroupChangesetPB::delete(
|
||||
group.id.clone(),
|
||||
vec![row_rev.id.clone()],
|
||||
)])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl GroupAction for CheckboxGroupController {
|
||||
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||
let is_contained = group.contains_row(&row_rev.id);
|
||||
if group.id == CHECK && cell_data.is_check() {
|
||||
@ -63,7 +63,7 @@ impl GroupAction for CheckboxGroupController {
|
||||
|
||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||
if group.contains_row(&row_rev.id) {
|
||||
changeset.deleted_rows.push(row_rev.id.clone());
|
||||
@ -79,7 +79,7 @@ impl GroupAction for CheckboxGroupController {
|
||||
|
||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||
let mut group_changeset = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = move_group_row(group, &mut context) {
|
||||
group_changeset.push(changeset);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ impl GroupAction for MultiSelectGroupController {
|
||||
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) {
|
||||
changesets.push(changeset);
|
||||
}
|
||||
@ -38,7 +38,7 @@ impl GroupAction for MultiSelectGroupController {
|
||||
|
||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) {
|
||||
changesets.push(changeset);
|
||||
}
|
||||
@ -48,7 +48,7 @@ impl GroupAction for MultiSelectGroupController {
|
||||
|
||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||
let mut group_changeset = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = move_group_row(group, &mut context) {
|
||||
group_changeset.push(changeset);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ impl GroupAction for SingleSelectGroupController {
|
||||
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) {
|
||||
changesets.push(changeset);
|
||||
}
|
||||
@ -38,7 +38,7 @@ impl GroupAction for SingleSelectGroupController {
|
||||
|
||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) {
|
||||
changesets.push(changeset);
|
||||
}
|
||||
@ -48,7 +48,7 @@ impl GroupAction for SingleSelectGroupController {
|
||||
|
||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||
let mut group_changeset = vec![];
|
||||
self.group_ctx.iter_mut_groups(|group| {
|
||||
self.group_ctx.iter_mut_all_groups(|group| {
|
||||
if let Some(changeset) = move_group_row(group, &mut context) {
|
||||
group_changeset.push(changeset);
|
||||
}
|
||||
|
@ -17,10 +17,13 @@ pub struct AppRevision {
|
||||
|
||||
pub belongings: Vec<ViewRevision>,
|
||||
|
||||
#[serde(default)]
|
||||
pub version: i64,
|
||||
|
||||
#[serde(default)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[serde(default)]
|
||||
pub create_time: i64,
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,76 @@
|
||||
use crate::revision::{TrashRevision, WorkspaceRevision};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::de::{MapAccess, Visitor};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Default, Serialize, Clone, Eq, PartialEq)]
|
||||
pub struct FolderRevision {
|
||||
pub workspaces: Vec<Arc<WorkspaceRevision>>,
|
||||
pub trash: Vec<Arc<TrashRevision>>,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for FolderRevision {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct FolderVisitor<'a>(&'a mut Option<FolderRevision>);
|
||||
impl<'de, 'a> Visitor<'de> for FolderVisitor<'a> {
|
||||
type Value = ();
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("Expect struct FolderRevision")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
let f = |map: &mut A,
|
||||
workspaces: &mut Option<Vec<WorkspaceRevision>>,
|
||||
trash: &mut Option<Vec<TrashRevision>>| match map.next_key::<String>()
|
||||
{
|
||||
Ok(Some(key)) => {
|
||||
if key == "workspaces" && workspaces.is_none() {
|
||||
*workspaces = Some(map.next_value::<Vec<WorkspaceRevision>>().ok()?);
|
||||
}
|
||||
if key == "trash" && trash.is_none() {
|
||||
*trash = Some(map.next_value::<Vec<TrashRevision>>().ok()?);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
Ok(None) => None,
|
||||
Err(_e) => None,
|
||||
};
|
||||
|
||||
let mut workspaces: Option<Vec<WorkspaceRevision>> = None;
|
||||
let mut trash: Option<Vec<TrashRevision>> = None;
|
||||
while f(&mut map, &mut workspaces, &mut trash).is_some() {
|
||||
if workspaces.is_some() && trash.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*self.0 = Some(FolderRevision {
|
||||
workspaces: workspaces.unwrap_or_default().into_iter().map(Arc::new).collect(),
|
||||
trash: trash.unwrap_or_default().into_iter().map(Arc::new).collect(),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
let mut folder_rev: Option<FolderRevision> = None;
|
||||
const FIELDS: &[&str] = &["workspaces", "trash"];
|
||||
let _ = serde::Deserializer::deserialize_struct(
|
||||
deserializer,
|
||||
"FolderRevision",
|
||||
FIELDS,
|
||||
FolderVisitor(&mut folder_rev),
|
||||
);
|
||||
|
||||
match folder_rev {
|
||||
None => Err(de::Error::missing_field("workspaces or trash")),
|
||||
Some(folder_rev) => Ok(folder_rev),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,10 @@ pub struct TrashRevision {
|
||||
|
||||
pub name: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[serde(default)]
|
||||
pub create_time: i64,
|
||||
|
||||
pub ty: TrashTypeRevision,
|
||||
|
@ -9,7 +9,6 @@ pub fn gen_view_id() -> String {
|
||||
pub struct ViewRevision {
|
||||
pub id: String,
|
||||
|
||||
// Maybe app_id or vi
|
||||
#[serde(rename = "belong_to_id")]
|
||||
pub app_id: String,
|
||||
|
||||
@ -24,8 +23,10 @@ pub struct ViewRevision {
|
||||
|
||||
pub belongings: Vec<ViewRevision>,
|
||||
|
||||
#[serde(default)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[serde(default)]
|
||||
pub create_time: i64,
|
||||
|
||||
#[serde(default)]
|
||||
|
@ -14,7 +14,9 @@ pub struct WorkspaceRevision {
|
||||
|
||||
pub apps: Vec<AppRevision>,
|
||||
|
||||
#[serde(default)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[serde(default)]
|
||||
pub create_time: i64,
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use flowy_folder_data_model::revision::{AppRevision, FolderRevision, TrashRevisi
|
||||
use lib_infra::util::move_vec_element;
|
||||
use lib_ot::core::*;
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
@ -44,7 +45,9 @@ impl FolderPad {
|
||||
pub fn from_delta(delta: FolderDelta) -> CollaborateResult<Self> {
|
||||
// TODO: Reconvert from history if delta.to_str() failed.
|
||||
let content = delta.content()?;
|
||||
let folder_rev: FolderRevision = serde_json::from_str(&content).map_err(|e| {
|
||||
let mut deserializer = serde_json::Deserializer::from_reader(content.as_bytes());
|
||||
|
||||
let folder_rev = FolderRevision::deserialize(&mut deserializer).map_err(|e| {
|
||||
tracing::error!("Deserialize folder from {} failed", content);
|
||||
return CollaborateError::internal().context(format!("Deserialize delta to folder failed: {}", e));
|
||||
})?;
|
||||
@ -455,6 +458,7 @@ mod tests {
|
||||
#![allow(clippy::all)]
|
||||
use crate::{client_folder::folder_pad::FolderPad, entities::folder::FolderDelta};
|
||||
use chrono::Utc;
|
||||
use serde::Deserialize;
|
||||
|
||||
use flowy_folder_data_model::revision::{
|
||||
AppRevision, FolderRevision, TrashRevision, ViewRevision, WorkspaceRevision,
|
||||
@ -478,6 +482,20 @@ mod tests {
|
||||
assert_eq!(folder, folder_from_delta);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_deserialize_invalid_json_test() {
|
||||
for json in vec![
|
||||
// No timestamp
|
||||
r#"{"workspaces":[{"id":"1","name":"first workspace","desc":"","apps":[]}],"trash":[]}"#,
|
||||
// Trailing characters
|
||||
r#"{"workspaces":[{"id":"1","name":"first workspace","desc":"","apps":[]}],"trash":[]}123"#,
|
||||
] {
|
||||
let mut deserializer = serde_json::Deserializer::from_reader(json.as_bytes());
|
||||
let folder_rev = FolderRevision::deserialize(&mut deserializer).unwrap();
|
||||
assert_eq!(folder_rev.workspaces.first().as_ref().unwrap().name, "first workspace");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_update_workspace() {
|
||||
let (mut folder, initial_delta, workspace) = test_folder();
|
||||
|
@ -23,6 +23,8 @@ impl std::ops::Deref for GridViewRevisionPad {
|
||||
}
|
||||
|
||||
impl GridViewRevisionPad {
|
||||
// For the moment, the view_id is equal to grid_id. The grid_id represents the database id.
|
||||
// A database can be referenced by multiple views.
|
||||
pub fn new(grid_id: String, view_id: String) -> Self {
|
||||
let view = Arc::new(GridViewRevision::new(grid_id, view_id));
|
||||
let json = serde_json::to_string(&view).unwrap();
|
||||
@ -30,11 +32,14 @@ impl GridViewRevisionPad {
|
||||
Self { view, delta }
|
||||
}
|
||||
|
||||
pub fn from_delta(delta: Delta) -> CollaborateResult<Self> {
|
||||
pub fn from_delta(view_id: &str, delta: Delta) -> CollaborateResult<Self> {
|
||||
if delta.is_empty() {
|
||||
return Ok(GridViewRevisionPad::new(view_id.to_owned(), view_id.to_owned()));
|
||||
}
|
||||
let s = delta.content()?;
|
||||
let view: GridViewRevision = serde_json::from_str(&s).map_err(|e| {
|
||||
let msg = format!("Deserialize delta to GridViewRevision failed: {}", e);
|
||||
tracing::error!("{}", s);
|
||||
tracing::error!("parsing json: {}", s);
|
||||
CollaborateError::internal().context(msg)
|
||||
})?;
|
||||
Ok(Self {
|
||||
@ -43,9 +48,9 @@ impl GridViewRevisionPad {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_revisions(_grid_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
|
||||
pub fn from_revisions(view_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
|
||||
let delta: Delta = make_text_delta_from_revisions(revisions)?;
|
||||
Self::from_delta(delta)
|
||||
Self::from_delta(view_id, delta)
|
||||
}
|
||||
|
||||
pub fn get_groups_by_field_revs(&self, field_revs: &[Arc<FieldRevision>]) -> Option<GroupConfigurationsByFieldId> {
|
||||
|
Loading…
Reference in New Issue
Block a user