From aa60b430aee0acb66c5ee50071d05102fafa3425 Mon Sep 17 00:00:00 2001 From: kirillston Date: Thu, 5 Dec 2024 11:57:36 +0100 Subject: [PATCH 1/7] GO-4270 Add virtual file blocks --- core/block/files.go | 35 +++++ core/block/service.go | 4 + .../files/fileobject/fileblocks/fileblocks.go | 147 ++++++++++++++++++ core/files/fileobject/fileindex.go | 87 +---------- 4 files changed, 188 insertions(+), 85 deletions(-) create mode 100644 core/files/fileobject/fileblocks/fileblocks.go diff --git a/core/block/files.go b/core/block/files.go index e4ea28e706..60af759719 100644 --- a/core/block/files.go +++ b/core/block/files.go @@ -6,11 +6,16 @@ import ( "os" "time" + "github.com/gogo/protobuf/types" "github.com/miolini/datacounter" + "github.com/anyproto/anytype-heart/core/block/editor/state" + "github.com/anyproto/anytype-heart/core/block/editor/template" "github.com/anyproto/anytype-heart/core/block/process" "github.com/anyproto/anytype-heart/core/files" + "github.com/anyproto/anytype-heart/core/files/fileobject/fileblocks" "github.com/anyproto/anytype-heart/pb" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" "github.com/anyproto/anytype-heart/util/anyerror" ) @@ -96,3 +101,33 @@ func (s *Service) getFileOrLargestImage(ctx context.Context, objectId string) (f return f, nil } + +func injectVirtualFileBlocks(objectId string, view *model.ObjectView) { + if view.Type != model.SmartBlockType_FileObject { + return + } + + var details *types.Struct + for _, det := range view.Details { + if det.Id == objectId { + details = det.Details + break + } + } + if details == nil { + return + } + + st := state.NewDoc(objectId, nil).NewState() + template.InitTemplate(st, + template.WithEmpty, + template.WithTitle, + template.WithDefaultFeaturedRelations, + template.WithFeaturedRelations, + template.WithAllBlocksEditsRestricted, + ) + + _ = fileblocks.AddFileBlocks(st, details, objectId) + + view.Blocks = st.Blocks() +} diff --git a/core/block/service.go b/core/block/service.go index d722bd398e..08404026d4 100644 --- a/core/block/service.go +++ b/core/block/service.go @@ -209,6 +209,9 @@ func (s *Service) OpenBlock(sctx session.Context, id domain.FullID, includeRelat return nil, err } mutex.WithLock(s.openedObjs.lock, func() any { s.openedObjs.objects[id.ObjectID] = true; return nil }) + + injectVirtualFileBlocks(id.ObjectID, obj) + return obj, nil } @@ -243,6 +246,7 @@ func (s *Service) ShowBlock(id domain.FullID, includeRelationsAsDependentObjects obj, err = b.Show() return err }) + injectVirtualFileBlocks(id.ObjectID, obj) return obj, err } diff --git a/core/files/fileobject/fileblocks/fileblocks.go b/core/files/fileobject/fileblocks/fileblocks.go new file mode 100644 index 0000000000..328ec9a024 --- /dev/null +++ b/core/files/fileobject/fileblocks/fileblocks.go @@ -0,0 +1,147 @@ +package fileblocks + +import ( + "fmt" + + "github.com/gogo/protobuf/types" + + "github.com/anyproto/anytype-heart/core/block/editor/state" + "github.com/anyproto/anytype-heart/core/block/editor/template" + "github.com/anyproto/anytype-heart/core/block/simple" + fileblock "github.com/anyproto/anytype-heart/core/block/simple/file" + "github.com/anyproto/anytype-heart/core/domain" + "github.com/anyproto/anytype-heart/pkg/lib/bundle" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" + "github.com/anyproto/anytype-heart/util/pbtypes" +) + +func AddFileBlocks(st *state.State, details *types.Struct, objectId string) error { + fname := pbtypes.GetString(details, bundle.RelationKeyName.String()) + fileType := fileblock.DetectTypeByMIME(fname, pbtypes.GetString(details, bundle.RelationKeyFileMimeType.String())) + + if fileType == model.BlockContentFile_Image { + st.SetDetailAndBundledRelation(bundle.RelationKeyIconImage, pbtypes.String(objectId)) + } + + blocks := BuildFileBlocks(details, objectId, fname, fileType) + + for _, b := range blocks { + if st.Exists(b.Id) { + st.Set(simple.New(b)) + } else { + st.Add(simple.New(b)) + err := st.InsertTo(st.RootId(), model.Block_Inner, b.Id) + if err != nil { + return fmt.Errorf("failed to insert file block: %w", err) + } + } + } + template.WithAllBlocksEditsRestricted(st) + return nil +} + +func BuildFileBlocks(details *types.Struct, objectId, fname string, fileType model.BlockContentFileType) []*model.Block { + var blocks []*model.Block + blocks = append(blocks, &model.Block{ + Id: "file", + Content: &model.BlockContentOfFile{ + File: &model.BlockContentFile{ + Name: fname, + Mime: pbtypes.GetString(details, bundle.RelationKeyFileMimeType.String()), + TargetObjectId: objectId, + Type: fileType, + Size_: int64(pbtypes.GetFloat64(details, bundle.RelationKeySizeInBytes.String())), + State: model.BlockContentFile_Done, + AddedAt: int64(pbtypes.GetFloat64(details, bundle.RelationKeyAddedDate.String())), + }, + }}, makeFileInfoBlock(), makeRelationBlock(bundle.RelationKeyFileExt)) + + switch fileType { + case model.BlockContentFile_Image: + for _, relKey := range []domain.RelationKey{ + bundle.RelationKeyWidthInPixels, + bundle.RelationKeyHeightInPixels, + bundle.RelationKeyCamera, + bundle.RelationKeyMediaArtistName, + bundle.RelationKeyMediaArtistURL, + } { + if notEmpty(details, relKey) { + blocks = append(blocks, makeRelationBlock(relKey)) + } + } + case model.BlockContentFile_Audio: + for _, relKey := range []domain.RelationKey{ + bundle.RelationKeyArtist, + bundle.RelationKeyAudioAlbum, + bundle.RelationKeyAudioAlbumTrackNumber, + bundle.RelationKeyAudioGenre, + bundle.RelationKeyAudioLyrics, + bundle.RelationKeyReleasedYear, + } { + if notEmpty(details, relKey) { + blocks = append(blocks, makeRelationBlock(relKey)) + } + } + case model.BlockContentFile_Video: + for _, relKey := range []domain.RelationKey{ + bundle.RelationKeyWidthInPixels, + bundle.RelationKeyHeightInPixels, + bundle.RelationKeyCamera, + bundle.RelationKeyCameraIso, + bundle.RelationKeyAperture, + bundle.RelationKeyExposure, + } { + if notEmpty(details, relKey) { + blocks = append(blocks, makeRelationBlock(relKey)) + } + } + } + + for _, relKey := range []domain.RelationKey{ + bundle.RelationKeySizeInBytes, + bundle.RelationKeyOrigin, + bundle.RelationKeyImportType, + bundle.RelationKeyAddedDate, + } { + if pbtypes.GetInt64(details, relKey.String()) != 0 { + blocks = append(blocks, makeRelationBlock(relKey)) + } + } + + return blocks +} + +func makeFileInfoBlock() *model.Block { + return &model.Block{ + Id: "info", + Content: &model.BlockContentOfText{ + Text: &model.BlockContentText{ + Text: "File Information", + Marks: &model.BlockContentTextMarks{ + Marks: []*model.BlockContentTextMark{{ + Range: &model.Range{ + From: 0, + To: 16, + }, + Type: model.BlockContentTextMark_Bold, + }}, + }, + }, + }, + } +} + +func notEmpty(details *types.Struct, relKey domain.RelationKey) bool { + return pbtypes.GetInt64(details, relKey.String()) != 0 || pbtypes.GetString(details, relKey.String()) != "" +} + +func makeRelationBlock(relationKey domain.RelationKey) *model.Block { + return &model.Block{ + Id: relationKey.String(), + Content: &model.BlockContentOfRelation{ + Relation: &model.BlockContentRelation{ + Key: relationKey.String(), + }, + }, + } +} diff --git a/core/files/fileobject/fileindex.go b/core/files/fileobject/fileindex.go index c6c280c812..7c47a1859a 100644 --- a/core/files/fileobject/fileindex.go +++ b/core/files/fileobject/fileindex.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "strings" "sync" "time" @@ -15,11 +14,9 @@ import ( "github.com/anyproto/anytype-heart/core/block/editor/smartblock" "github.com/anyproto/anytype-heart/core/block/editor/state" - "github.com/anyproto/anytype-heart/core/block/editor/template" - "github.com/anyproto/anytype-heart/core/block/simple" - fileblock "github.com/anyproto/anytype-heart/core/block/simple/file" "github.com/anyproto/anytype-heart/core/domain" "github.com/anyproto/anytype-heart/core/files" + "github.com/anyproto/anytype-heart/core/files/fileobject/fileblocks" "github.com/anyproto/anytype-heart/core/filestorage/rpcstore" "github.com/anyproto/anytype-heart/pkg/lib/bundle" "github.com/anyproto/anytype-heart/pkg/lib/database" @@ -252,7 +249,7 @@ func (ind *indexer) injectMetadataToState(ctx context.Context, st *state.State, details = pbtypes.StructMerge(prevDetails, details, false) st.SetDetails(details) - err = ind.addBlocks(st, details, id.ObjectID) + err = fileblocks.AddFileBlocks(st, details, id.ObjectID) if err != nil { return fmt.Errorf("add blocks: %w", err) } @@ -291,83 +288,3 @@ func (ind *indexer) buildDetails(ctx context.Context, id domain.FullFileId) (det details.Fields[bundle.RelationKeyFileIndexingStatus.String()] = pbtypes.Int64(int64(model.FileIndexingStatus_Indexed)) return details, typeKey, nil } - -func (ind *indexer) addBlocks(st *state.State, details *types.Struct, objectId string) error { - fname := pbtypes.GetString(details, bundle.RelationKeyName.String()) - fileType := fileblock.DetectTypeByMIME(fname, pbtypes.GetString(details, bundle.RelationKeyFileMimeType.String())) - - ext := pbtypes.GetString(details, bundle.RelationKeyFileExt.String()) - - if ext != "" && !strings.HasSuffix(fname, "."+ext) { - fname = fname + "." + ext - } - - var blocks []*model.Block - blocks = append(blocks, &model.Block{ - Id: "file", - Content: &model.BlockContentOfFile{ - File: &model.BlockContentFile{ - Name: fname, - Mime: pbtypes.GetString(details, bundle.RelationKeyFileMimeType.String()), - TargetObjectId: objectId, - Type: fileType, - Size_: int64(pbtypes.GetFloat64(details, bundle.RelationKeySizeInBytes.String())), - State: model.BlockContentFile_Done, - AddedAt: int64(pbtypes.GetFloat64(details, bundle.RelationKeyFileMimeType.String())), - }, - }}) - - switch fileType { - case model.BlockContentFile_Image: - st.SetDetailAndBundledRelation(bundle.RelationKeyIconImage, pbtypes.String(objectId)) - - if pbtypes.GetInt64(details, bundle.RelationKeyWidthInPixels.String()) != 0 { - blocks = append(blocks, makeRelationBlock(bundle.RelationKeyWidthInPixels)) - } - - if pbtypes.GetInt64(details, bundle.RelationKeyHeightInPixels.String()) != 0 { - blocks = append(blocks, makeRelationBlock(bundle.RelationKeyHeightInPixels)) - } - - if pbtypes.GetString(details, bundle.RelationKeyCamera.String()) != "" { - blocks = append(blocks, makeRelationBlock(bundle.RelationKeyCamera)) - } - - if pbtypes.GetInt64(details, bundle.RelationKeySizeInBytes.String()) != 0 { - blocks = append(blocks, makeRelationBlock(bundle.RelationKeySizeInBytes)) - } - if pbtypes.GetString(details, bundle.RelationKeyMediaArtistName.String()) != "" { - blocks = append(blocks, makeRelationBlock(bundle.RelationKeyMediaArtistName)) - } - if pbtypes.GetString(details, bundle.RelationKeyMediaArtistURL.String()) != "" { - blocks = append(blocks, makeRelationBlock(bundle.RelationKeyMediaArtistURL)) - } - default: - blocks = append(blocks, makeRelationBlock(bundle.RelationKeySizeInBytes)) - } - - for _, b := range blocks { - if st.Exists(b.Id) { - st.Set(simple.New(b)) - } else { - st.Add(simple.New(b)) - err := st.InsertTo(st.RootId(), model.Block_Inner, b.Id) - if err != nil { - return fmt.Errorf("failed to insert file block: %w", err) - } - } - } - template.WithAllBlocksEditsRestricted(st) - return nil -} - -func makeRelationBlock(relationKey domain.RelationKey) *model.Block { - return &model.Block{ - Id: relationKey.String(), - Content: &model.BlockContentOfRelation{ - Relation: &model.BlockContentRelation{ - Key: relationKey.String(), - }, - }, - } -} From 5134df739dbb48bbe6b58b0d039b989dfc377b66 Mon Sep 17 00:00:00 2001 From: kirillston Date: Thu, 5 Dec 2024 14:37:13 +0100 Subject: [PATCH 2/7] GO-4270 Add title --- core/block/editor/files.go | 3 ++- core/block/files.go | 11 ++--------- core/files/fileobject/fileblocks/fileblocks.go | 14 ++++++++++++-- core/files/fileobject/service.go | 12 +++--------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/core/block/editor/files.go b/core/block/editor/files.go index 7068a5ad05..17da47e9cc 100644 --- a/core/block/editor/files.go +++ b/core/block/editor/files.go @@ -12,6 +12,7 @@ import ( "github.com/anyproto/anytype-heart/core/block/source" "github.com/anyproto/anytype-heart/core/domain" "github.com/anyproto/anytype-heart/core/files/fileobject" + "github.com/anyproto/anytype-heart/core/files/fileobject/fileblocks" "github.com/anyproto/anytype-heart/core/files/reconciler" "github.com/anyproto/anytype-heart/core/filestorage" "github.com/anyproto/anytype-heart/pkg/lib/bundle" @@ -59,7 +60,7 @@ func (f *File) CreationStateMigration(ctx *smartblock.InitContext) migration.Mig // - In background metadata indexer, if we use asynchronous metadata indexing mode // // See fileobject.Service - f.fileObjectService.InitEmptyFileState(ctx.State) + fileblocks.InitEmptyFileState(ctx.State) }, } } diff --git a/core/block/files.go b/core/block/files.go index 60af759719..ebef45b063 100644 --- a/core/block/files.go +++ b/core/block/files.go @@ -10,7 +10,6 @@ import ( "github.com/miolini/datacounter" "github.com/anyproto/anytype-heart/core/block/editor/state" - "github.com/anyproto/anytype-heart/core/block/editor/template" "github.com/anyproto/anytype-heart/core/block/process" "github.com/anyproto/anytype-heart/core/files" "github.com/anyproto/anytype-heart/core/files/fileobject/fileblocks" @@ -119,14 +118,8 @@ func injectVirtualFileBlocks(objectId string, view *model.ObjectView) { } st := state.NewDoc(objectId, nil).NewState() - template.InitTemplate(st, - template.WithEmpty, - template.WithTitle, - template.WithDefaultFeaturedRelations, - template.WithFeaturedRelations, - template.WithAllBlocksEditsRestricted, - ) - + st.SetDetails(details) + fileblocks.InitEmptyFileState(st) _ = fileblocks.AddFileBlocks(st, details, objectId) view.Blocks = st.Blocks() diff --git a/core/files/fileobject/fileblocks/fileblocks.go b/core/files/fileobject/fileblocks/fileblocks.go index 328ec9a024..c1340fc633 100644 --- a/core/files/fileobject/fileblocks/fileblocks.go +++ b/core/files/fileobject/fileblocks/fileblocks.go @@ -15,6 +15,16 @@ import ( "github.com/anyproto/anytype-heart/util/pbtypes" ) +func InitEmptyFileState(st *state.State) { + template.InitTemplate(st, + template.WithEmpty, + template.WithTitle, + template.WithDefaultFeaturedRelations, + template.WithFeaturedRelations, + template.WithAllBlocksEditsRestricted, + ) +} + func AddFileBlocks(st *state.State, details *types.Struct, objectId string) error { fname := pbtypes.GetString(details, bundle.RelationKeyName.String()) fileType := fileblock.DetectTypeByMIME(fname, pbtypes.GetString(details, bundle.RelationKeyFileMimeType.String())) @@ -23,7 +33,7 @@ func AddFileBlocks(st *state.State, details *types.Struct, objectId string) erro st.SetDetailAndBundledRelation(bundle.RelationKeyIconImage, pbtypes.String(objectId)) } - blocks := BuildFileBlocks(details, objectId, fname, fileType) + blocks := buildFileBlocks(details, objectId, fname, fileType) for _, b := range blocks { if st.Exists(b.Id) { @@ -40,7 +50,7 @@ func AddFileBlocks(st *state.State, details *types.Struct, objectId string) erro return nil } -func BuildFileBlocks(details *types.Struct, objectId, fname string, fileType model.BlockContentFileType) []*model.Block { +func buildFileBlocks(details *types.Struct, objectId, fname string, fileType model.BlockContentFileType) []*model.Block { var blocks []*model.Block blocks = append(blocks, &model.Block{ Id: "file", diff --git a/core/files/fileobject/service.go b/core/files/fileobject/service.go index b1f1429705..73475d44e9 100644 --- a/core/files/fileobject/service.go +++ b/core/files/fileobject/service.go @@ -15,7 +15,6 @@ import ( "github.com/anyproto/anytype-heart/core/anytype/config" "github.com/anyproto/anytype-heart/core/block/editor/smartblock" "github.com/anyproto/anytype-heart/core/block/editor/state" - "github.com/anyproto/anytype-heart/core/block/editor/template" "github.com/anyproto/anytype-heart/core/block/object/idresolver" "github.com/anyproto/anytype-heart/core/block/object/objectcreator" "github.com/anyproto/anytype-heart/core/block/object/payloadcreator" @@ -23,6 +22,7 @@ import ( "github.com/anyproto/anytype-heart/core/domain" "github.com/anyproto/anytype-heart/core/domain/objectorigin" "github.com/anyproto/anytype-heart/core/files" + "github.com/anyproto/anytype-heart/core/files/fileobject/fileblocks" "github.com/anyproto/anytype-heart/core/files/fileobject/filemodels" "github.com/anyproto/anytype-heart/core/files/fileoffloader" "github.com/anyproto/anytype-heart/core/filestorage/filesync" @@ -263,13 +263,7 @@ func (s *service) Close(ctx context.Context) error { } func (s *service) InitEmptyFileState(st *state.State) { - template.InitTemplate(st, - template.WithEmpty, - template.WithTitle, - template.WithDefaultFeaturedRelations, - template.WithFeaturedRelations, - template.WithAllBlocksEditsRestricted, - ) + fileblocks.InitEmptyFileState(st) } func (s *service) Create(ctx context.Context, spaceId string, req filemodels.CreateRequest) (id string, object *types.Struct, err error) { @@ -312,7 +306,7 @@ func (s *service) createInSpace(ctx context.Context, space clientspace.Space, re EncryptionKeys: req.EncryptionKeys, }) if !req.AsyncMetadataIndexing { - s.InitEmptyFileState(createState) + fileblocks.InitEmptyFileState(createState) fullFileId := domain.FullFileId{SpaceId: space.Id(), FileId: req.FileId} fullObjectId := domain.FullID{SpaceID: space.Id(), ObjectID: payload.RootRawChange.Id} err := s.indexer.injectMetadataToState(ctx, createState, fullFileId, fullObjectId) From a823512cf1af38defbcecb71a62e2b6909ce8634 Mon Sep 17 00:00:00 2001 From: kirillston Date: Thu, 5 Dec 2024 18:54:16 +0100 Subject: [PATCH 3/7] GO-4270 Fix lint --- core/block/files.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/block/files.go b/core/block/files.go index ebef45b063..be6e5fc866 100644 --- a/core/block/files.go +++ b/core/block/files.go @@ -120,7 +120,10 @@ func injectVirtualFileBlocks(objectId string, view *model.ObjectView) { st := state.NewDoc(objectId, nil).NewState() st.SetDetails(details) fileblocks.InitEmptyFileState(st) - _ = fileblocks.AddFileBlocks(st, details, objectId) + if err := fileblocks.AddFileBlocks(st, details, objectId); err != nil { + log.Errorf("failed to inject virtual file blocks: %v", err) + return + } view.Blocks = st.Blocks() } From d53750240032e514e696f6a510b47cceb9b85a78 Mon Sep 17 00:00:00 2001 From: kirillston Date: Thu, 5 Dec 2024 21:30:29 +0100 Subject: [PATCH 4/7] GO-4270 Add test --- .../fileobject/fileblocks/fileblocks_test.go | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 core/files/fileobject/fileblocks/fileblocks_test.go diff --git a/core/files/fileobject/fileblocks/fileblocks_test.go b/core/files/fileobject/fileblocks/fileblocks_test.go new file mode 100644 index 0000000000..144ad5abb1 --- /dev/null +++ b/core/files/fileobject/fileblocks/fileblocks_test.go @@ -0,0 +1,104 @@ +package fileblocks + +import ( + "fmt" + "testing" + "time" + + "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/assert" + + "github.com/anyproto/anytype-heart/core/block/editor/state" + "github.com/anyproto/anytype-heart/core/block/simple" + "github.com/anyproto/anytype-heart/core/domain" + "github.com/anyproto/anytype-heart/pkg/lib/bundle" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" + "github.com/anyproto/anytype-heart/util/pbtypes" +) + +func TestAddFileBlocks(t *testing.T) { + id := "some_file" + + for _, tc := range []struct { + name string + details *types.Struct + expectedRelations []domain.RelationKey + }{ + { + "image", + &types.Struct{Fields: map[string]*types.Value{ + bundle.RelationKeyName.String(): pbtypes.String("photo.jpeg"), + bundle.RelationKeyFileMimeType.String(): pbtypes.String("image/jpeg"), + bundle.RelationKeyWidthInPixels.String(): pbtypes.Int64(400), + bundle.RelationKeyHeightInPixels.String(): pbtypes.Int64(600), + bundle.RelationKeyAddedDate.String(): pbtypes.Int64(time.Now().Unix()), + }}, + []domain.RelationKey{bundle.RelationKeyFileExt, bundle.RelationKeyWidthInPixels, bundle.RelationKeyHeightInPixels, bundle.RelationKeyAddedDate}, + }, + { + "plain file", + &types.Struct{Fields: map[string]*types.Value{ + bundle.RelationKeyName.String(): pbtypes.String("txt.txt"), + bundle.RelationKeySizeInBytes.String(): pbtypes.Int64(24000), + bundle.RelationKeyOrigin.String(): pbtypes.Int64(int64(model.ObjectOrigin_dragAndDrop)), + bundle.RelationKeyAddedDate.String(): pbtypes.Int64(time.Now().Unix()), + }}, + []domain.RelationKey{bundle.RelationKeyFileExt, bundle.RelationKeySizeInBytes, bundle.RelationKeyOrigin, bundle.RelationKeyAddedDate}, + }, + { + "audio", + &types.Struct{Fields: map[string]*types.Value{ + bundle.RelationKeyName.String(): pbtypes.String("song.mp3"), + bundle.RelationKeyFileMimeType.String(): pbtypes.String("audio/mp3"), + bundle.RelationKeySizeInBytes.String(): pbtypes.Int64(2400000), + bundle.RelationKeyAudioAlbum.String(): pbtypes.String("Never mind"), + bundle.RelationKeyAudioAlbumTrackNumber.String(): pbtypes.Int64(13), + bundle.RelationKeyOrigin.String(): pbtypes.Int64(int64(model.ObjectOrigin_clipboard)), + bundle.RelationKeyImportType.String(): pbtypes.Int64(2), + }}, + []domain.RelationKey{bundle.RelationKeyFileExt, bundle.RelationKeySizeInBytes, bundle.RelationKeyAudioAlbum, bundle.RelationKeyAudioAlbumTrackNumber, bundle.RelationKeyOrigin, bundle.RelationKeyImportType}, + }, + } { + t.Run(fmt.Sprintf("add file blocks: %s", tc.name), func(t *testing.T) { + // given + st := state.NewDoc(id, map[string]simple.Block{ + id: simple.New(&model.Block{Id: id}), + }).NewState() + + // when + err := AddFileBlocks(st, tc.details, id) + + // then + assert.NoError(t, err) + assertBlocks(t, st.Blocks(), tc.expectedRelations) + }) + } +} + +func assertBlocks(t *testing.T, blocks []*model.Block, relations []domain.RelationKey) { + counter := 0 + var txtFound, fileFound bool + for _, block := range blocks { + rb := block.GetRelation() + if rb != nil { + assert.Contains(t, relations, domain.RelationKey(rb.Key)) + counter++ + continue + } + + txt := block.GetText() + if txt != nil { + assert.Equal(t, "File Information", txt.GetText()) + txtFound = true + continue + } + + file := block.GetFile() + if file != nil { + fileFound = true + } + } + assert.Equal(t, counter, len(relations)) + assert.True(t, txtFound) + assert.True(t, fileFound) +} From 45b875d703979be49ab9cada3545b4969fb6bc88 Mon Sep 17 00:00:00 2001 From: kirillston Date: Tue, 10 Dec 2024 12:39:05 +0100 Subject: [PATCH 5/7] GO-4263 Add tag and backlinks to featured relations --- core/block/editor/template/template.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/block/editor/template/template.go b/core/block/editor/template/template.go index d1f804a94b..f4ab09a7e3 100644 --- a/core/block/editor/template/template.go +++ b/core/block/editor/template/template.go @@ -232,6 +232,8 @@ var WithDefaultFeaturedRelations = func(s *state.State) { fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeySetOf.String(), bundle.RelationKeyBacklinks.String()} case model.ObjectType_collection: fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeyBacklinks.String()} + case model.ObjectType_file, model.ObjectType_image, model.ObjectType_audio, model.ObjectType_video: + fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(), bundle.RelationKeyBacklinks.String()} } s.SetDetail(bundle.RelationKeyFeaturedRelations.String(), pbtypes.StringList(fr)) } From ca5d94b534ca977204f88c4e9517c1d4d36dd0d9 Mon Sep 17 00:00:00 2001 From: kirillston Date: Tue, 10 Dec 2024 18:51:48 +0100 Subject: [PATCH 6/7] GO-4270 Add withVirtualBlocks interface --- core/block/editor/files.go | 30 ++++++++++++++++++++++++++++++ core/block/files.go | 31 ------------------------------- core/block/service.go | 22 +++++++++++++++++----- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/core/block/editor/files.go b/core/block/editor/files.go index 17da47e9cc..8a9e97a989 100644 --- a/core/block/editor/files.go +++ b/core/block/editor/files.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/gogo/protobuf/types" + "github.com/anyproto/anytype-heart/core/block/editor/basic" "github.com/anyproto/anytype-heart/core/block/editor/smartblock" "github.com/anyproto/anytype-heart/core/block/editor/state" @@ -17,6 +19,7 @@ import ( "github.com/anyproto/anytype-heart/core/filestorage" "github.com/anyproto/anytype-heart/pkg/lib/bundle" coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock" + "github.com/anyproto/anytype-heart/pkg/lib/pb/model" ) // required relations for files beside the bundle.RequiredInternalRelations @@ -99,3 +102,30 @@ func (f *File) Init(ctx *smartblock.InitContext) error { } return nil } + +func (f *File) InjectVirtualBlocks(objectId string, view *model.ObjectView) { + if view.Type != model.SmartBlockType_FileObject { + return + } + + var details *types.Struct + for _, det := range view.Details { + if det.Id == objectId { + details = det.Details + break + } + } + if details == nil { + return + } + + st := state.NewDoc(objectId, nil).NewState() + st.SetDetails(details) + fileblocks.InitEmptyFileState(st) + if err := fileblocks.AddFileBlocks(st, details, objectId); err != nil { + log.Errorf("failed to inject virtual file blocks: %v", err) + return + } + + view.Blocks = st.Blocks() +} diff --git a/core/block/files.go b/core/block/files.go index be6e5fc866..e4ea28e706 100644 --- a/core/block/files.go +++ b/core/block/files.go @@ -6,15 +6,11 @@ import ( "os" "time" - "github.com/gogo/protobuf/types" "github.com/miolini/datacounter" - "github.com/anyproto/anytype-heart/core/block/editor/state" "github.com/anyproto/anytype-heart/core/block/process" "github.com/anyproto/anytype-heart/core/files" - "github.com/anyproto/anytype-heart/core/files/fileobject/fileblocks" "github.com/anyproto/anytype-heart/pb" - "github.com/anyproto/anytype-heart/pkg/lib/pb/model" "github.com/anyproto/anytype-heart/util/anyerror" ) @@ -100,30 +96,3 @@ func (s *Service) getFileOrLargestImage(ctx context.Context, objectId string) (f return f, nil } - -func injectVirtualFileBlocks(objectId string, view *model.ObjectView) { - if view.Type != model.SmartBlockType_FileObject { - return - } - - var details *types.Struct - for _, det := range view.Details { - if det.Id == objectId { - details = det.Details - break - } - } - if details == nil { - return - } - - st := state.NewDoc(objectId, nil).NewState() - st.SetDetails(details) - fileblocks.InitEmptyFileState(st) - if err := fileblocks.AddFileBlocks(st, details, objectId); err != nil { - log.Errorf("failed to inject virtual file blocks: %v", err) - return - } - - view.Blocks = st.Blocks() -} diff --git a/core/block/service.go b/core/block/service.go index 08404026d4..f471ac44dd 100644 --- a/core/block/service.go +++ b/core/block/service.go @@ -59,6 +59,10 @@ import ( const CName = "block-service" +type withVirtualBlocks interface { + InjectVirtualBlocks(objectId string, view *model.ObjectView) +} + var ErrUnknownObjectType = fmt.Errorf("unknown object type") var log = logging.Logger("anytype-mw-service") @@ -193,6 +197,10 @@ func (s *Service) OpenBlock(sctx session.Context, id domain.FullID, includeRelat log.Errorf("failed to watch status for object %s: %s", id, err) } + if v, ok := ob.(withVirtualBlocks); ok { + v.InjectVirtualBlocks(id.ObjectID, obj) + } + afterHashesTime := time.Now() metrics.Service.Send(&metrics.OpenBlockEvent{ ObjectId: id.ObjectID, @@ -209,9 +217,6 @@ func (s *Service) OpenBlock(sctx session.Context, id domain.FullID, includeRelat return nil, err } mutex.WithLock(s.openedObjs.lock, func() any { s.openedObjs.objects[id.ObjectID] = true; return nil }) - - injectVirtualFileBlocks(id.ObjectID, obj) - return obj, nil } @@ -244,9 +249,16 @@ func (s *Service) ShowBlock(id domain.FullID, includeRelationsAsDependentObjects b.EnabledRelationAsDependentObjects() } obj, err = b.Show() - return err + if err != nil { + return err + } + + if v, ok := b.(withVirtualBlocks); ok { + v.InjectVirtualBlocks(id.ObjectID, obj) + } + + return nil }) - injectVirtualFileBlocks(id.ObjectID, obj) return obj, err } From 3dd6948b01cbe928261c211abe31bd3bc616bf21 Mon Sep 17 00:00:00 2001 From: kirillston Date: Wed, 11 Dec 2024 17:56:10 +0100 Subject: [PATCH 7/7] GO-4270 Increase timeout in test --- core/subscription/service_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/subscription/service_test.go b/core/subscription/service_test.go index 00f12753c8..3a0172fb17 100644 --- a/core/subscription/service_test.go +++ b/core/subscription/service_test.go @@ -82,7 +82,7 @@ func TestService_Search(t *testing.T) { require.NoError(t, err) // Wait enough time to flush pending updates to subscriptions handler - time.Sleep(batchTime + time.Millisecond) + time.Sleep(batchTime + 3*time.Millisecond) spaceSub.onChange([]*entry{ newEntry("1", &types.Struct{Fields: map[string]*types.Value{