mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-11 02:13:41 +09:00
GO-1084: Extract file methods from anytype service 🎉
This commit is contained in:
parent
1c6ce78557
commit
db21e190f4
30 changed files with 361 additions and 290 deletions
|
@ -62,7 +62,7 @@ type service struct {
|
|||
store objectstore.ObjectStore
|
||||
linkPreview linkpreview.LinkPreview
|
||||
tempDirService *core.TempDirService
|
||||
coreService core.Service
|
||||
fileService *files.Service
|
||||
}
|
||||
|
||||
func New(tempDirService *core.TempDirService) Service {
|
||||
|
@ -74,7 +74,7 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
s.creator = a.MustComponent("objectCreator").(ObjectCreator)
|
||||
s.store = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
s.linkPreview = a.MustComponent(linkpreview.CName).(linkpreview.LinkPreview)
|
||||
s.coreService = a.MustComponent(core.CName).(core.Service)
|
||||
s.fileService = app.MustComponent[*files.Service](a)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ func (s *service) ContentUpdaters(url string) (chan func(contentBookmark *model.
|
|||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
hash, err := loadImage(s.coreService, s.tempDirService.TempDir(), data.Title, data.ImageUrl)
|
||||
hash, err := loadImage(s.fileService, s.tempDirService.TempDir(), data.Title, data.ImageUrl)
|
||||
if err != nil {
|
||||
log.Errorf("can't load image url %s: %s", data.ImageUrl, err)
|
||||
return
|
||||
|
@ -252,7 +252,7 @@ func (s *service) ContentUpdaters(url string) (chan func(contentBookmark *model.
|
|||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
hash, err := loadImage(s.coreService, s.tempDirService.TempDir(), "", data.FaviconUrl)
|
||||
hash, err := loadImage(s.fileService, s.tempDirService.TempDir(), "", data.FaviconUrl)
|
||||
if err != nil {
|
||||
log.Errorf("can't load favicon url %s: %s", data.FaviconUrl, err)
|
||||
return
|
||||
|
@ -292,7 +292,7 @@ func (s *service) fetcher(id string, params bookmark.FetchParams) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func loadImage(coreService core.Service, tempDir string, title, url string) (hash string, err error) {
|
||||
func loadImage(fileService *files.Service, tempDir string, title, url string) (hash string, err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
|
@ -339,7 +339,7 @@ func loadImage(coreService core.Service, tempDir string, title, url string) (has
|
|||
fileName = title
|
||||
}
|
||||
|
||||
im, err := coreService.ImageAdd(context.TODO(), files.WithReader(tmpFile), files.WithName(fileName))
|
||||
im, err := fileService.ImageAdd(context.TODO(), files.WithReader(tmpFile), files.WithName(fileName))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -470,7 +470,7 @@ func (s *Service) CreateAndUploadFile(
|
|||
}
|
||||
|
||||
func (s *Service) UploadFile(req pb.RpcFileUploadRequest) (hash string, err error) {
|
||||
upl := file.NewUploader(s, s.anytype, s.tempDirProvider)
|
||||
upl := file.NewUploader(s, s.fileService, s.tempDirProvider)
|
||||
if req.DisableEncryption {
|
||||
log.Errorf("DisableEncryption is deprecated and has no effect")
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/simple/text"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/converter/html"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/session"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
|
@ -43,25 +44,25 @@ type Clipboard interface {
|
|||
func NewClipboard(
|
||||
sb smartblock.SmartBlock,
|
||||
file file.File,
|
||||
anytype core.Service,
|
||||
tempDirProvider core.TempDirProvider,
|
||||
relationService relation.Service,
|
||||
fileService *files.Service,
|
||||
) Clipboard {
|
||||
return &clipboard{
|
||||
SmartBlock: sb,
|
||||
file: file,
|
||||
anytype: anytype,
|
||||
tempDirProvider: tempDirProvider,
|
||||
relationService: relationService,
|
||||
fileService: fileService,
|
||||
}
|
||||
}
|
||||
|
||||
type clipboard struct {
|
||||
smartblock.SmartBlock
|
||||
file file.File
|
||||
anytype core.Service
|
||||
tempDirProvider core.TempDirProvider
|
||||
relationService relation.Service
|
||||
fileService *files.Service
|
||||
}
|
||||
|
||||
func (cb *clipboard) Paste(ctx *session.Context, req *pb.RpcBlockPasteRequest, groupId string) (blockIds []string, uploadArr []pb.RpcBlockUploadRequest, caretPosition int32, isSameBlockCaret bool, err error) {
|
||||
|
@ -141,14 +142,14 @@ func (cb *clipboard) Copy(req pb.RpcBlockCopyRequest) (textSlot string, htmlSlot
|
|||
cutBlock.GetText().Style = model.BlockContentText_Paragraph
|
||||
textSlot = cutBlock.GetText().Text
|
||||
s.Set(simple.New(cutBlock))
|
||||
htmlSlot = html.NewHTMLConverter(cb.anytype, s).Convert()
|
||||
htmlSlot = html.NewHTMLConverter(cb.fileService, s).Convert()
|
||||
textSlot = cutBlock.GetText().Text
|
||||
anySlot = cb.stateToBlocks(s)
|
||||
return textSlot, htmlSlot, anySlot, nil
|
||||
}
|
||||
|
||||
// scenario: ordinary copy
|
||||
htmlSlot = html.NewHTMLConverter(cb.anytype, s).Convert()
|
||||
htmlSlot = html.NewHTMLConverter(cb.fileService, s).Convert()
|
||||
anySlot = cb.stateToBlocks(s)
|
||||
return textSlot, htmlSlot, anySlot, nil
|
||||
}
|
||||
|
@ -207,7 +208,7 @@ func (cb *clipboard) Cut(ctx *session.Context, req pb.RpcBlockCutRequest) (textS
|
|||
anySlot = []*model.Block{cutBlock}
|
||||
cbs := cb.blocksToState(req.Blocks)
|
||||
cbs.Set(simple.New(cutBlock))
|
||||
htmlSlot = html.NewHTMLConverter(cb.anytype, cbs).Convert()
|
||||
htmlSlot = html.NewHTMLConverter(cb.fileService, cbs).Convert()
|
||||
|
||||
return textSlot, htmlSlot, anySlot, cb.Apply(s)
|
||||
}
|
||||
|
@ -222,7 +223,7 @@ func (cb *clipboard) Cut(ctx *session.Context, req pb.RpcBlockCutRequest) (textS
|
|||
ids = append(ids, b.Id)
|
||||
}
|
||||
|
||||
htmlSlot = html.NewHTMLConverter(cb.anytype, cb.blocksToState(req.Blocks)).Convert()
|
||||
htmlSlot = html.NewHTMLConverter(cb.fileService, cb.blocksToState(req.Blocks)).Convert()
|
||||
anySlot = req.Blocks
|
||||
|
||||
var someUnlinked bool
|
||||
|
@ -242,7 +243,7 @@ func (cb *clipboard) Cut(ctx *session.Context, req pb.RpcBlockCutRequest) (textS
|
|||
|
||||
func (cb *clipboard) Export(req pb.RpcBlockExportRequest) (path string, err error) {
|
||||
s := cb.blocksToState(req.Blocks)
|
||||
htmlData := html.NewHTMLConverter(cb.anytype, s).Export()
|
||||
htmlData := html.NewHTMLConverter(cb.fileService, s).Export()
|
||||
|
||||
dir := cb.tempDirProvider.TempDir()
|
||||
fileName := "export-" + cb.Id() + ".html"
|
||||
|
|
|
@ -41,6 +41,7 @@ type ObjectFactory struct {
|
|||
sourceService source.Service
|
||||
tempDirProvider core.TempDirProvider
|
||||
templateCloner templateCloner
|
||||
fileService *files.Service
|
||||
|
||||
smartblockFactory smartblockFactory
|
||||
}
|
||||
|
@ -68,10 +69,11 @@ func (f *ObjectFactory) Init(a *app.App) (err error) {
|
|||
f.sourceService = app.MustComponent[source.Service](a)
|
||||
f.sendEvent = app.MustComponent[event.Sender](a).Send
|
||||
f.templateCloner = app.MustComponent[templateCloner](a)
|
||||
f.fileService = app.MustComponent[*files.Service](a)
|
||||
|
||||
f.smartblockFactory = smartblockFactory{
|
||||
anytype: f.anytype,
|
||||
fileService: app.MustComponent[*files.Service](a),
|
||||
fileService: f.fileService,
|
||||
indexer: app.MustComponent[smartblock.Indexer](a),
|
||||
objectStore: f.objectStore,
|
||||
relationService: f.relationService,
|
||||
|
@ -158,6 +160,7 @@ func (f *ObjectFactory) New(sbType model.SmartBlockType) (smartblock.SmartBlock,
|
|||
f.tempDirProvider,
|
||||
f.sbtProvider,
|
||||
f.layoutConverter,
|
||||
f.fileService,
|
||||
), nil
|
||||
case model.SmartBlockType_Archive:
|
||||
return NewArchive(
|
||||
|
@ -179,13 +182,13 @@ func (f *ObjectFactory) New(sbType model.SmartBlockType) (smartblock.SmartBlock,
|
|||
sb,
|
||||
f.objectStore,
|
||||
f.relationService,
|
||||
f.anytype,
|
||||
f.fileBlockService,
|
||||
f.bookmarkBlockService,
|
||||
f.bookmarkService,
|
||||
f.sendEvent,
|
||||
f.tempDirProvider,
|
||||
f.layoutConverter,
|
||||
f.fileService,
|
||||
), nil
|
||||
case model.SmartBlockType_File:
|
||||
return NewFiles(sb), nil
|
||||
|
@ -201,6 +204,7 @@ func (f *ObjectFactory) New(sbType model.SmartBlockType) (smartblock.SmartBlock,
|
|||
f.tempDirProvider,
|
||||
f.sbtProvider,
|
||||
f.layoutConverter,
|
||||
f.fileService,
|
||||
), nil
|
||||
case model.SmartBlockType_BundledTemplate:
|
||||
return NewTemplate(
|
||||
|
@ -214,6 +218,7 @@ func (f *ObjectFactory) New(sbType model.SmartBlockType) (smartblock.SmartBlock,
|
|||
f.tempDirProvider,
|
||||
f.sbtProvider,
|
||||
f.layoutConverter,
|
||||
f.fileService,
|
||||
), nil
|
||||
case model.SmartBlockType_Workspace:
|
||||
return NewWorkspace(
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/process"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/simple/file"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/session"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
|
@ -37,14 +38,14 @@ var log = logging.Logger("anytype-mw-smartfile")
|
|||
func NewFile(
|
||||
sb smartblock.SmartBlock,
|
||||
fileSource BlockService,
|
||||
anytype core.Service,
|
||||
tempDirProvider core.TempDirProvider,
|
||||
fileService *files.Service,
|
||||
) File {
|
||||
return &sfile{
|
||||
SmartBlock: sb,
|
||||
fileSource: fileSource,
|
||||
anytype: anytype,
|
||||
tempDirProvider: tempDirProvider,
|
||||
fileService: fileService,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,8 +78,8 @@ type FileSource struct {
|
|||
type sfile struct {
|
||||
smartblock.SmartBlock
|
||||
fileSource BlockService
|
||||
anytype core.Service
|
||||
tempDirProvider core.TempDirProvider
|
||||
fileService *files.Service
|
||||
}
|
||||
|
||||
func (sf *sfile) Upload(ctx *session.Context, id string, source FileSource, isSync bool) (err error) {
|
||||
|
@ -167,7 +168,7 @@ func (sf *sfile) upload(s *state.State, id string, source FileSource, isSync boo
|
|||
}
|
||||
|
||||
func (sf *sfile) newUploader() Uploader {
|
||||
return newUploader(sf.fileSource, sf.anytype, sf.tempDirProvider)
|
||||
return NewUploader(sf.fileSource, sf.fileService, sf.tempDirProvider)
|
||||
}
|
||||
|
||||
func (sf *sfile) UpdateFile(id, groupId string, apply func(b file.Block) error) (err error) {
|
||||
|
@ -186,7 +187,7 @@ func (sf *sfile) UpdateFile(id, groupId string, apply func(b file.Block) error)
|
|||
func (sf *sfile) DropFiles(req pb.RpcFileDropRequest) (err error) {
|
||||
proc := &dropFilesProcess{
|
||||
s: sf.fileSource,
|
||||
coreService: sf.anytype,
|
||||
fileService: sf.fileService,
|
||||
tempDirProvider: sf.tempDirProvider,
|
||||
}
|
||||
if err = proc.Init(req.LocalFilePaths); err != nil {
|
||||
|
@ -300,7 +301,7 @@ type dropFilesHandler interface {
|
|||
type dropFilesProcess struct {
|
||||
id string
|
||||
s BlockService
|
||||
coreService core.Service
|
||||
fileService *files.Service
|
||||
tempDirProvider core.TempDirProvider
|
||||
root *dropFileEntry
|
||||
total, done int64
|
||||
|
@ -518,7 +519,7 @@ func (dp *dropFilesProcess) addFilesWorker(wg *sync.WaitGroup, in chan *dropFile
|
|||
}
|
||||
|
||||
func (dp *dropFilesProcess) addFile(f *dropFileInfo) (err error) {
|
||||
upl := newUploader(dp.s, dp.coreService, dp.tempDirProvider)
|
||||
upl := NewUploader(dp.s, dp.fileService, dp.tempDirProvider)
|
||||
res := upl.SetName(f.name).AutoType(true).SetFile(f.path).Upload(context.TODO())
|
||||
if res.Err != nil {
|
||||
f.err = fmt.Errorf("upload error")
|
||||
|
|
|
@ -40,12 +40,12 @@ func init() {
|
|||
|
||||
func NewUploader(
|
||||
s BlockService,
|
||||
coreService core.Service,
|
||||
fileService *files.Service,
|
||||
provider core.TempDirProvider,
|
||||
) Uploader {
|
||||
return &uploader{
|
||||
service: s,
|
||||
anytype: coreService,
|
||||
fileService: fileService,
|
||||
tempDirProvider: provider,
|
||||
}
|
||||
}
|
||||
|
@ -109,16 +109,8 @@ type uploader struct {
|
|||
opts []files.AddOption
|
||||
groupId string
|
||||
|
||||
anytype core.Service
|
||||
tempDirProvider core.TempDirProvider
|
||||
}
|
||||
|
||||
func newUploader(s BlockService, coreService core.Service, tmpDirService core.TempDirProvider) *uploader {
|
||||
return &uploader{
|
||||
service: s,
|
||||
anytype: coreService,
|
||||
tempDirProvider: tmpDirService,
|
||||
}
|
||||
fileService *files.Service
|
||||
}
|
||||
|
||||
type bufioSeekClose struct {
|
||||
|
@ -357,7 +349,7 @@ func (u *uploader) Upload(ctx context.Context) (result UploadResult) {
|
|||
}
|
||||
|
||||
if u.fileType == model.BlockContentFile_Image {
|
||||
im, e := u.anytype.ImageAdd(ctx, opts...)
|
||||
im, e := u.fileService.ImageAdd(ctx, opts...)
|
||||
if e == image.ErrFormat || e == mill.ErrFormatSupportNotEnabled {
|
||||
log.Infof("can't add file '%s' as image: add as file", u.name)
|
||||
e = nil
|
||||
|
@ -373,7 +365,7 @@ func (u *uploader) Upload(ctx context.Context) (result UploadResult) {
|
|||
result.Size = orig.Meta().Size
|
||||
}
|
||||
} else {
|
||||
fl, e := u.anytype.FileAdd(ctx, opts...)
|
||||
fl, e := u.fileService.FileAdd(ctx, opts...)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/file"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
|
||||
file2 "github.com/anytypeio/go-anytype-middleware/core/block/simple/file"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
|
||||
"github.com/anytypeio/go-anytype-middleware/util/testMock"
|
||||
|
@ -58,13 +59,13 @@ func TestUploader_Upload(t *testing.T) {
|
|||
t.Run("image to file failover", func(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
meta := &core.FileMeta{
|
||||
meta := &files.FileMeta{
|
||||
Media: "text/text",
|
||||
Name: "test.txt",
|
||||
Size: 3,
|
||||
Added: time.Now(),
|
||||
}
|
||||
//fx.anytype.EXPECT().ImageAdd(gomock.Any(), gomock.Any()).Return(nil, image.ErrFormat)
|
||||
// fx.anytype.EXPECT().ImageAdd(gomock.Any(), gomock.Any()).Return(nil, image.ErrFormat)
|
||||
fx.fileService.EXPECT().Do(gomock.Any(), gomock.Any()).Return(nil)
|
||||
fx.anytype.EXPECT().FileAdd(gomock.Any(), gomock.Any()).Return(fx.newFile("123", meta), nil)
|
||||
b := newBlock(model.BlockContentFile_Image)
|
||||
|
@ -146,7 +147,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
fx.fileService.EXPECT().Do(gomock.Any(), gomock.Any()).Return(nil)
|
||||
fx.anytype.EXPECT().FileAdd(gomock.Any(), gomock.Any()).Return(fx.newFile("123", &core.FileMeta{}), nil)
|
||||
fx.anytype.EXPECT().FileAdd(gomock.Any(), gomock.Any()).Return(fx.newFile("123", &files.FileMeta{}), nil)
|
||||
res := fx.Uploader.SetBytes([]byte("my bytes")).SetName("filename").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
assert.Equal(t, res.Hash, "123")
|
||||
|
@ -178,7 +179,7 @@ func (fx *uplFixture) newImage(hash string) *testMock.MockImage {
|
|||
return im
|
||||
}
|
||||
|
||||
func (fx *uplFixture) newFile(hash string, meta *core.FileMeta) *testMock.MockFile {
|
||||
func (fx *uplFixture) newFile(hash string, meta *files.FileMeta) *testMock.MockFile {
|
||||
f := testMock.NewMockFile(fx.ctrl)
|
||||
f.EXPECT().Hash().Return(hash).AnyTimes()
|
||||
f.EXPECT().Meta().Return(meta).AnyTimes()
|
||||
|
|
|
@ -12,6 +12,8 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/restriction"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
relation2 "github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/relation/relationutils"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
|
@ -38,6 +40,7 @@ func NewObjectType(
|
|||
tempDirProvider core.TempDirProvider,
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *ObjectType {
|
||||
return &ObjectType{
|
||||
relationService: relationService,
|
||||
|
@ -50,6 +53,7 @@ func NewObjectType(
|
|||
tempDirProvider,
|
||||
sbtProvider,
|
||||
layoutConverter,
|
||||
fileService,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -138,8 +142,14 @@ func (t *ObjectType) Init(ctx *smartblock.InitContext) (err error) {
|
|||
}
|
||||
}*/
|
||||
|
||||
recommendedLayout := pbtypes.GetInt64(t.Details(), bundle.RelationKeyRecommendedLayout.String())
|
||||
recommendedLayoutObj := bundle.MustGetLayout(model.ObjectTypeLayout(recommendedLayout))
|
||||
recommendedLayout := pbtypes.GetString(t.Details(), bundle.RelationKeyRecommendedLayout.String())
|
||||
if recommendedLayout == "" {
|
||||
recommendedLayout = model.ObjectType_basic.String()
|
||||
} else if _, ok := model.ObjectTypeLayout_value[recommendedLayout]; !ok {
|
||||
recommendedLayout = model.ObjectType_basic.String()
|
||||
}
|
||||
|
||||
recommendedLayoutObj := bundle.MustGetLayout(model.ObjectTypeLayout(model.ObjectTypeLayout_value[recommendedLayout]))
|
||||
for _, rel := range recommendedLayoutObj.RequiredRelations {
|
||||
if slice.FindPos(recommendedRelationsKeys, rel.Key) == -1 {
|
||||
recommendedRelationsKeys = append(recommendedRelationsKeys, rel.Key)
|
||||
|
@ -187,6 +197,36 @@ func (t *ObjectType) Init(ctx *smartblock.InitContext) (err error) {
|
|||
|
||||
defaultValue := &types.Struct{Fields: map[string]*types.Value{bundle.RelationKeyTargetObjectType.String(): pbtypes.String(t.RootId())}}
|
||||
|
||||
if !isBundled {
|
||||
var system bool
|
||||
for _, o := range bundle.SystemTypes {
|
||||
if o.URL() == t.RootId() {
|
||||
system = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var internal bool
|
||||
for _, o := range bundle.InternalTypes {
|
||||
if o.URL() == t.RootId() {
|
||||
internal = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if system {
|
||||
rest := t.Restrictions()
|
||||
obj := append(rest.Object.Copy(), []model.RestrictionsObjectRestriction{model.Restrictions_Details, model.Restrictions_Delete}...)
|
||||
dv := rest.Dataview.Copy()
|
||||
if internal {
|
||||
// internal mean not possible to create the object using the standard ObjectCreate flow
|
||||
dv = append(dv, model.RestrictionsDataviewRestrictions{BlockId: template.DataviewBlockId, Restrictions: []model.RestrictionsDataviewRestriction{model.Restrictions_DVCreateObject}})
|
||||
}
|
||||
t.SetRestrictions(restriction.Restrictions{Object: obj, Dataview: dv})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fixMissingSmartblockTypes := func(s *state.State) {
|
||||
if isBundled {
|
||||
return
|
||||
|
@ -221,7 +261,6 @@ func (t *ObjectType) Init(ctx *smartblock.InitContext) (err error) {
|
|||
}
|
||||
return smartblock.ObjectApplyTemplate(t, ctx.State,
|
||||
template.WithForcedObjectTypes([]string{objectType}),
|
||||
template.WithDetail(bundle.RelationKeyRecommendedLayout, pbtypes.Int64(recommendedLayout)),
|
||||
template.WithForcedDetail(bundle.RelationKeyLayout, pbtypes.Float64(float64(model.ObjectType_objectType))),
|
||||
template.WithEmpty,
|
||||
template.WithTitle,
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/table"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/migration"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
relation2 "github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
|
@ -48,12 +49,13 @@ func NewPage(
|
|||
tempDirProvider core.TempDirProvider,
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *Page {
|
||||
f := file.NewFile(
|
||||
sb,
|
||||
fileBlockService,
|
||||
anytype,
|
||||
tempDirProvider,
|
||||
fileService,
|
||||
)
|
||||
return &Page{
|
||||
SmartBlock: sb,
|
||||
|
@ -67,9 +69,9 @@ func NewPage(
|
|||
Clipboard: clipboard.NewClipboard(
|
||||
sb,
|
||||
f,
|
||||
anytype,
|
||||
tempDirProvider,
|
||||
relationService,
|
||||
fileService,
|
||||
),
|
||||
Bookmark: bookmark.NewBookmark(
|
||||
sb,
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/table"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/migration"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/session"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
|
@ -39,19 +40,19 @@ func NewProfile(
|
|||
sb smartblock.SmartBlock,
|
||||
objectStore objectstore.ObjectStore,
|
||||
relationService relation.Service,
|
||||
anytype core.Service,
|
||||
fileBlockService file.BlockService,
|
||||
bookmarkBlockService bookmark.BlockService,
|
||||
bookmarkService bookmark.BookmarkService,
|
||||
sendEvent func(e *pb.Event),
|
||||
tempDirProvider core.TempDirProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *Profile {
|
||||
f := file.NewFile(
|
||||
sb,
|
||||
fileBlockService,
|
||||
anytype,
|
||||
tempDirProvider,
|
||||
fileService,
|
||||
)
|
||||
return &Profile{
|
||||
SmartBlock: sb,
|
||||
|
@ -66,8 +67,9 @@ func NewProfile(
|
|||
Clipboard: clipboard.NewClipboard(
|
||||
sb,
|
||||
f,
|
||||
anytype,
|
||||
tempDirProvider,
|
||||
relationService,
|
||||
fileService,
|
||||
),
|
||||
Bookmark: bookmark.NewBookmark(
|
||||
sb,
|
||||
|
|
|
@ -6,10 +6,13 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/restriction"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
relation2 "github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/relation/relationutils"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/addr"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/objectstore"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
|
||||
"github.com/anytypeio/go-anytype-middleware/space/typeprovider"
|
||||
|
@ -29,6 +32,7 @@ func NewRelation(
|
|||
tempDirProvider core.TempDirProvider,
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *Relation {
|
||||
return &Relation{
|
||||
SubObject: NewSubObject(
|
||||
|
@ -40,6 +44,7 @@ func NewRelation(
|
|||
tempDirProvider,
|
||||
sbtProvider,
|
||||
layoutConverter,
|
||||
fileService,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +56,19 @@ func (r *Relation) Init(ctx *smartblock.InitContext) error {
|
|||
|
||||
st := ctx.State
|
||||
|
||||
var system bool
|
||||
for _, rel := range bundle.SystemRelations {
|
||||
if addr.RelationKeyToIdPrefix+rel.String() == r.RootId() {
|
||||
system = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if system {
|
||||
rest := r.Restrictions()
|
||||
obj := append(rest.Object.Copy(), []model.RestrictionsObjectRestriction{model.Restrictions_Delete, model.Restrictions_Relations, model.Restrictions_Details}...)
|
||||
r.SetRestrictions(restriction.Restrictions{Object: obj, Dataview: rest.Dataview})
|
||||
}
|
||||
|
||||
// temp fix for our internal accounts with inconsistent types (should be removed later)
|
||||
// todo: remove after release
|
||||
fixTypes := func(s *state.State) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/file"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
relation2 "github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
|
@ -27,6 +28,7 @@ func NewRelationOption(
|
|||
tempDirProvider core.TempDirProvider,
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *RelationOption {
|
||||
return &RelationOption{
|
||||
SubObject: NewSubObject(
|
||||
|
@ -38,6 +40,7 @@ func NewRelationOption(
|
|||
tempDirProvider,
|
||||
sbtProvider,
|
||||
layoutConverter,
|
||||
fileService,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/file"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/stext"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
relation2 "github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore/objectstore"
|
||||
|
@ -35,6 +36,7 @@ func NewSubObject(
|
|||
tempDirProvider core.TempDirProvider,
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *SubObject {
|
||||
return &SubObject{
|
||||
SmartBlock: sb,
|
||||
|
@ -49,12 +51,12 @@ func NewSubObject(
|
|||
file.NewFile(
|
||||
sb,
|
||||
fileBlockService,
|
||||
anytype,
|
||||
tempDirProvider,
|
||||
fileService,
|
||||
),
|
||||
anytype,
|
||||
tempDirProvider,
|
||||
relationService,
|
||||
fileService,
|
||||
),
|
||||
Dataview: dataview.NewDataview(
|
||||
sb,
|
||||
|
|
|
@ -398,15 +398,16 @@ func (c *SubObjectCollection) initSubObject(st *state.State, collection string,
|
|||
return
|
||||
}
|
||||
|
||||
// TODO Extract to subobject factory
|
||||
func (c *SubObjectCollection) newSubObject(collection string) (SubObjectImpl, error) {
|
||||
sb := c.smartblockFactory.Produce()
|
||||
switch collection {
|
||||
case collectionKeyObjectTypes:
|
||||
return NewObjectType(sb, c.objectStore, c.fileBlockService, c.anytype, c.relationService, c.tempDirProvider, c.sbtProvider, c.layoutConverter), nil
|
||||
return NewObjectType(sb, c.objectStore, c.fileBlockService, c.anytype, c.relationService, c.tempDirProvider, c.sbtProvider, c.layoutConverter, c.smartblockFactory.fileService), nil
|
||||
case collectionKeyRelations:
|
||||
return NewRelation(sb, c.objectStore, c.fileBlockService, c.anytype, c.relationService, c.tempDirProvider, c.sbtProvider, c.layoutConverter), nil
|
||||
return NewRelation(sb, c.objectStore, c.fileBlockService, c.anytype, c.relationService, c.tempDirProvider, c.sbtProvider, c.layoutConverter, c.smartblockFactory.fileService), nil
|
||||
case collectionKeyRelationOptions:
|
||||
return NewRelationOption(sb, c.objectStore, c.fileBlockService, c.anytype, c.relationService, c.tempDirProvider, c.sbtProvider, c.layoutConverter), nil
|
||||
return NewRelationOption(sb, c.objectStore, c.fileBlockService, c.anytype, c.relationService, c.tempDirProvider, c.sbtProvider, c.layoutConverter, c.smartblockFactory.fileService), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown collection: %s", collection)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/migration"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
relation2 "github.com/anytypeio/go-anytype-middleware/core/relation"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
|
@ -34,6 +35,7 @@ func NewTemplate(
|
|||
tempDirProvider core.TempDirProvider,
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
fileService *files.Service,
|
||||
) *Template {
|
||||
return &Template{Page: NewPage(
|
||||
sb,
|
||||
|
@ -46,6 +48,7 @@ func NewTemplate(
|
|||
tempDirProvider,
|
||||
sbtProvider,
|
||||
layoutConverter,
|
||||
fileService,
|
||||
)}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/converter/md"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/converter/pbc"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/converter/pbjson"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
|
@ -55,6 +56,7 @@ type export struct {
|
|||
objectStore objectstore.ObjectStore
|
||||
a core.Service
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
fileService *files.Service
|
||||
}
|
||||
|
||||
func New(sbtProvider typeprovider.SmartBlockTypeProvider) Export {
|
||||
|
@ -67,6 +69,7 @@ func (e *export) Init(a *app.App) (err error) {
|
|||
e.bs = a.MustComponent(block.CName).(*block.Service)
|
||||
e.a = a.MustComponent(core.CName).(core.Service)
|
||||
e.objectStore = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
e.fileService = app.MustComponent[*files.Service](a)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -365,7 +368,7 @@ func (e *export) writeDoc(format pb.RpcObjectListExportFormat, wr writer, docInf
|
|||
}
|
||||
|
||||
func (e *export) saveFile(wr writer, hash string) (err error) {
|
||||
file, err := e.a.FileByHash(context.TODO(), hash)
|
||||
file, err := e.fileService.FileByHash(context.TODO(), hash)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -379,7 +382,7 @@ func (e *export) saveFile(wr writer, hash string) (err error) {
|
|||
}
|
||||
|
||||
func (e *export) saveImage(wr writer, hash string) (err error) {
|
||||
file, err := e.a.ImageByHash(context.TODO(), hash)
|
||||
file, err := e.fileService.ImageByHash(context.TODO(), hash)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
"github.com/miolini/datacounter"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/process"
|
||||
files2 "github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
"github.com/anytypeio/go-anytype-middleware/util/files"
|
||||
)
|
||||
|
||||
|
@ -79,15 +79,15 @@ func (s *Service) DownloadFile(req *pb.RpcFileDownloadRequest) (string, error) {
|
|||
return path, nil
|
||||
}
|
||||
|
||||
func (s *Service) getFileOrLargestImage(ctx context.Context, hash string) (core.File, error) {
|
||||
image, err := s.anytype.ImageByHash(ctx, hash)
|
||||
func (s *Service) getFileOrLargestImage(ctx context.Context, hash string) (files2.File, error) {
|
||||
image, err := s.fileService.ImageByHash(ctx, hash)
|
||||
if err != nil {
|
||||
return s.anytype.FileByHash(ctx, hash)
|
||||
return s.fileService.FileByHash(ctx, hash)
|
||||
}
|
||||
|
||||
f, err := image.GetOriginalFile(ctx)
|
||||
if err != nil {
|
||||
return s.anytype.FileByHash(ctx, hash)
|
||||
return s.fileService.FileByHash(ctx, hash)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
|
||||
files2 "github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
|
@ -18,43 +19,45 @@ import (
|
|||
|
||||
var getFileTimeout = time.Second * 5
|
||||
|
||||
func NewFiles(a core.Service, fileStore filestore.FileStore, id string) (s Source) {
|
||||
func NewFiles(a core.Service, fileStore filestore.FileStore, fileService *files2.Service, id string) (s Source) {
|
||||
return &files{
|
||||
id: id,
|
||||
a: a,
|
||||
fileStore: fileStore,
|
||||
id: id,
|
||||
a: a,
|
||||
fileStore: fileStore,
|
||||
fileService: fileService,
|
||||
}
|
||||
}
|
||||
|
||||
type files struct {
|
||||
id string
|
||||
a core.Service
|
||||
fileStore filestore.FileStore
|
||||
id string
|
||||
a core.Service
|
||||
fileStore filestore.FileStore
|
||||
fileService *files2.Service
|
||||
}
|
||||
|
||||
func (v *files) ReadOnly() bool {
|
||||
func (f *files) ReadOnly() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *files) Id() string {
|
||||
return v.id
|
||||
func (f *files) Id() string {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (v *files) Type() model.SmartBlockType {
|
||||
func (f *files) Type() model.SmartBlockType {
|
||||
return model.SmartBlockType_File
|
||||
}
|
||||
|
||||
func (v *files) Virtual() bool {
|
||||
func (f *files) Virtual() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func getDetailsForFileOrImage(ctx context.Context, a core.Service, id string) (p *types.Struct, isImage bool, err error) {
|
||||
f, err := a.FileByHash(ctx, id)
|
||||
func (f *files) getDetailsForFileOrImage(ctx context.Context, id string) (p *types.Struct, isImage bool, err error) {
|
||||
file, err := f.fileService.FileByHash(ctx, id)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if strings.HasPrefix(f.Info().Media, "image") {
|
||||
i, err := a.ImageByHash(ctx, id)
|
||||
if strings.HasPrefix(file.Info().Media, "image") {
|
||||
i, err := f.fileService.ImageByHash(ctx, id)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
@ -62,27 +65,27 @@ func getDetailsForFileOrImage(ctx context.Context, a core.Service, id string) (p
|
|||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
d.Fields[bundle.RelationKeyWorkspaceId.String()] = pbtypes.String(a.PredefinedBlocks().Account)
|
||||
d.Fields[bundle.RelationKeyWorkspaceId.String()] = pbtypes.String(f.a.PredefinedBlocks().Account)
|
||||
return d, true, nil
|
||||
}
|
||||
|
||||
d, err := f.Details()
|
||||
d, err := file.Details()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
d.Fields[bundle.RelationKeyWorkspaceId.String()] = pbtypes.String(a.PredefinedBlocks().Account)
|
||||
d.Fields[bundle.RelationKeyWorkspaceId.String()] = pbtypes.String(f.a.PredefinedBlocks().Account)
|
||||
return d, false, nil
|
||||
}
|
||||
|
||||
func (v *files) ReadDoc(ctx context.Context, receiver ChangeReceiver, empty bool) (doc state.Doc, err error) {
|
||||
s := state.NewDoc(v.id, nil).(*state.State)
|
||||
func (f *files) ReadDoc(ctx context.Context, receiver ChangeReceiver, empty bool) (doc state.Doc, err error) {
|
||||
s := state.NewDoc(f.id, nil).(*state.State)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), getFileTimeout)
|
||||
defer cancel()
|
||||
|
||||
d, _, err := getDetailsForFileOrImage(ctx, v.a, v.id)
|
||||
d, _, err := f.getDetailsForFileOrImage(ctx, f.id)
|
||||
if err != nil {
|
||||
if err == core.ErrFileNotIndexable {
|
||||
if err == files2.ErrFileNotIndexable {
|
||||
return s, nil
|
||||
}
|
||||
return nil, err
|
||||
|
@ -94,42 +97,42 @@ func (v *files) ReadDoc(ctx context.Context, receiver ChangeReceiver, empty bool
|
|||
return s, nil
|
||||
}
|
||||
|
||||
func (v *files) ReadMeta(ctx context.Context, _ ChangeReceiver) (doc state.Doc, err error) {
|
||||
func (f *files) ReadMeta(ctx context.Context, _ ChangeReceiver) (doc state.Doc, err error) {
|
||||
s := &state.State{}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), getFileTimeout)
|
||||
defer cancel()
|
||||
|
||||
d, _, err := getDetailsForFileOrImage(ctx, v.a, v.id)
|
||||
d, _, err := f.getDetailsForFileOrImage(ctx, f.id)
|
||||
if err != nil {
|
||||
if err == core.ErrFileNotIndexable {
|
||||
if err == files2.ErrFileNotIndexable {
|
||||
return s, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.SetDetails(d)
|
||||
s.SetLocalDetail(bundle.RelationKeyId.String(), pbtypes.String(v.id))
|
||||
s.SetLocalDetail(bundle.RelationKeyId.String(), pbtypes.String(f.id))
|
||||
s.SetObjectTypes(pbtypes.GetStringList(d, bundle.RelationKeyType.String()))
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (v *files) PushChange(params PushChangeParams) (id string, err error) {
|
||||
func (f *files) PushChange(params PushChangeParams) (id string, err error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (v *files) ListIds() ([]string, error) {
|
||||
return v.fileStore.ListTargets()
|
||||
func (f *files) ListIds() ([]string, error) {
|
||||
return f.fileStore.ListTargets()
|
||||
}
|
||||
|
||||
func (v *files) Close() (err error) {
|
||||
func (f *files) Close() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (v *files) Heads() []string {
|
||||
func (f *files) Heads() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *files) GetFileKeysSnapshot() []*pb.ChangeFileKeys {
|
||||
func (f *files) GetFileKeysSnapshot() []*pb.ChangeFileKeys {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ func (s *service) NewSource(id string, spaceID string, buildOptions commonspace.
|
|||
st, err := s.sbtProvider.Type(id)
|
||||
switch st {
|
||||
case smartblock.SmartBlockTypeFile:
|
||||
return NewFiles(s.coreService, s.fileStore, id), nil
|
||||
return NewFiles(s.coreService, s.fileStore, s.fileService, id), nil
|
||||
case smartblock.SmartBlockTypeDate:
|
||||
return NewDate(id, s.coreService), nil
|
||||
case smartblock.SmartBlockTypeBundledObjectType:
|
||||
|
|
|
@ -62,6 +62,7 @@ type SourceIdEndodedDetails interface {
|
|||
DetailsFromId() (*types.Struct, error)
|
||||
}
|
||||
|
||||
// TODO Extract implementation from sources impl
|
||||
type SourceType interface {
|
||||
ListIds() ([]string, error)
|
||||
Virtual() bool
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/editor/table"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
|
||||
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
|
||||
utf16 "github.com/anytypeio/go-anytype-middleware/util/text"
|
||||
|
@ -61,14 +61,14 @@ const (
|
|||
</html>`
|
||||
)
|
||||
|
||||
func NewHTMLConverter(a core.Service, s *state.State) *HTML {
|
||||
return &HTML{a: a, s: s}
|
||||
func NewHTMLConverter(fileService *files.Service, s *state.State) *HTML {
|
||||
return &HTML{fileService: fileService, s: s}
|
||||
}
|
||||
|
||||
type HTML struct {
|
||||
a core.Service
|
||||
s *state.State
|
||||
buf *bytes.Buffer
|
||||
s *state.State
|
||||
buf *bytes.Buffer
|
||||
fileService *files.Service
|
||||
}
|
||||
|
||||
func (h *HTML) Convert() (result string) {
|
||||
|
@ -525,7 +525,7 @@ func (h *HTML) renderCell(colWidth map[string]float64, colId string, colToCell m
|
|||
}
|
||||
|
||||
func (h *HTML) getImageBase64(hash string) (res string) {
|
||||
im, err := h.a.ImageByHash(context.TODO(), hash)
|
||||
im, err := h.fileService.ImageByHash(context.TODO(), hash)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package core
|
||||
package files
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/dhowden/tag"
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/storage"
|
||||
|
@ -28,7 +27,7 @@ type File interface {
|
|||
type file struct {
|
||||
hash string
|
||||
info *storage.FileInfo
|
||||
node *files.Service
|
||||
node *Service
|
||||
}
|
||||
|
||||
type FileMeta struct {
|
||||
|
@ -38,8 +37,8 @@ type FileMeta struct {
|
|||
Added time.Time
|
||||
}
|
||||
|
||||
func (i *file) audioDetails() (*types.Struct, error) {
|
||||
r, err := i.Reader()
|
||||
func (f *file) audioDetails() (*types.Struct, error) {
|
||||
r, err := f.Reader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -75,12 +74,12 @@ func (i *file) audioDetails() (*types.Struct, error) {
|
|||
return d, nil
|
||||
}
|
||||
|
||||
func (i *file) Details() (*types.Struct, error) {
|
||||
meta := i.Meta()
|
||||
func (f *file) Details() (*types.Struct, error) {
|
||||
meta := f.Meta()
|
||||
|
||||
t := &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyId.String(): pbtypes.String(i.hash),
|
||||
bundle.RelationKeyId.String(): pbtypes.String(f.hash),
|
||||
bundle.RelationKeyLayout.String(): pbtypes.Float64(float64(model.ObjectType_file)),
|
||||
bundle.RelationKeyIsReadonly.String(): pbtypes.Bool(true),
|
||||
bundle.RelationKeyType.String(): pbtypes.String(bundle.TypeKeyFile.URL()),
|
||||
|
@ -97,7 +96,7 @@ func (i *file) Details() (*types.Struct, error) {
|
|||
}
|
||||
|
||||
if strings.HasPrefix(meta.Media, "audio") {
|
||||
if audioDetails, err := i.audioDetails(); err == nil {
|
||||
if audioDetails, err := f.audioDetails(); err == nil {
|
||||
t = pbtypes.StructMerge(t, audioDetails, false)
|
||||
}
|
||||
t.Fields[bundle.RelationKeyType.String()] = pbtypes.String(bundle.TypeKeyAudio.URL())
|
||||
|
@ -106,23 +105,23 @@ func (i *file) Details() (*types.Struct, error) {
|
|||
return t, nil
|
||||
}
|
||||
|
||||
func (i *file) Info() *storage.FileInfo {
|
||||
return i.info
|
||||
func (f *file) Info() *storage.FileInfo {
|
||||
return f.info
|
||||
}
|
||||
|
||||
func (file *file) Meta() *FileMeta {
|
||||
func (f *file) Meta() *FileMeta {
|
||||
return &FileMeta{
|
||||
Media: file.info.Media,
|
||||
Name: file.info.Name,
|
||||
Size: file.info.Size_,
|
||||
Added: time.Unix(file.info.Added, 0),
|
||||
Media: f.info.Media,
|
||||
Name: f.info.Name,
|
||||
Size: f.info.Size_,
|
||||
Added: time.Unix(f.info.Added, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (file *file) Hash() string {
|
||||
return file.hash
|
||||
func (f *file) Hash() string {
|
||||
return f.hash
|
||||
}
|
||||
|
||||
func (file *file) Reader() (io.ReadSeeker, error) {
|
||||
return file.node.FileContentReader(context.Background(), file.info)
|
||||
func (f *file) Reader() (io.ReadSeeker, error) {
|
||||
return f.node.FileContentReader(context.Background(), f.info)
|
||||
}
|
|
@ -44,11 +44,12 @@ const (
|
|||
)
|
||||
|
||||
var log = logging.Logger("anytype-files")
|
||||
var ErrorFailedToUnmarhalNotencrypted = fmt.Errorf("failed to unmarshal not-encrypted file info")
|
||||
|
||||
var _ app.Component = (*Service)(nil)
|
||||
|
||||
type Service struct {
|
||||
store filestore.FileStore
|
||||
fileStore filestore.FileStore
|
||||
commonFile fileservice.FileService
|
||||
fileSync filesync.FileSync
|
||||
dagService ipld.DAGService
|
||||
|
@ -57,7 +58,7 @@ type Service struct {
|
|||
}
|
||||
|
||||
func (s *Service) Init(a *app.App) (err error) {
|
||||
s.store = a.MustComponent("filestore").(filestore.FileStore)
|
||||
s.fileStore = a.MustComponent("filestore").(filestore.FileStore)
|
||||
s.commonFile = a.MustComponent(fileservice.CName).(fileservice.FileService)
|
||||
s.fileSync = a.MustComponent(filesync.CName).(filesync.FileSync)
|
||||
s.spaceService = a.MustComponent(space.CName).(space.Service)
|
||||
|
@ -89,8 +90,8 @@ var ValidContentLinkNames = []string{"content"}
|
|||
|
||||
var cidBuilder = cid.V1Builder{Codec: cid.DagProtobuf, MhType: mh.SHA2_256}
|
||||
|
||||
func (s *Service) FileAdd(ctx context.Context, opts AddOptions) (string, *storage.FileInfo, error) {
|
||||
fileInfo, err := s.FileAddWithConfig(ctx, &m.Blob{}, opts)
|
||||
func (s *Service) fileAdd(ctx context.Context, opts AddOptions) (string, *storage.FileInfo, error) {
|
||||
fileInfo, err := s.fileAddWithConfig(ctx, &m.Blob{}, opts)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -112,7 +113,7 @@ func (s *Service) FileAdd(ctx context.Context, opts AddOptions) (string, *storag
|
|||
return "", nil, err
|
||||
}
|
||||
|
||||
if err = s.store.AddFileKeys(filestore.FileKeys{
|
||||
if err = s.fileStore.AddFileKeys(filestore.FileKeys{
|
||||
Hash: nodeHash,
|
||||
Keys: keys.KeysByPath,
|
||||
}); err != nil {
|
||||
|
@ -122,14 +123,27 @@ func (s *Service) FileAdd(ctx context.Context, opts AddOptions) (string, *storag
|
|||
return nodeHash, fileInfo, nil
|
||||
}
|
||||
|
||||
func (s *Service) getChunksCount(ctx context.Context, node ipld.Node) (int, error) {
|
||||
var chunksCount int
|
||||
err := ipld.NewWalker(ctx, ipld.NewNavigableIPLDNode(node, s.commonFile.DAGService())).
|
||||
Iterate(func(_ ipld.NavigableNode) error {
|
||||
chunksCount++
|
||||
return nil
|
||||
})
|
||||
if err != nil && err != ipld.EndOfDag {
|
||||
return -1, fmt.Errorf("failed to count cids: %w", err)
|
||||
}
|
||||
return chunksCount, nil
|
||||
}
|
||||
|
||||
func (s *Service) storeChunksCount(ctx context.Context, node ipld.Node) error {
|
||||
chunksCount, err := s.fileSync.FetchChunksCount(ctx, node)
|
||||
chunksCount, err := s.getChunksCount(ctx, node)
|
||||
if err != nil {
|
||||
return fmt.Errorf("count chunks: %w", err)
|
||||
}
|
||||
|
||||
nodeHash := node.Cid().String()
|
||||
if err = s.store.SetChunksCount(nodeHash, chunksCount); err != nil {
|
||||
if err = s.fileStore.SetChunksCount(nodeHash, chunksCount); err != nil {
|
||||
return fmt.Errorf("store chunks count: %w", err)
|
||||
}
|
||||
|
||||
|
@ -152,7 +166,7 @@ func (s *Service) FileRestoreKeys(ctx context.Context, hash string) (map[string]
|
|||
|
||||
if looksLikeFileNode(node) {
|
||||
l := schema.LinkByName(node.Links(), ValidContentLinkNames)
|
||||
info, err := s.store.GetByHash(l.Cid.String())
|
||||
info, err := s.fileStore.GetByHash(l.Cid.String())
|
||||
if err == nil {
|
||||
fileKeys["/"+index.Name+"/"] = info.Key
|
||||
} else {
|
||||
|
@ -171,7 +185,7 @@ func (s *Service) FileRestoreKeys(ctx context.Context, hash string) (map[string]
|
|||
continue
|
||||
}
|
||||
|
||||
info, err := s.store.GetByHash(l.Cid.String())
|
||||
info, err := s.fileStore.GetByHash(l.Cid.String())
|
||||
|
||||
if err == nil {
|
||||
fileKeys["/"+index.Name+"/"+link.Name+"/"] = info.Key
|
||||
|
@ -182,7 +196,7 @@ func (s *Service) FileRestoreKeys(ctx context.Context, hash string) (map[string]
|
|||
}
|
||||
}
|
||||
|
||||
err = s.store.AddFileKeys(filestore.FileKeys{
|
||||
err = s.fileStore.AddFileKeys(filestore.FileKeys{
|
||||
Hash: hash,
|
||||
Keys: fileKeys,
|
||||
})
|
||||
|
@ -296,7 +310,7 @@ func (s *Service) FileGetInfoForPath(pth string) (*storage.FileInfo, error) {
|
|||
}
|
||||
|
||||
func (s *Service) FileGetKeys(hash string) (*FileKeys, error) {
|
||||
m, err := s.store.GetFileKeys(hash)
|
||||
m, err := s.fileStore.GetFileKeys(hash)
|
||||
if err != nil {
|
||||
if err != localstore.ErrNotFound {
|
||||
return nil, err
|
||||
|
@ -369,7 +383,7 @@ func (s *Service) fileIndexLink(ctx context.Context, inode ipld.Node, data strin
|
|||
return ErrMissingContentLink
|
||||
}
|
||||
|
||||
return s.store.AddTarget(dlink.Cid.String(), data)
|
||||
return s.fileStore.AddTarget(dlink.Cid.String(), data)
|
||||
}
|
||||
|
||||
func (s *Service) fileInfoFromPath(target string, path string, key string) (*storage.FileInfo, error) {
|
||||
|
@ -428,7 +442,7 @@ func (s *Service) fileInfoFromPath(target string, path string, key string) (*sto
|
|||
}
|
||||
err = proto.Unmarshal(b, &file)
|
||||
if err != nil || file.Hash == "" {
|
||||
return nil, fmt.Errorf("failed to unmarshal not-encrypted file info: %w", err)
|
||||
return nil, ErrorFailedToUnmarhalNotencrypted
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,7 +458,7 @@ func (s *Service) fileContent(ctx context.Context, hash string) (io.ReadSeeker,
|
|||
var err error
|
||||
var file *storage.FileInfo
|
||||
var reader io.ReadSeeker
|
||||
file, err = s.store.GetByHash(hash)
|
||||
file, err = s.fileStore.GetByHash(hash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -478,7 +492,7 @@ func (s *Service) FileContentReader(ctx context.Context, file *storage.FileInfo)
|
|||
return dec.DecryptReader(fd)
|
||||
}
|
||||
|
||||
func (s *Service) FileAddWithConfig(ctx context.Context, mill m.Mill, conf AddOptions) (*storage.FileInfo, error) {
|
||||
func (s *Service) fileAddWithConfig(ctx context.Context, mill m.Mill, conf AddOptions) (*storage.FileInfo, error) {
|
||||
var source string
|
||||
if conf.Use != "" {
|
||||
source = conf.Use
|
||||
|
@ -501,7 +515,7 @@ func (s *Service) FileAddWithConfig(ctx context.Context, mill m.Mill, conf AddOp
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if efile, _ := s.store.GetBySource(mill.ID(), source, opts); efile != nil && efile.MetaHash != "" {
|
||||
if efile, _ := s.fileStore.GetBySource(mill.ID(), source, opts); efile != nil && efile.MetaHash != "" {
|
||||
efile.Targets = nil
|
||||
return efile, nil
|
||||
}
|
||||
|
@ -518,7 +532,7 @@ func (s *Service) FileAddWithConfig(ctx context.Context, mill m.Mill, conf AddOp
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if efile, _ := s.store.GetByChecksum(mill.ID(), check); efile != nil && efile.MetaHash != "" {
|
||||
if efile, _ := s.fileStore.GetByChecksum(mill.ID(), check); efile != nil && efile.MetaHash != "" {
|
||||
efile.Targets = nil
|
||||
return efile, nil
|
||||
}
|
||||
|
@ -596,7 +610,7 @@ func (s *Service) FileAddWithConfig(ctx context.Context, mill m.Mill, conf AddOp
|
|||
|
||||
fileInfo.MetaHash = metaNode.Cid().String()
|
||||
|
||||
err = s.store.Add(fileInfo)
|
||||
err = s.fileStore.Add(fileInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -605,7 +619,7 @@ func (s *Service) FileAddWithConfig(ctx context.Context, mill m.Mill, conf AddOp
|
|||
}
|
||||
|
||||
func (s *Service) fileNode(ctx context.Context, file *storage.FileInfo, dir uio.Directory, link string) error {
|
||||
file, err := s.store.GetByHash(file.Hash)
|
||||
file, err := s.fileStore.GetByHash(file.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -657,7 +671,7 @@ func (s *Service) fileBuildDirectory(ctx context.Context, reader io.ReadSeeker,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
added, err := s.FileAddWithConfig(ctx, mil, opts)
|
||||
added, err := s.fileAddWithConfig(ctx, mil, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -709,7 +723,7 @@ func (s *Service) fileBuildDirectory(ctx context.Context, reader io.ReadSeeker,
|
|||
}
|
||||
}
|
||||
|
||||
added, err := s.FileAddWithConfig(ctx, stepMill, *opts)
|
||||
added, err := s.fileAddWithConfig(ctx, stepMill, *opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -729,7 +743,7 @@ func (s *Service) FileIndexInfo(ctx context.Context, hash string, updateIfExists
|
|||
return nil, err
|
||||
}
|
||||
|
||||
keys, err := s.store.GetFileKeys(hash)
|
||||
keys, err := s.fileStore.GetFileKeys(hash)
|
||||
if err != nil {
|
||||
// no keys means file is not encrypted or keys are missing
|
||||
log.Errorf("failed to get file keys from filestore %s: %s", hash, err.Error())
|
||||
|
@ -769,7 +783,7 @@ func (s *Service) FileIndexInfo(ctx context.Context, hash string, updateIfExists
|
|||
}
|
||||
}
|
||||
|
||||
err = s.store.AddMulti(updateIfExists, files...)
|
||||
err = s.fileStore.AddMulti(updateIfExists, files...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add files to store: %w", err)
|
||||
}
|
||||
|
@ -831,5 +845,55 @@ func (s *Service) StoreFileKeys(fileKeys ...FileKeys) error {
|
|||
})
|
||||
}
|
||||
|
||||
return s.store.AddFileKeys(fks...)
|
||||
return s.fileStore.AddFileKeys(fks...)
|
||||
}
|
||||
|
||||
var ErrFileNotFound = fmt.Errorf("file not found")
|
||||
|
||||
func (s *Service) FileByHash(ctx context.Context, hash string) (File, error) {
|
||||
fileList, err := s.fileStore.ListByTarget(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fileList) == 0 || fileList[0].MetaHash == "" {
|
||||
// info from ipfs
|
||||
fileList, err = s.FileIndexInfo(ctx, hash, false)
|
||||
if err != nil {
|
||||
log.With("cid", hash).Errorf("FileByHash: failed to retrieve from IPFS: %s", err.Error())
|
||||
return nil, ErrFileNotFound
|
||||
}
|
||||
}
|
||||
|
||||
fileIndex := fileList[0]
|
||||
return &file{
|
||||
hash: hash,
|
||||
info: fileIndex,
|
||||
node: s,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO: Touch the file to fire indexing
|
||||
func (s *Service) FileAdd(ctx context.Context, options ...AddOption) (File, error) {
|
||||
opts := AddOptions{}
|
||||
for _, opt := range options {
|
||||
opt(&opts)
|
||||
}
|
||||
|
||||
err := s.NormalizeOptions(ctx, &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash, info, err := s.fileAdd(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := &file{
|
||||
hash: hash,
|
||||
info: info,
|
||||
node: s,
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package core
|
||||
package files
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -12,7 +12,6 @@ import (
|
|||
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/mill"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
|
||||
|
@ -39,7 +38,7 @@ type Image interface {
|
|||
type image struct {
|
||||
hash string // directory hash
|
||||
variantsByWidth map[int]*storage.FileInfo
|
||||
service *files.Service
|
||||
service *Service
|
||||
}
|
||||
|
||||
func (i *image) GetFileForWidth(ctx context.Context, wantWidth int) (File, error) {
|
|
@ -9,7 +9,68 @@ import (
|
|||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/storage"
|
||||
)
|
||||
|
||||
func (s *Service) ImageAdd(ctx context.Context, opts AddOptions) (string, map[int]*storage.FileInfo, error) {
|
||||
var ErrImageNotFound = fmt.Errorf("image not found")
|
||||
|
||||
func (s *Service) ImageByHash(ctx context.Context, hash string) (Image, error) {
|
||||
files, err := s.fileStore.ListByTarget(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check the image files count explicitly because we have a bug when the info can be cached not fully(only for some files)
|
||||
if len(files) < 4 || files[0].MetaHash == "" {
|
||||
// index image files info from ipfs
|
||||
files, err = s.FileIndexInfo(ctx, hash, true)
|
||||
if err != nil {
|
||||
log.Errorf("ImageByHash: failed to retrieve from IPFS: %s", err.Error())
|
||||
return nil, ErrImageNotFound
|
||||
}
|
||||
}
|
||||
|
||||
var variantsByWidth = make(map[int]*storage.FileInfo, len(files))
|
||||
for _, f := range files {
|
||||
if f.Mill != "/image/resize" {
|
||||
continue
|
||||
}
|
||||
|
||||
if v, exists := f.Meta.Fields["width"]; exists {
|
||||
variantsByWidth[int(v.GetNumberValue())] = f
|
||||
}
|
||||
}
|
||||
|
||||
return &image{
|
||||
hash: files[0].Targets[0],
|
||||
variantsByWidth: variantsByWidth,
|
||||
service: s,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO: Touch the file to fire indexing
|
||||
func (s *Service) ImageAdd(ctx context.Context, options ...AddOption) (Image, error) {
|
||||
opts := AddOptions{}
|
||||
for _, opt := range options {
|
||||
opt(&opts)
|
||||
}
|
||||
|
||||
err := s.NormalizeOptions(ctx, &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash, variants, err := s.imageAdd(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img := &image{
|
||||
hash: hash,
|
||||
variantsByWidth: variants,
|
||||
service: s,
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func (s *Service) imageAdd(ctx context.Context, opts AddOptions) (string, map[int]*storage.FileInfo, error) {
|
||||
dir, err := s.fileBuildDirectory(ctx, opts.Reader, opts.Name, opts.Plaintext, anytype.ImageNode())
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
@ -24,7 +85,7 @@ func (s *Service) ImageAdd(ctx context.Context, opts AddOptions) (string, map[in
|
|||
}
|
||||
|
||||
nodeHash := node.Cid().String()
|
||||
err = s.store.AddFileKeys(filestore.FileKeys{
|
||||
err = s.fileStore.AddFileKeys(filestore.FileKeys{
|
||||
Hash: nodeHash,
|
||||
Keys: keys.KeysByPath,
|
||||
})
|
||||
|
|
|
@ -67,7 +67,7 @@ func (s *Service) fileOffload(hash string) (totalSize uint64, err error) {
|
|||
|
||||
func (s *Service) FileListOffload(fileIDs []string, includeNotPinned bool) (totalBytesOffloaded uint64, totalFilesOffloaded uint64, err error) {
|
||||
if len(fileIDs) == 0 {
|
||||
allFiles, err := s.store.List()
|
||||
allFiles, err := s.fileStore.List()
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("list all files: %w", err)
|
||||
}
|
||||
|
|
|
@ -41,12 +41,6 @@ type Service interface {
|
|||
EnsurePredefinedBlocks(ctx context.Context) error
|
||||
PredefinedBlocks() threads.DerivedSmartblockIds
|
||||
|
||||
FileByHash(ctx context.Context, hash string) (File, error)
|
||||
FileAdd(ctx context.Context, opts ...files2.AddOption) (File, error)
|
||||
|
||||
ImageByHash(ctx context.Context, hash string) (Image, error)
|
||||
ImageAdd(ctx context.Context, opts ...files2.AddOption) (Image, error)
|
||||
|
||||
GetAllWorkspaces() ([]string, error)
|
||||
GetWorkspaceIdForObject(objectId string) (string, error)
|
||||
|
||||
|
|
|
@ -1,58 +1,2 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
files2 "github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
)
|
||||
|
||||
var ErrFileNotFound = fmt.Errorf("file not found")
|
||||
|
||||
func (a *Anytype) FileByHash(ctx context.Context, hash string) (File, error) {
|
||||
fileList, err := a.fileStore.ListByTarget(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fileList) == 0 || fileList[0].MetaHash == "" {
|
||||
// info from ipfs
|
||||
fileList, err = a.files.FileIndexInfo(ctx, hash, false)
|
||||
if err != nil {
|
||||
log.With("cid", hash).Errorf("FileByHash: failed to retrieve from IPFS: %s", err.Error())
|
||||
return nil, ErrFileNotFound
|
||||
}
|
||||
}
|
||||
|
||||
fileIndex := fileList[0]
|
||||
return &file{
|
||||
hash: hash,
|
||||
info: fileIndex,
|
||||
node: a.files,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO: Touch the file to fire indexing
|
||||
func (a *Anytype) FileAdd(ctx context.Context, options ...files2.AddOption) (File, error) {
|
||||
opts := files2.AddOptions{}
|
||||
for _, opt := range options {
|
||||
opt(&opts)
|
||||
}
|
||||
|
||||
err := a.files.NormalizeOptions(ctx, &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash, info, err := a.files.FileAdd(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := &file{
|
||||
hash: hash,
|
||||
info: info,
|
||||
node: a.files,
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
|
|
@ -1,70 +1,2 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/storage"
|
||||
)
|
||||
|
||||
var ErrImageNotFound = fmt.Errorf("image not found")
|
||||
|
||||
func (a *Anytype) ImageByHash(ctx context.Context, hash string) (Image, error) {
|
||||
files, err := a.fileStore.ListByTarget(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check the image files count explicitly because we have a bug when the info can be cached not fully(only for some files)
|
||||
if len(files) < 4 || files[0].MetaHash == "" {
|
||||
// index image files info from ipfs
|
||||
files, err = a.files.FileIndexInfo(ctx, hash, true)
|
||||
if err != nil {
|
||||
log.Errorf("ImageByHash: failed to retrieve from IPFS: %s", err.Error())
|
||||
return nil, ErrImageNotFound
|
||||
}
|
||||
}
|
||||
|
||||
var variantsByWidth = make(map[int]*storage.FileInfo, len(files))
|
||||
for _, f := range files {
|
||||
if f.Mill != "/image/resize" {
|
||||
continue
|
||||
}
|
||||
|
||||
if v, exists := f.Meta.Fields["width"]; exists {
|
||||
variantsByWidth[int(v.GetNumberValue())] = f
|
||||
}
|
||||
}
|
||||
|
||||
return &image{
|
||||
hash: files[0].Targets[0],
|
||||
variantsByWidth: variantsByWidth,
|
||||
service: a.files,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO: Touch the file to fire indexing
|
||||
func (a *Anytype) ImageAdd(ctx context.Context, options ...files.AddOption) (Image, error) {
|
||||
opts := files.AddOptions{}
|
||||
for _, opt := range options {
|
||||
opt(&opts)
|
||||
}
|
||||
|
||||
err := a.files.NormalizeOptions(ctx, &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash, variants, err := a.files.ImageAdd(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img := &image{
|
||||
hash: hash,
|
||||
variantsByWidth: variants,
|
||||
service: a.files,
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/util/netutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -15,8 +13,11 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/anytypeio/any-sync/app"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/core/files"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/logging"
|
||||
"github.com/anytypeio/go-anytype-middleware/util/netutil"
|
||||
)
|
||||
|
||||
const CName = "gateway"
|
||||
|
@ -37,7 +38,7 @@ type Gateway interface {
|
|||
}
|
||||
|
||||
type gateway struct {
|
||||
Node core.Service
|
||||
fileService *files.Service
|
||||
server *http.Server
|
||||
listener net.Listener
|
||||
handler *http.ServeMux
|
||||
|
@ -76,7 +77,7 @@ func GatewayAddr() string {
|
|||
}
|
||||
|
||||
func (g *gateway) Init(a *app.App) (err error) {
|
||||
g.Node = a.MustComponent(core.CName).(core.Service)
|
||||
g.fileService = app.MustComponent[*files.Service](a)
|
||||
g.addr = GatewayAddr()
|
||||
log.Debugf("gateway.Init: %s", g.addr)
|
||||
return nil
|
||||
|
@ -204,7 +205,7 @@ func (g *gateway) fileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
fileHash = parts[0]
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer cancel()
|
||||
file, err := g.Node.FileByHash(ctx, fileHash)
|
||||
file, err := g.fileService.FileByHash(ctx, fileHash)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "file not found") {
|
||||
http.NotFound(w, r)
|
||||
|
@ -238,7 +239,7 @@ func (g *gateway) imageHandler(w http.ResponseWriter, r *http.Request) {
|
|||
enableCors(w)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer cancel()
|
||||
image, err := g.Node.ImageByHash(ctx, imageHash)
|
||||
image, err := g.fileService.ImageByHash(ctx, imageHash)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "file not found") {
|
||||
http.NotFound(w, r)
|
||||
|
@ -247,7 +248,7 @@ func (g *gateway) imageHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
var file core.File
|
||||
var file files.File
|
||||
wantWidthStr := query.Get("width")
|
||||
if wantWidthStr == "" {
|
||||
file, err = image.GetOriginalFile(ctx)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue