mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-09 09:35:00 +09:00
GO-3504 Support cross-space links dnd
This commit is contained in:
parent
4d554f0433
commit
7231f548c2
2 changed files with 109 additions and 3 deletions
|
@ -19,6 +19,7 @@ import (
|
|||
relationblock "github.com/anyproto/anytype-heart/core/block/simple/relation"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple/text"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/domain/linkresolver"
|
||||
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileobject"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
|
@ -188,9 +189,7 @@ func (bs *basic) copyBlocks(srcState, destState *state.State, sourceId string) (
|
|||
return newId, nil
|
||||
}
|
||||
|
||||
m := b.Copy().Model()
|
||||
m.Id = "" // reset id
|
||||
result := simple.New(m)
|
||||
result := copySimpleBlock(b, bs.SpaceID(), destState.SpaceID())
|
||||
destState.Add(result)
|
||||
for i, childrenId := range result.Model().ChildrenIds {
|
||||
if result.Model().ChildrenIds[i], err = bs.copyBlocks(srcState, destState, childrenId); err != nil {
|
||||
|
@ -224,6 +223,32 @@ func (bs *basic) processFileBlock(f *model.BlockContentOfFile, spaceId string) {
|
|||
f.File.TargetObjectId = objectId
|
||||
}
|
||||
|
||||
func copySimpleBlock(b simple.Block, srcSpaceId, destSpaceId string) simple.Block {
|
||||
isSameSpace := srcSpaceId == destSpaceId
|
||||
blockCopy := b.Copy()
|
||||
|
||||
if replacer, ok := blockCopy.(simple.ObjectLinkReplacer); ok && !isSameSpace {
|
||||
replacer.ReplaceLinkIds(func(oldId string) (newId string) {
|
||||
if oldId == "" {
|
||||
return
|
||||
}
|
||||
id, err := linkresolver.ParseObjectLink(oldId)
|
||||
if err != nil {
|
||||
return linkresolver.GetObjectLink(domain.FullID{SpaceID: srcSpaceId, ObjectID: oldId})
|
||||
}
|
||||
if id.SpaceID == destSpaceId {
|
||||
return id.ObjectID
|
||||
}
|
||||
return oldId
|
||||
})
|
||||
}
|
||||
|
||||
blockModel := blockCopy.Model()
|
||||
blockModel.Id = "" // reset id
|
||||
|
||||
return simple.New(blockModel)
|
||||
}
|
||||
|
||||
func (bs *basic) Unlink(ctx session.Context, ids ...string) (err error) {
|
||||
s := bs.NewStateCtx(ctx)
|
||||
|
||||
|
|
|
@ -197,6 +197,87 @@ func TestBasic_Duplicate(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
t.Run("copy cross-space links to other space", func(t *testing.T) {
|
||||
// given
|
||||
source := smarttest.New("source").
|
||||
AddBlock(simple.New(&model.Block{Id: "source", ChildrenIds: []string{"1", "l1", "t1"}})).
|
||||
AddBlock(simple.New(&model.Block{Id: "1", ChildrenIds: []string{"l2", "t2"}})).
|
||||
AddBlock(simple.New(&model.Block{Id: "l1", Content: &model.BlockContentOfLink{
|
||||
Link: &model.BlockContentLink{TargetBlockId: "obj11"}}})).
|
||||
AddBlock(simple.New(&model.Block{Id: "t1", Content: &model.BlockContentOfText{Text: &model.BlockContentText{
|
||||
Text: "it is link to object from 3rd space",
|
||||
Marks: &model.BlockContentTextMarks{Marks: []*model.BlockContentTextMark{{
|
||||
Type: model.BlockContentTextMark_Link,
|
||||
Param: "object?spaceId=sp3&objectId=obj13",
|
||||
}}}}}})).
|
||||
AddBlock(simple.New(&model.Block{Id: "l2", Content: &model.BlockContentOfLink{
|
||||
Link: &model.BlockContentLink{TargetBlockId: "object?spaceId=sp2&objectId=obj21"}}})).
|
||||
AddBlock(simple.New(&model.Block{Id: "t2", Content: &model.BlockContentOfText{Text: &model.BlockContentText{
|
||||
Text: "it is mention of object from 1st space",
|
||||
Marks: &model.BlockContentTextMarks{Marks: []*model.BlockContentTextMark{{
|
||||
Type: model.BlockContentTextMark_Mention,
|
||||
Param: "obj12",
|
||||
}}}}}}))
|
||||
source.SetSpaceId("sp1")
|
||||
ss := source.NewState()
|
||||
ss.SetDetail(bundle.RelationKeySpaceId.String(), pbtypes.String("sp1"))
|
||||
|
||||
target := smarttest.New("target").AddBlock(simple.New(&model.Block{Id: "target"}))
|
||||
ts := target.NewState()
|
||||
ts.SetDetail(bundle.RelationKeySpaceId.String(), pbtypes.String("sp2"))
|
||||
|
||||
// when
|
||||
newIds, err := NewBasic(source, nil, nil, nil).Duplicate(ss, ts, "target", model.Block_Inner, []string{"1", "l1", "t1"})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, target.Apply(ts))
|
||||
|
||||
// then
|
||||
require.Len(t, newIds, 3)
|
||||
|
||||
ts = target.NewState()
|
||||
root := ts.Pick("target")
|
||||
require.NotNil(t, root)
|
||||
assert.Equal(t, newIds, root.Model().ChildrenIds)
|
||||
block1 := ts.Pick(newIds[0])
|
||||
require.NotNil(t, block1)
|
||||
children := block1.Model().ChildrenIds
|
||||
require.Len(t, children, 2)
|
||||
|
||||
l1 := ts.Pick(newIds[1])
|
||||
t1 := ts.Pick(newIds[2])
|
||||
l2 := ts.Pick(children[0])
|
||||
t2 := ts.Pick(children[1])
|
||||
|
||||
assertLink := func(block simple.Block, link string) {
|
||||
l := block.Model().GetLink()
|
||||
require.NotNil(t, l)
|
||||
assert.Equal(t, link, l.TargetBlockId)
|
||||
}
|
||||
|
||||
linkTypes := []model.BlockContentTextMarkType{model.BlockContentTextMark_Link, model.BlockContentTextMark_Mention}
|
||||
assertText := func(block simple.Block, link string) {
|
||||
txt := block.Model().GetText()
|
||||
require.NotNil(t, txt)
|
||||
require.NotNil(t, txt.Marks)
|
||||
require.NotEmpty(t, txt.Marks.GetMarks())
|
||||
assert.Contains(t, linkTypes, txt.Marks.GetMarks()[0].Type)
|
||||
assert.Equal(t, link, txt.Marks.GetMarks()[0].Param)
|
||||
}
|
||||
|
||||
for _, testBlock := range []struct {
|
||||
block simple.Block
|
||||
link string
|
||||
assertFunc func(block simple.Block, link string)
|
||||
}{
|
||||
{l1, "object?spaceId=sp1&objectId=obj11", assertLink},
|
||||
{t1, "object?spaceId=sp3&objectId=obj13", assertText},
|
||||
{l2, "obj21", assertLink},
|
||||
{t2, "object?spaceId=sp1&objectId=obj12", assertText},
|
||||
} {
|
||||
testBlock.assertFunc(testBlock.block, testBlock.link)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestBasic_Unlink(t *testing.T) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue