mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-08 05:47:07 +09:00
GO-2827 Merge branch 'main' of github.com:anyproto/anytype-heart into go-2827-migration-unbind-user-files
# Conflicts: # .mockery.yaml # clientlibrary/service/service.pb.go # core/files/fileobject/service.go # docs/proto.md # pb/commands.pb.go # pb/service/service.pb.go
This commit is contained in:
commit
431a455e94
220 changed files with 13982 additions and 5137 deletions
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
|
@ -16,18 +16,17 @@ jobs:
|
|||
GOPRIVATE: github.com/anyproto
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v1
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22
|
||||
|
||||
cache: false
|
||||
- name: git config
|
||||
run: git config --global url.https://${{ secrets.ANYTYPE_PAT }}@github.com/.insteadOf https://github.com/
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup GO
|
||||
- name: Setup GO env
|
||||
run: |
|
||||
echo GOPATH=$(go env GOPATH) >> $GITHUB_ENV
|
||||
echo GOBIN=$(go env GOPATH)/bin >> $GITHUB_ENV
|
||||
|
@ -61,7 +60,7 @@ jobs:
|
|||
PACKAGE_NAMES=$(go list -tags nogrpcserver ./... | grep -v "github.com/anyproto/anytype-heart/cmd/grpserver" | grep -v "github.com/anyproto/anytype-heart/clientlibrary/clib")
|
||||
rm -rf ~/gotestsum-report
|
||||
mkdir ~/gotestsum-report
|
||||
CGO_CFLAGS="-Wno-deprecated-declarations -Wno-deprecated-non-prototype -Wno-xor-used-as-pow" gotestsum --junitfile ~/gotestsum-report/gotestsum-report.xml -- -tags "nogrpcserver nographviz" -p 1 $(echo $PACKAGE_NAMES) -race -coverprofile=coverage.out -covermode=atomic ./...
|
||||
CGO_CFLAGS="-Wno-deprecated-non-prototype -Wno-unknown-warning-option -Wno-deprecated-declarations -Wno-xor-used-as-pow -Wno-single-bit-bitfield-constant-conversion" gotestsum --junitfile ~/gotestsum-report/gotestsum-report.xml -- -tags "nogrpcserver nographviz" -ldflags="-extldflags=-Wl,-ld_classic" -p 1 $(echo $PACKAGE_NAMES) -race -coverprofile=coverage.out -covermode=atomic ./...
|
||||
|
||||
generated_pattern='^\/\/ Code generated .* DO NOT EDIT\.$'
|
||||
files_list=$(grep -rl "$generated_pattern" . | grep '\.go$' | sed 's/^\.\///')
|
||||
|
|
|
@ -9,6 +9,8 @@ run:
|
|||
go: '1.22'
|
||||
|
||||
linters-settings:
|
||||
unused:
|
||||
field-writes-are-uses: false
|
||||
errcheck:
|
||||
check-blank: true
|
||||
errchkjson:
|
||||
|
|
|
@ -10,6 +10,9 @@ packages:
|
|||
github.com/anyproto/anytype-heart/core/wallet:
|
||||
interfaces:
|
||||
Wallet:
|
||||
github.com/anyproto/anytype-heart/core/nameservice:
|
||||
interfaces:
|
||||
Service:
|
||||
github.com/anyproto/anytype-heart/core/event:
|
||||
interfaces:
|
||||
Sender:
|
||||
|
@ -169,3 +172,6 @@ packages:
|
|||
github.com/anyproto/anytype-heart/core/filestorage:
|
||||
interfaces:
|
||||
FileStorage:
|
||||
github.com/anyproto/anytype-heart/util/linkpreview:
|
||||
interfaces:
|
||||
LinkPreview:
|
||||
|
|
2
Makefile
2
Makefile
|
@ -4,7 +4,7 @@ CLIENT_ANDROID_PATH ?= ../anytype-kotlin
|
|||
CLIENT_IOS_PATH ?= ../anytype-swift
|
||||
BUILD_FLAGS ?=
|
||||
|
||||
export GOLANGCI_LINT_VERSION=v1.54.2
|
||||
export GOLANGCI_LINT_VERSION=1.58.1
|
||||
export CGO_CFLAGS=-Wno-deprecated-non-prototype -Wno-unknown-warning-option -Wno-deprecated-declarations -Wno-xor-used-as-pow -Wno-single-bit-bitfield-constant-conversion
|
||||
|
||||
ifndef $(GOPATH)
|
||||
|
|
|
@ -25,306 +25,308 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
|||
func init() { proto.RegisterFile("pb/protos/service/service.proto", fileDescriptor_93a29dc403579097) }
|
||||
|
||||
var fileDescriptor_93a29dc403579097 = []byte{
|
||||
// 4771 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x9d, 0xdd, 0x6f, 0x24, 0x49,
|
||||
0x52, 0xc0, 0xb7, 0x5f, 0x58, 0xa8, 0xe3, 0x16, 0xa8, 0x85, 0x65, 0x6f, 0xb9, 0x9b, 0x99, 0x9d,
|
||||
0x9d, 0x6f, 0x8f, 0xdb, 0xde, 0x99, 0xfd, 0x38, 0xf6, 0x90, 0x90, 0xc7, 0x1e, 0x7b, 0xcd, 0xd9,
|
||||
0x1e, 0xe3, 0xb6, 0x67, 0xa4, 0x95, 0x90, 0x48, 0x57, 0xc7, 0xb4, 0x0b, 0x57, 0x57, 0xd6, 0x55,
|
||||
0x65, 0xb7, 0xa7, 0x0f, 0x81, 0x40, 0x20, 0x10, 0x08, 0xc4, 0x89, 0xaf, 0x17, 0x1e, 0x90, 0xf8,
|
||||
0x6b, 0x78, 0x3c, 0xf1, 0xc4, 0x23, 0xda, 0x95, 0xf8, 0x3b, 0x4e, 0x95, 0x95, 0x95, 0x1f, 0x51,
|
||||
0x19, 0x59, 0xe5, 0x7d, 0x9a, 0x51, 0xc7, 0x2f, 0x22, 0x32, 0x2b, 0x23, 0x33, 0x23, 0x3f, 0xaa,
|
||||
0x1c, 0xdd, 0x2c, 0xce, 0x37, 0x8a, 0x92, 0x0b, 0x5e, 0x6d, 0x54, 0x50, 0x2e, 0xd3, 0x04, 0xda,
|
||||
0x7f, 0xc7, 0xf2, 0xe7, 0xf8, 0x6d, 0x96, 0xaf, 0xc4, 0xaa, 0x80, 0x0f, 0xde, 0x37, 0x64, 0xc2,
|
||||
0xe7, 0x73, 0x96, 0x4f, 0xab, 0x06, 0xf9, 0xe0, 0x3d, 0x23, 0x81, 0x25, 0xe4, 0x42, 0xfd, 0xfe,
|
||||
0xe4, 0xff, 0xff, 0x67, 0x14, 0xbd, 0xb3, 0x9d, 0xa5, 0x90, 0x8b, 0x6d, 0xa5, 0x11, 0x7f, 0x15,
|
||||
0x7d, 0x77, 0xab, 0x28, 0xf6, 0x40, 0xbc, 0x84, 0xb2, 0x4a, 0x79, 0x1e, 0x7f, 0x34, 0x56, 0x0e,
|
||||
0xc6, 0x27, 0x45, 0x32, 0xde, 0x2a, 0x8a, 0xb1, 0x11, 0x8e, 0x4f, 0xe0, 0x27, 0x0b, 0xa8, 0xc4,
|
||||
0x07, 0x77, 0xc2, 0x50, 0x55, 0xf0, 0xbc, 0x82, 0xf8, 0x75, 0xf4, 0x1b, 0x5b, 0x45, 0x31, 0x01,
|
||||
0xb1, 0x03, 0x75, 0x05, 0x26, 0x82, 0x09, 0x88, 0xef, 0x77, 0x54, 0x5d, 0x40, 0xfb, 0x78, 0xd0,
|
||||
0x0f, 0x2a, 0x3f, 0xa7, 0xd1, 0x77, 0x6a, 0x3f, 0x17, 0x0b, 0x31, 0xe5, 0x57, 0x79, 0xfc, 0x61,
|
||||
0x57, 0x51, 0x89, 0xb4, 0xed, 0xdb, 0x21, 0x44, 0x59, 0x7d, 0x15, 0xfd, 0xea, 0x2b, 0x96, 0x65,
|
||||
0x20, 0xb6, 0x4b, 0xa8, 0x0b, 0xee, 0xea, 0x34, 0xa2, 0x71, 0x23, 0xd3, 0x76, 0x3f, 0x0a, 0x32,
|
||||
0xca, 0xf0, 0x57, 0xd1, 0x77, 0x1b, 0xc9, 0x09, 0x24, 0x7c, 0x09, 0x65, 0xec, 0xd5, 0x52, 0x42,
|
||||
0xe2, 0x91, 0x77, 0x20, 0x6c, 0x7b, 0x9b, 0xe7, 0x4b, 0x28, 0x85, 0xdf, 0xb6, 0x12, 0x86, 0x6d,
|
||||
0x1b, 0x48, 0xd9, 0xfe, 0xbb, 0x51, 0xf4, 0xfd, 0xad, 0x24, 0xe1, 0x8b, 0x5c, 0x1c, 0xf0, 0x84,
|
||||
0x65, 0x07, 0x69, 0x7e, 0x79, 0x04, 0x57, 0xdb, 0x17, 0x35, 0x9f, 0xcf, 0x20, 0x7e, 0xea, 0x3e,
|
||||
0xd5, 0x06, 0x1d, 0x6b, 0x76, 0x6c, 0xc3, 0xda, 0xf7, 0x27, 0xd7, 0x53, 0x52, 0x65, 0xf9, 0xa7,
|
||||
0x51, 0x74, 0x03, 0x97, 0x65, 0xc2, 0xb3, 0x25, 0x98, 0xd2, 0x7c, 0xda, 0x63, 0xd8, 0xc5, 0x75,
|
||||
0x79, 0x3e, 0xbb, 0xae, 0x9a, 0x2a, 0x51, 0x16, 0xbd, 0x6b, 0x87, 0xcb, 0x04, 0x2a, 0xd9, 0x9d,
|
||||
0x1e, 0xd2, 0x11, 0xa1, 0x10, 0xed, 0xf9, 0xd1, 0x10, 0x54, 0x79, 0x4b, 0xa3, 0x58, 0x79, 0xcb,
|
||||
0x78, 0xa5, 0x9d, 0x3d, 0xf0, 0x5a, 0xb0, 0x08, 0xed, 0xeb, 0xe1, 0x00, 0x52, 0xb9, 0xfa, 0xe3,
|
||||
0xe8, 0xd7, 0x5e, 0xf1, 0xf2, 0xb2, 0x2a, 0x58, 0x02, 0xaa, 0x2b, 0xdc, 0x75, 0xb5, 0x5b, 0x29,
|
||||
0xee, 0x0d, 0xf7, 0xfa, 0x30, 0x2b, 0x68, 0x5b, 0xe1, 0x8b, 0x02, 0xf0, 0x18, 0x64, 0x14, 0x6b,
|
||||
0x21, 0x15, 0xb4, 0x18, 0x52, 0xb6, 0x2f, 0xa3, 0xd8, 0xd8, 0x3e, 0xff, 0x13, 0x48, 0xc4, 0xd6,
|
||||
0x74, 0x8a, 0x5b, 0xc5, 0xe8, 0x4a, 0x62, 0xbc, 0x35, 0x9d, 0x52, 0xad, 0xe2, 0x47, 0x95, 0xb3,
|
||||
0xab, 0xe8, 0x3d, 0xe4, 0xec, 0x20, 0xad, 0xa4, 0xc3, 0xf5, 0xb0, 0x15, 0x85, 0x69, 0xa7, 0xe3,
|
||||
0xa1, 0xb8, 0x72, 0xfc, 0x17, 0xa3, 0xe8, 0x7b, 0x1e, 0xcf, 0x27, 0x30, 0xe7, 0x4b, 0x88, 0x37,
|
||||
0xfb, 0xad, 0x35, 0xa4, 0xf6, 0xff, 0xf1, 0x35, 0x34, 0x3c, 0x61, 0x32, 0x81, 0x0c, 0x12, 0x41,
|
||||
0x86, 0x49, 0x23, 0xee, 0x0d, 0x13, 0x8d, 0x59, 0x3d, 0xac, 0x15, 0xee, 0x81, 0xd8, 0x5e, 0x94,
|
||||
0x25, 0xe4, 0x82, 0x6c, 0x4b, 0x83, 0xf4, 0xb6, 0xa5, 0x83, 0x7a, 0xea, 0xb3, 0x07, 0x62, 0x2b,
|
||||
0xcb, 0xc8, 0xfa, 0x34, 0xe2, 0xde, 0xfa, 0x68, 0x4c, 0x79, 0x48, 0xa2, 0x5f, 0xb7, 0x9e, 0x98,
|
||||
0xd8, 0xcf, 0x5f, 0xf3, 0x98, 0x7e, 0x16, 0x52, 0xae, 0x7d, 0xdc, 0xef, 0xe5, 0x3c, 0xd5, 0x78,
|
||||
0xfe, 0xa6, 0xe0, 0x25, 0xdd, 0x2c, 0x8d, 0xb8, 0xb7, 0x1a, 0x1a, 0x53, 0x1e, 0xfe, 0x28, 0x7a,
|
||||
0x47, 0x8d, 0x92, 0xed, 0x7c, 0x76, 0xc7, 0x3b, 0x84, 0xe2, 0x09, 0xed, 0x6e, 0x0f, 0x65, 0x06,
|
||||
0x07, 0x25, 0x53, 0x83, 0xcf, 0x47, 0x5e, 0x3d, 0x34, 0xf4, 0xdc, 0x09, 0x43, 0x1d, 0xdb, 0x3b,
|
||||
0x90, 0x01, 0x69, 0xbb, 0x11, 0xf6, 0xd8, 0xd6, 0x90, 0xb2, 0x5d, 0x46, 0xbf, 0xa5, 0x1f, 0x4b,
|
||||
0x3d, 0x8f, 0x4a, 0x79, 0x3d, 0x48, 0xaf, 0x11, 0xf5, 0xb6, 0x21, 0xed, 0xeb, 0xf1, 0x30, 0xb8,
|
||||
0x53, 0x1f, 0xd5, 0x03, 0xfd, 0xf5, 0x41, 0xfd, 0xef, 0x4e, 0x18, 0x52, 0xb6, 0xff, 0x7e, 0x14,
|
||||
0xfd, 0x40, 0xc9, 0x9e, 0xe7, 0xec, 0x3c, 0x03, 0x39, 0x25, 0x1e, 0x81, 0xb8, 0xe2, 0xe5, 0xe5,
|
||||
0x64, 0x95, 0x27, 0xc4, 0xf4, 0xef, 0x87, 0x7b, 0xa6, 0x7f, 0x52, 0xc9, 0xca, 0xf8, 0x54, 0x45,
|
||||
0x05, 0x2f, 0x70, 0xc6, 0xd7, 0xd6, 0x40, 0xf0, 0x82, 0xca, 0xf8, 0x5c, 0xa4, 0x63, 0xf5, 0xb0,
|
||||
0x1e, 0x36, 0xfd, 0x56, 0x0f, 0xed, 0x71, 0xf2, 0x76, 0x08, 0x31, 0xc3, 0x56, 0x1b, 0xc0, 0x3c,
|
||||
0x7f, 0x9d, 0xce, 0xce, 0x8a, 0x69, 0x1d, 0xc6, 0x0f, 0xfd, 0x11, 0x6a, 0x21, 0xc4, 0xb0, 0x45,
|
||||
0xa0, 0xca, 0xdb, 0x3f, 0x9a, 0xc4, 0x48, 0x75, 0xa5, 0xdd, 0x92, 0xcf, 0x0f, 0x60, 0xc6, 0x92,
|
||||
0x95, 0xea, 0xff, 0x9f, 0x84, 0x3a, 0x1e, 0xa6, 0x75, 0x21, 0x3e, 0xbd, 0xa6, 0x96, 0x2a, 0xcf,
|
||||
0x7f, 0x8e, 0xa2, 0x3b, 0x6d, 0xf5, 0x2f, 0x58, 0x3e, 0x03, 0xd5, 0x9e, 0x4d, 0xe9, 0xb7, 0xf2,
|
||||
0xe9, 0x09, 0x54, 0x82, 0x95, 0x22, 0xfe, 0xc2, 0x5f, 0xc9, 0x90, 0x8e, 0x2e, 0xdb, 0x8f, 0xbe,
|
||||
0x95, 0xae, 0x69, 0xf5, 0x49, 0x3d, 0xb0, 0xa9, 0x21, 0xc0, 0x6d, 0x75, 0x29, 0xc1, 0x03, 0xc0,
|
||||
0xed, 0x10, 0x62, 0x5a, 0x5d, 0x0a, 0xf6, 0xf3, 0x65, 0x2a, 0x60, 0x0f, 0x72, 0x28, 0xbb, 0xad,
|
||||
0xde, 0xa8, 0xba, 0x08, 0xd1, 0xea, 0x04, 0x6a, 0x06, 0x1b, 0xc7, 0x9b, 0x9e, 0x1c, 0xd7, 0x02,
|
||||
0x46, 0x3a, 0xd3, 0xe3, 0xe3, 0x61, 0xb0, 0x59, 0xdd, 0x59, 0x3e, 0x4f, 0x60, 0xc9, 0x2f, 0xf1,
|
||||
0xea, 0xce, 0x36, 0xd1, 0x00, 0xc4, 0xea, 0xce, 0x0b, 0x9a, 0x19, 0xcc, 0xf2, 0xf3, 0x32, 0x85,
|
||||
0x2b, 0x34, 0x83, 0xd9, 0xca, 0xb5, 0x98, 0x98, 0xc1, 0x3c, 0x98, 0xf2, 0x70, 0x14, 0xfd, 0x8a,
|
||||
0x14, 0xfe, 0x01, 0x4f, 0xf3, 0xf8, 0xa6, 0x47, 0xa9, 0x16, 0x68, 0xab, 0xb7, 0x68, 0x00, 0x95,
|
||||
0xb8, 0xfe, 0x75, 0x9b, 0xe5, 0x09, 0x64, 0xde, 0x12, 0x1b, 0x71, 0xb0, 0xc4, 0x0e, 0x66, 0x52,
|
||||
0x07, 0x29, 0xac, 0xc7, 0xaf, 0xc9, 0x05, 0x2b, 0xd3, 0x7c, 0x16, 0xfb, 0x74, 0x2d, 0x39, 0x91,
|
||||
0x3a, 0xf8, 0x38, 0x14, 0xc2, 0x4a, 0x71, 0xab, 0x28, 0xca, 0x7a, 0x58, 0xf4, 0x85, 0xb0, 0x8b,
|
||||
0x04, 0x43, 0xb8, 0x83, 0xfa, 0xbd, 0xed, 0x40, 0x92, 0xa5, 0x79, 0xd0, 0x9b, 0x42, 0x86, 0x78,
|
||||
0x33, 0x28, 0x0a, 0xde, 0x03, 0x60, 0x4b, 0x68, 0x6b, 0xe6, 0x7b, 0x32, 0x36, 0x10, 0x0c, 0x5e,
|
||||
0x04, 0x9a, 0x75, 0x9a, 0x14, 0x1f, 0xb2, 0x4b, 0xa8, 0x1f, 0x30, 0xd4, 0xf3, 0x5a, 0xec, 0xd3,
|
||||
0x77, 0x08, 0x62, 0x9d, 0xe6, 0x27, 0x95, 0xab, 0x45, 0xf4, 0x9e, 0x94, 0x1f, 0xb3, 0x52, 0xa4,
|
||||
0x49, 0x5a, 0xb0, 0xbc, 0xcd, 0xff, 0x7d, 0xfd, 0xba, 0x43, 0x69, 0x97, 0xeb, 0x03, 0x69, 0xe5,
|
||||
0xf6, 0xdf, 0x47, 0xd1, 0x87, 0xd8, 0xef, 0x31, 0x94, 0xf3, 0x54, 0x2e, 0x23, 0xab, 0x66, 0x10,
|
||||
0x8e, 0x3f, 0x0f, 0x1b, 0xed, 0x28, 0xe8, 0xd2, 0xfc, 0xf0, 0xfa, 0x8a, 0xaa, 0x60, 0x7f, 0x18,
|
||||
0x45, 0xcd, 0x72, 0x45, 0x2e, 0x29, 0xdd, 0x5e, 0xab, 0xd6, 0x31, 0xce, 0x7a, 0xf2, 0xc3, 0x00,
|
||||
0x61, 0xa6, 0x8a, 0xe6, 0x77, 0xb9, 0x52, 0x8e, 0xbd, 0x1a, 0x52, 0x44, 0x4c, 0x15, 0x08, 0xc1,
|
||||
0x05, 0x9d, 0x5c, 0xf0, 0x2b, 0x7f, 0x41, 0x6b, 0x49, 0xb8, 0xa0, 0x8a, 0x30, 0x7b, 0x57, 0xaa,
|
||||
0xa0, 0xbe, 0xbd, 0xab, 0xb6, 0x18, 0xa1, 0xbd, 0x2b, 0xcc, 0x28, 0xc3, 0x3c, 0xfa, 0x4d, 0xdb,
|
||||
0xf0, 0x33, 0xce, 0x2f, 0xe7, 0xac, 0xbc, 0x8c, 0x1f, 0xd1, 0xca, 0x2d, 0xa3, 0x1d, 0xad, 0x0d,
|
||||
0x62, 0xcd, 0xb0, 0x60, 0x3b, 0xac, 0x13, 0x8d, 0xb3, 0x32, 0x43, 0xc3, 0x82, 0x63, 0x43, 0x21,
|
||||
0xc4, 0xb0, 0x40, 0xa0, 0x66, 0xe4, 0xb6, 0xbd, 0x4d, 0x00, 0xaf, 0x96, 0x1c, 0xf5, 0x09, 0x50,
|
||||
0xab, 0x25, 0x0f, 0x86, 0x43, 0x68, 0xaf, 0x64, 0xc5, 0x85, 0x3f, 0x84, 0xa4, 0x28, 0x1c, 0x42,
|
||||
0x2d, 0x82, 0xdb, 0x7b, 0x02, 0xac, 0x4c, 0x2e, 0xfc, 0xed, 0xdd, 0xc8, 0xc2, 0xed, 0xad, 0x19,
|
||||
0x93, 0x58, 0xd8, 0x86, 0x27, 0x8b, 0xf3, 0x2a, 0x29, 0xd3, 0x73, 0x88, 0xd7, 0x68, 0x6d, 0x0d,
|
||||
0x11, 0x89, 0x05, 0x09, 0x9b, 0x31, 0x53, 0xf9, 0x6c, 0x65, 0xfb, 0xd3, 0x0a, 0x8d, 0x99, 0xad,
|
||||
0x0d, 0x8b, 0x20, 0xc6, 0x4c, 0x3f, 0x89, 0xab, 0xb7, 0x57, 0xf2, 0x45, 0x51, 0xf5, 0x54, 0x0f,
|
||||
0x41, 0xe1, 0xea, 0x75, 0x61, 0xe5, 0xf3, 0x4d, 0xf4, 0xdb, 0xf6, 0x23, 0x3d, 0xcb, 0x2b, 0xed,
|
||||
0x75, 0x9d, 0x7e, 0x4e, 0x16, 0x46, 0xec, 0x12, 0x05, 0x70, 0x93, 0x35, 0xb4, 0x9e, 0xc5, 0x0e,
|
||||
0x08, 0x96, 0x66, 0x55, 0x7c, 0xcf, 0x6f, 0xa3, 0x95, 0x13, 0x59, 0x83, 0x8f, 0xc3, 0x5d, 0x68,
|
||||
0x67, 0x51, 0x64, 0x69, 0xd2, 0xdd, 0x2e, 0x54, 0xba, 0x5a, 0x1c, 0xee, 0x42, 0x36, 0x86, 0x87,
|
||||
0x84, 0x09, 0x88, 0xe6, 0x3f, 0xa7, 0xab, 0x02, 0xfc, 0x43, 0x82, 0x83, 0x84, 0x87, 0x04, 0x8c,
|
||||
0xe2, 0xfa, 0x4c, 0x40, 0x1c, 0xb0, 0x15, 0x5f, 0x10, 0x43, 0x82, 0x16, 0x87, 0xeb, 0x63, 0x63,
|
||||
0x66, 0xe2, 0xd6, 0x1e, 0xf6, 0x73, 0x01, 0x65, 0xce, 0xb2, 0xdd, 0x8c, 0xcd, 0xaa, 0x98, 0xe8,
|
||||
0x37, 0x2e, 0x45, 0x4c, 0xdc, 0x34, 0xed, 0x79, 0x8c, 0xfb, 0xd5, 0x2e, 0x5b, 0xf2, 0x32, 0x15,
|
||||
0xf4, 0x63, 0x34, 0x48, 0xef, 0x63, 0x74, 0x50, 0xaf, 0xb7, 0xad, 0x32, 0xb9, 0x48, 0x97, 0x30,
|
||||
0x0d, 0x78, 0x6b, 0x91, 0x01, 0xde, 0x2c, 0xd4, 0xd3, 0x68, 0x13, 0xbe, 0x28, 0x13, 0x20, 0x1b,
|
||||
0xad, 0x11, 0xf7, 0x36, 0x9a, 0xc6, 0x94, 0x87, 0xbf, 0x1e, 0x45, 0xbf, 0xd3, 0x48, 0xed, 0x3d,
|
||||
0xbc, 0x1d, 0x56, 0x5d, 0x9c, 0x73, 0x56, 0x4e, 0xe3, 0x8f, 0x7d, 0x76, 0xbc, 0xa8, 0x76, 0xfd,
|
||||
0xe4, 0x3a, 0x2a, 0xf8, 0xb1, 0x1e, 0xa4, 0x95, 0xd5, 0xe3, 0xbc, 0x8f, 0xd5, 0x41, 0xc2, 0x8f,
|
||||
0x15, 0xa3, 0x78, 0x00, 0x91, 0xf2, 0x66, 0xbd, 0x7c, 0x8f, 0xd4, 0x77, 0x17, 0xcd, 0xf7, 0x7b,
|
||||
0x39, 0x3c, 0x3e, 0xd6, 0x42, 0x37, 0x5a, 0xd6, 0x29, 0x1b, 0xfe, 0x88, 0x19, 0x0f, 0xc5, 0x49,
|
||||
0xcf, 0xba, 0x57, 0x84, 0x3d, 0x77, 0x7a, 0xc6, 0x78, 0x28, 0x4e, 0x78, 0xb6, 0x86, 0xb5, 0x90,
|
||||
0x67, 0xcf, 0xd0, 0x36, 0x1e, 0x8a, 0xe3, 0x84, 0x4e, 0x31, 0xed, 0xbc, 0xf0, 0x28, 0x60, 0x07,
|
||||
0xcf, 0x0d, 0x6b, 0x83, 0x58, 0x1c, 0xb1, 0x5b, 0x45, 0x91, 0xad, 0x4e, 0x61, 0x5e, 0x64, 0x64,
|
||||
0xc4, 0x3a, 0x48, 0x38, 0x62, 0x31, 0x8a, 0xd3, 0xad, 0x53, 0x5e, 0x27, 0x73, 0xde, 0x74, 0x4b,
|
||||
0x8a, 0xc2, 0xe9, 0x56, 0x8b, 0xe0, 0x0c, 0xe5, 0x94, 0x6f, 0xf3, 0x2c, 0x83, 0x44, 0x74, 0x4f,
|
||||
0xdf, 0xb4, 0xa6, 0x21, 0xc2, 0x19, 0x0a, 0x22, 0xcd, 0x42, 0xb5, 0x5d, 0x1c, 0xb0, 0x12, 0x9e,
|
||||
0xad, 0x0e, 0xd2, 0xfc, 0x32, 0xf6, 0x4f, 0xc6, 0x06, 0x20, 0x16, 0xaa, 0x5e, 0x10, 0x2f, 0x42,
|
||||
0xce, 0xf2, 0x29, 0xf7, 0x2f, 0x42, 0x6a, 0x49, 0x78, 0x11, 0xa2, 0x08, 0x6c, 0xf2, 0x04, 0x28,
|
||||
0x93, 0xb5, 0x24, 0x6c, 0x52, 0x11, 0xbe, 0x01, 0x48, 0x6d, 0x67, 0x92, 0x03, 0x10, 0xda, 0xc0,
|
||||
0xbc, 0xdf, 0xcb, 0xe1, 0x08, 0x6d, 0x57, 0x23, 0xbb, 0x20, 0x92, 0x0b, 0x7f, 0x84, 0x3a, 0x48,
|
||||
0x38, 0x42, 0x31, 0x8a, 0xab, 0x74, 0xca, 0xf5, 0x6a, 0xea, 0x9e, 0x3f, 0x3e, 0x3a, 0x2b, 0xa9,
|
||||
0xfb, 0xbd, 0x1c, 0x5e, 0x1f, 0xec, 0xcf, 0xe5, 0x33, 0xf3, 0x06, 0x79, 0x23, 0x0b, 0xaf, 0x0f,
|
||||
0x34, 0x83, 0x4b, 0xdf, 0x08, 0xea, 0xc7, 0xe9, 0x2f, 0xbd, 0x91, 0x87, 0x4b, 0xef, 0x70, 0xca,
|
||||
0xc9, 0xbf, 0x8e, 0xa2, 0x9b, 0xb6, 0x97, 0x23, 0x5e, 0xf7, 0x91, 0x97, 0x2c, 0x4b, 0xa7, 0x4c,
|
||||
0xc0, 0x29, 0xbf, 0x84, 0x1c, 0x6d, 0x30, 0xb8, 0xa5, 0x6d, 0xf8, 0xb1, 0xa3, 0x40, 0x6c, 0x30,
|
||||
0x0c, 0x52, 0xc4, 0x71, 0xd2, 0xd0, 0x67, 0x15, 0x6c, 0xb3, 0x8a, 0x18, 0xc9, 0x1c, 0x24, 0x1c,
|
||||
0x27, 0x18, 0xc5, 0x59, 0x62, 0x23, 0x7f, 0xfe, 0xa6, 0x80, 0x32, 0x85, 0x3c, 0x01, 0x7f, 0x96,
|
||||
0x88, 0xa9, 0x70, 0x96, 0xe8, 0xa1, 0x3b, 0xeb, 0x6f, 0x3d, 0x38, 0x75, 0x0f, 0xd0, 0x31, 0x11,
|
||||
0x38, 0x40, 0x27, 0x50, 0x5c, 0x49, 0x03, 0x78, 0xf7, 0xb0, 0x3a, 0x56, 0x82, 0x7b, 0x58, 0x34,
|
||||
0xdd, 0xd9, 0xd5, 0xd0, 0xcc, 0xa4, 0xee, 0x26, 0x3d, 0x45, 0x9f, 0xd8, 0xdd, 0x65, 0x6d, 0x10,
|
||||
0xeb, 0xdf, 0x46, 0x39, 0x81, 0x8c, 0xc9, 0x29, 0x24, 0xb0, 0x57, 0xd1, 0x32, 0x43, 0xb6, 0x51,
|
||||
0x2c, 0x56, 0x39, 0xfc, 0xcb, 0x51, 0xf4, 0x81, 0xcf, 0xe3, 0x8b, 0x42, 0xfa, 0xdd, 0xec, 0xb7,
|
||||
0xd5, 0x90, 0xc4, 0x0d, 0x81, 0xb0, 0x86, 0x2a, 0xc3, 0x9f, 0x46, 0xef, 0xb7, 0x22, 0x73, 0x81,
|
||||
0x40, 0x15, 0xc0, 0x4d, 0x5b, 0x74, 0xf9, 0x31, 0xa7, 0xdd, 0x6f, 0x0c, 0xe6, 0xcd, 0x8a, 0xc0,
|
||||
0x2d, 0x57, 0x85, 0x56, 0x04, 0xda, 0x86, 0x12, 0x13, 0x2b, 0x02, 0x0f, 0x86, 0x67, 0xea, 0x16,
|
||||
0xa9, 0xfb, 0x89, 0x6f, 0x8c, 0xd3, 0x26, 0xec, 0x5e, 0xf2, 0xa0, 0x1f, 0xc4, 0xb1, 0xd3, 0x8a,
|
||||
0x55, 0x22, 0xfe, 0x28, 0x64, 0x01, 0x25, 0xe3, 0x6b, 0x83, 0x58, 0xe5, 0xf0, 0xcf, 0xa3, 0xef,
|
||||
0x75, 0x2a, 0xb6, 0x0b, 0x4c, 0x2c, 0x4a, 0x98, 0xc6, 0x1b, 0x3d, 0xe5, 0x6e, 0x41, 0xed, 0x7a,
|
||||
0x73, 0xb8, 0x82, 0xf2, 0xff, 0xb7, 0xa3, 0xe8, 0xfb, 0x2e, 0xd7, 0x34, 0xb1, 0x2e, 0xc3, 0x93,
|
||||
0x90, 0x49, 0x97, 0xd5, 0xc5, 0x78, 0x7a, 0x2d, 0x9d, 0xce, 0xa2, 0xcf, 0x0e, 0xe4, 0xad, 0x25,
|
||||
0x4b, 0x33, 0xb9, 0xaf, 0xff, 0x71, 0xc8, 0xa8, 0x83, 0x06, 0x17, 0x7d, 0xa4, 0x4a, 0x67, 0x94,
|
||||
0x94, 0xfd, 0xcd, 0x5a, 0x2c, 0x3c, 0xa6, 0x7b, 0xa5, 0x67, 0xad, 0xb0, 0x3e, 0x90, 0x56, 0x6e,
|
||||
0x45, 0xbb, 0x59, 0x56, 0xff, 0x6c, 0x07, 0xb9, 0xcf, 0xab, 0x52, 0xf5, 0x44, 0xfa, 0xfa, 0x40,
|
||||
0x5a, 0x79, 0xfd, 0xb3, 0xe8, 0xfd, 0xae, 0x57, 0x35, 0x29, 0x6c, 0xf4, 0x9a, 0x42, 0xf3, 0xc2,
|
||||
0xe6, 0x70, 0x05, 0x93, 0xea, 0x7f, 0x99, 0x56, 0x82, 0x97, 0xab, 0xc9, 0x05, 0xbf, 0x6a, 0x2f,
|
||||
0xc9, 0xba, 0xbd, 0x55, 0x01, 0x63, 0x8b, 0x20, 0x52, 0x7d, 0x3f, 0xd9, 0x71, 0x65, 0x2e, 0xd3,
|
||||
0x56, 0x84, 0x2b, 0x8b, 0xe8, 0x71, 0xe5, 0x92, 0x66, 0xac, 0x6a, 0x6b, 0x65, 0x6e, 0xfe, 0xde,
|
||||
0xf7, 0x17, 0xb5, 0x7b, 0xfb, 0xf7, 0x41, 0x3f, 0x68, 0xd2, 0xc3, 0xdd, 0x34, 0x03, 0x79, 0x6c,
|
||||
0xf3, 0xe2, 0xf5, 0xeb, 0x8c, 0xb3, 0x29, 0x4a, 0x0f, 0x6b, 0xf1, 0xd8, 0x96, 0x13, 0xe9, 0xa1,
|
||||
0x8f, 0x33, 0xb7, 0x5e, 0x6a, 0xe9, 0x09, 0x24, 0x3c, 0x4f, 0xd2, 0x0c, 0xdf, 0xe2, 0x91, 0x9a,
|
||||
0x5a, 0x48, 0xdc, 0x7a, 0xe9, 0x40, 0x66, 0xda, 0xa8, 0x45, 0x75, 0x47, 0x6c, 0xcb, 0x7f, 0xb7,
|
||||
0xab, 0x68, 0x89, 0x89, 0x69, 0xc3, 0x83, 0x99, 0x55, 0x52, 0x2d, 0x3c, 0x2b, 0xa4, 0xf1, 0x5b,
|
||||
0x5d, 0xad, 0x46, 0x42, 0xac, 0x92, 0x5c, 0xc2, 0x64, 0xfb, 0xf5, 0xef, 0x3b, 0xfc, 0x2a, 0x97,
|
||||
0x46, 0x6f, 0x77, 0x55, 0x5a, 0x19, 0x91, 0xed, 0x63, 0x46, 0x19, 0xfe, 0x71, 0xf4, 0xcb, 0xd2,
|
||||
0x70, 0xc9, 0x8b, 0xf8, 0x86, 0x47, 0xa1, 0xb4, 0x2e, 0xdc, 0xdc, 0x24, 0xe5, 0xe6, 0xde, 0x98,
|
||||
0x8e, 0x8d, 0xb3, 0x8a, 0xcd, 0x20, 0xbe, 0x43, 0xb4, 0xb8, 0x94, 0x12, 0xf7, 0xc6, 0xba, 0x94,
|
||||
0x1b, 0x15, 0x47, 0x7c, 0xaa, 0xac, 0x7b, 0x6a, 0xa8, 0x85, 0xa1, 0xa8, 0xb0, 0x21, 0x73, 0x6c,
|
||||
0x70, 0xc4, 0x96, 0xe9, 0x4c, 0x4f, 0x01, 0xcd, 0x48, 0x52, 0xa1, 0x63, 0x03, 0xc3, 0x8c, 0x2d,
|
||||
0x88, 0x38, 0x36, 0x20, 0x61, 0xe5, 0xf3, 0x5f, 0x46, 0xd1, 0x2d, 0xc3, 0xec, 0xb5, 0xbb, 0x39,
|
||||
0xfb, 0xf9, 0x6b, 0xfe, 0x2a, 0x15, 0x17, 0xf5, 0x6a, 0xbe, 0x8a, 0x3f, 0xa3, 0x4c, 0xfa, 0x79,
|
||||
0x5d, 0x94, 0xcf, 0xaf, 0xad, 0x67, 0x72, 0xba, 0x76, 0xd3, 0xc5, 0x1c, 0xa9, 0x35, 0x1a, 0x28,
|
||||
0xa7, 0xd3, 0x7b, 0x33, 0x98, 0x23, 0x72, 0xba, 0x10, 0x6f, 0x9a, 0x58, 0x3b, 0xcf, 0x78, 0x8e,
|
||||
0x9b, 0xd8, 0x58, 0xa8, 0x85, 0x44, 0x13, 0x77, 0x20, 0x33, 0x42, 0xb6, 0xa2, 0x66, 0x7f, 0x60,
|
||||
0x2b, 0xcb, 0xd0, 0x08, 0xa9, 0x55, 0x35, 0x40, 0x8c, 0x90, 0x5e, 0x50, 0xf9, 0x39, 0x89, 0xbe,
|
||||
0x53, 0x3f, 0xd2, 0xe3, 0x12, 0x96, 0x29, 0xe0, 0xd3, 0x5f, 0x4b, 0x42, 0xf4, 0x7f, 0x97, 0x30,
|
||||
0x3d, 0xeb, 0x2c, 0xaf, 0x8a, 0x8c, 0x55, 0x17, 0xea, 0x3c, 0xd0, 0xad, 0x73, 0x2b, 0xc4, 0x27,
|
||||
0x82, 0x77, 0x7b, 0x28, 0x33, 0xa8, 0xb7, 0x32, 0x3d, 0xc4, 0xdc, 0xf3, 0xab, 0x76, 0x86, 0x99,
|
||||
0xfb, 0xbd, 0x9c, 0xd9, 0x11, 0xdd, 0x63, 0x59, 0x06, 0xe5, 0xaa, 0x95, 0x1d, 0xb2, 0x3c, 0x7d,
|
||||
0x0d, 0x95, 0x40, 0x3b, 0xa2, 0x8a, 0x1a, 0x63, 0x8c, 0xd8, 0x11, 0x0d, 0xe0, 0x26, 0xbf, 0x46,
|
||||
0x9e, 0xf7, 0xf3, 0x29, 0xbc, 0x41, 0xf9, 0x35, 0xb6, 0x23, 0x19, 0x22, 0xbf, 0xa6, 0x58, 0xb3,
|
||||
0x47, 0xf9, 0x2c, 0xe3, 0xc9, 0xa5, 0x9a, 0x02, 0xdc, 0x06, 0x96, 0x12, 0x3c, 0x07, 0xdc, 0x0e,
|
||||
0x21, 0x66, 0x12, 0x90, 0x82, 0x13, 0x28, 0x32, 0x96, 0xe0, 0x2b, 0x00, 0x8d, 0x8e, 0x92, 0x11,
|
||||
0x93, 0x00, 0x66, 0x50, 0x71, 0xd5, 0xd5, 0x02, 0x5f, 0x71, 0xd1, 0xcd, 0x82, 0xdb, 0x21, 0xc4,
|
||||
0x4c, 0x83, 0x52, 0x30, 0x29, 0xb2, 0x54, 0xa0, 0x6e, 0xd0, 0x68, 0x48, 0x09, 0xd1, 0x0d, 0x5c,
|
||||
0x02, 0x99, 0x3c, 0x84, 0x72, 0x06, 0x5e, 0x93, 0x52, 0x12, 0x34, 0xd9, 0x12, 0xe6, 0xa6, 0x58,
|
||||
0x53, 0x77, 0x5e, 0xac, 0xd0, 0x4d, 0x31, 0x55, 0x2d, 0x5e, 0xac, 0x88, 0x9b, 0x62, 0x0e, 0x80,
|
||||
0x8a, 0x78, 0xcc, 0x2a, 0xe1, 0x2f, 0xa2, 0x94, 0x04, 0x8b, 0xd8, 0x12, 0x66, 0x8e, 0x6e, 0x8a,
|
||||
0xb8, 0x10, 0x68, 0x8e, 0x56, 0x05, 0xb0, 0x4e, 0x28, 0x6f, 0x92, 0x72, 0x33, 0x92, 0x34, 0xad,
|
||||
0x02, 0x62, 0x37, 0x85, 0x6c, 0x5a, 0xa1, 0x91, 0x44, 0x3d, 0xf7, 0x56, 0x4a, 0x8c, 0x24, 0x5d,
|
||||
0x0a, 0x85, 0x92, 0xda, 0xc9, 0xf5, 0xd5, 0x0e, 0x6d, 0xe2, 0xde, 0x0e, 0x21, 0x66, 0x7c, 0x6a,
|
||||
0x0b, 0xbd, 0xcd, 0xca, 0x32, 0xad, 0x27, 0xff, 0x7b, 0xfe, 0x02, 0xb5, 0x72, 0x62, 0x7c, 0xf2,
|
||||
0x71, 0xa8, 0x7b, 0xb5, 0x03, 0xb7, 0xaf, 0x60, 0x78, 0xe8, 0xfe, 0x28, 0xc8, 0x98, 0x8c, 0x53,
|
||||
0x4a, 0xac, 0x23, 0x36, 0xdf, 0xd3, 0xf4, 0x9c, 0xb0, 0xdd, 0xeb, 0xc3, 0xac, 0x9b, 0xdc, 0xda,
|
||||
0xc5, 0x21, 0x5f, 0xc2, 0x29, 0x7f, 0xfe, 0x26, 0xad, 0x44, 0x9a, 0xcf, 0xd4, 0xcc, 0xfd, 0x94,
|
||||
0xb0, 0xe4, 0x83, 0x89, 0x9b, 0xdc, 0xbd, 0x4a, 0x26, 0x81, 0x40, 0x65, 0x39, 0x82, 0x2b, 0x6f,
|
||||
0x02, 0x81, 0x2d, 0x6a, 0x8e, 0x48, 0x20, 0x42, 0xbc, 0xd9, 0xd9, 0xd0, 0xce, 0xd5, 0xeb, 0x6e,
|
||||
0xa7, 0xbc, 0xcd, 0xe5, 0x28, 0x6b, 0x18, 0x24, 0x16, 0x97, 0x41, 0x05, 0xb3, 0xe2, 0xd3, 0xfe,
|
||||
0x4d, 0x17, 0x7b, 0x40, 0xd8, 0xe9, 0x76, 0xb3, 0x87, 0x03, 0x48, 0x8f, 0x2b, 0x73, 0x4e, 0x4c,
|
||||
0xb9, 0xea, 0x1e, 0x13, 0x3f, 0x1c, 0x40, 0x5a, 0xbb, 0x24, 0x76, 0xb5, 0x9e, 0xb1, 0xe4, 0x72,
|
||||
0x56, 0xf2, 0x45, 0x3e, 0xdd, 0xe6, 0x19, 0x2f, 0xd1, 0x2e, 0x89, 0x53, 0x6a, 0x84, 0x12, 0xbb,
|
||||
0x24, 0x3d, 0x2a, 0x26, 0x83, 0xb3, 0x4b, 0xb1, 0x95, 0xa5, 0x33, 0xbc, 0xc6, 0x75, 0x0c, 0x49,
|
||||
0x80, 0xc8, 0xe0, 0xbc, 0xa0, 0x27, 0x88, 0x9a, 0x35, 0xb0, 0x48, 0x13, 0x96, 0x35, 0xfe, 0x36,
|
||||
0x68, 0x33, 0x0e, 0xd8, 0x1b, 0x44, 0x1e, 0x05, 0x4f, 0x3d, 0x4f, 0x17, 0x65, 0xbe, 0x9f, 0x0b,
|
||||
0x4e, 0xd6, 0xb3, 0x05, 0x7a, 0xeb, 0x69, 0x81, 0x68, 0x58, 0x3d, 0x85, 0x37, 0x75, 0x69, 0xea,
|
||||
0x7f, 0x7c, 0xc3, 0x6a, 0xfd, 0xfb, 0x58, 0xc9, 0x43, 0xc3, 0x2a, 0xe2, 0x50, 0x65, 0x94, 0x93,
|
||||
0x26, 0x60, 0x02, 0xda, 0x6e, 0x98, 0x3c, 0xe8, 0x07, 0xfd, 0x7e, 0x26, 0x62, 0x95, 0x41, 0xc8,
|
||||
0x8f, 0x04, 0x86, 0xf8, 0x69, 0x41, 0x73, 0x7c, 0xe2, 0xd4, 0xe7, 0x02, 0x92, 0xcb, 0xce, 0xb5,
|
||||
0x17, 0xb7, 0xa0, 0x0d, 0x42, 0x1c, 0x9f, 0x10, 0xa8, 0xbf, 0x89, 0xf6, 0x13, 0x9e, 0x87, 0x9a,
|
||||
0xa8, 0x96, 0x0f, 0x69, 0x22, 0xc5, 0x99, 0xc5, 0xaf, 0x96, 0xaa, 0xc8, 0x6c, 0x9a, 0x69, 0x8d,
|
||||
0xb0, 0x60, 0x43, 0xc4, 0xe2, 0x97, 0x84, 0x4d, 0x4e, 0x8e, 0x7d, 0x1e, 0x76, 0xaf, 0x9d, 0x76,
|
||||
0xac, 0x1c, 0xd2, 0xd7, 0x4e, 0x29, 0x96, 0xae, 0x64, 0x13, 0x23, 0x3d, 0x56, 0xdc, 0x38, 0x79,
|
||||
0x3c, 0x0c, 0x36, 0x4b, 0x1e, 0xc7, 0xe7, 0x76, 0x06, 0xac, 0x6c, 0xbc, 0xae, 0x07, 0x0c, 0x19,
|
||||
0x8c, 0x58, 0xf2, 0x04, 0x70, 0x34, 0x84, 0x39, 0x9e, 0xb7, 0x79, 0x2e, 0x20, 0x17, 0xbe, 0x21,
|
||||
0xcc, 0x35, 0xa6, 0xc0, 0xd0, 0x10, 0x46, 0x29, 0xa0, 0xb8, 0x95, 0xfb, 0x41, 0x20, 0x8e, 0xd8,
|
||||
0xdc, 0x9b, 0xb1, 0x35, 0x7b, 0x3d, 0x8d, 0x3c, 0x14, 0xb7, 0x88, 0xb3, 0x8e, 0xc0, 0x6c, 0x2f,
|
||||
0xa7, 0xac, 0x9c, 0xe9, 0xdd, 0x8d, 0x69, 0xbc, 0x49, 0xdb, 0x71, 0x49, 0xe2, 0x08, 0x2c, 0xac,
|
||||
0x81, 0x86, 0x9d, 0xfd, 0x39, 0x9b, 0xe9, 0x9a, 0x7a, 0x6a, 0x20, 0xe5, 0x9d, 0xaa, 0x3e, 0xe8,
|
||||
0x07, 0x91, 0x9f, 0x97, 0xe9, 0x14, 0x78, 0xc0, 0x8f, 0x94, 0x0f, 0xf1, 0x83, 0x41, 0x94, 0xbd,
|
||||
0xd5, 0xf5, 0x6e, 0x56, 0x74, 0x5b, 0xf9, 0x54, 0xad, 0x63, 0xc7, 0xc4, 0xe3, 0x41, 0x5c, 0x28,
|
||||
0x7b, 0x23, 0x78, 0xd4, 0x47, 0xdb, 0x0d, 0xda, 0x50, 0x1f, 0xd5, 0xfb, 0xaf, 0x43, 0xfa, 0xa8,
|
||||
0x0f, 0x56, 0x3e, 0x7f, 0xaa, 0xfa, 0xe8, 0x0e, 0x13, 0xac, 0xce, 0xdb, 0x5f, 0xa6, 0x70, 0xa5,
|
||||
0x16, 0xc2, 0x9e, 0xfa, 0xb6, 0xd4, 0x58, 0xbe, 0x6f, 0x84, 0x56, 0xc5, 0x1b, 0x83, 0xf9, 0x80,
|
||||
0x6f, 0xb5, 0x42, 0xe8, 0xf5, 0x8d, 0x96, 0x0a, 0x1b, 0x83, 0xf9, 0x80, 0x6f, 0xf5, 0x22, 0x63,
|
||||
0xaf, 0x6f, 0xf4, 0x36, 0xe3, 0xc6, 0x60, 0x5e, 0xf9, 0xfe, 0xab, 0xb6, 0xe3, 0xda, 0xce, 0xeb,
|
||||
0x3c, 0x2c, 0x11, 0xe9, 0x12, 0x7c, 0xe9, 0xa4, 0x6b, 0x4f, 0xa3, 0xa1, 0x74, 0x92, 0x56, 0xb1,
|
||||
0xbe, 0x7e, 0xe1, 0x2b, 0xc5, 0x31, 0xaf, 0x52, 0x79, 0x84, 0xfd, 0x74, 0x80, 0xd1, 0x16, 0x0e,
|
||||
0x2d, 0x9a, 0x42, 0x4a, 0xe6, 0x00, 0xd0, 0x41, 0xcd, 0x2d, 0xd7, 0xc7, 0x01, 0x7b, 0xdd, 0xcb,
|
||||
0xae, 0xeb, 0x03, 0x69, 0x73, 0x14, 0xe7, 0x30, 0xf6, 0x19, 0x60, 0xa8, 0x55, 0xbd, 0xc7, 0x80,
|
||||
0x9b, 0xc3, 0x15, 0x94, 0xfb, 0xbf, 0x69, 0xd7, 0x15, 0xd8, 0xbf, 0xea, 0x04, 0x4f, 0x86, 0x58,
|
||||
0x44, 0x1d, 0xe1, 0xe9, 0xb5, 0x74, 0x54, 0x41, 0xfe, 0x63, 0x14, 0xdd, 0xf6, 0x16, 0xc4, 0x3d,
|
||||
0x0d, 0xfe, 0xdd, 0x21, 0xb6, 0xfd, 0xa7, 0xc2, 0x5f, 0x7c, 0x1b, 0x55, 0x55, 0xba, 0x7f, 0x68,
|
||||
0x97, 0xf7, 0xad, 0x86, 0x7c, 0x13, 0xe1, 0x45, 0x39, 0x85, 0x52, 0xf5, 0xd8, 0x50, 0xd0, 0x19,
|
||||
0x18, 0xf7, 0xdb, 0x4f, 0xaf, 0xa9, 0x65, 0x7d, 0xa9, 0xc5, 0x81, 0xd5, 0x4b, 0x59, 0x56, 0x79,
|
||||
0x42, 0x96, 0x2d, 0x1a, 0x17, 0xe8, 0xb3, 0xeb, 0xaa, 0x51, 0x3d, 0xd9, 0x82, 0xe5, 0x8b, 0xdf,
|
||||
0x4f, 0x07, 0x1a, 0x76, 0x5e, 0x05, 0xff, 0xe4, 0x7a, 0x4a, 0xaa, 0x2c, 0xff, 0x35, 0x8a, 0xee,
|
||||
0x3a, 0xac, 0x39, 0xed, 0x40, 0x7b, 0x32, 0x3f, 0x0a, 0xd8, 0xa7, 0x94, 0x74, 0xe1, 0x7e, 0xef,
|
||||
0xdb, 0x29, 0x9b, 0xcf, 0x9a, 0x38, 0x2a, 0xbb, 0x69, 0x26, 0xa0, 0xec, 0x7e, 0xd6, 0xc4, 0xb5,
|
||||
0xdb, 0x50, 0x63, 0xfa, 0xb3, 0x26, 0x01, 0xdc, 0xfa, 0xac, 0x89, 0xc7, 0xb3, 0xf7, 0xb3, 0x26,
|
||||
0x5e, 0x6b, 0xc1, 0xcf, 0x9a, 0x84, 0x35, 0xa8, 0xc9, 0xa7, 0x2d, 0x42, 0xb3, 0xab, 0x3e, 0xc8,
|
||||
0xa2, 0xbb, 0xc9, 0xfe, 0xe4, 0x3a, 0x2a, 0xc4, 0xf4, 0xdb, 0x70, 0xf2, 0x8e, 0xda, 0x80, 0x67,
|
||||
0xea, 0xdc, 0x53, 0xdb, 0x18, 0xcc, 0x2b, 0xdf, 0x3f, 0x51, 0x6b, 0x2f, 0x3d, 0xd9, 0xf0, 0x52,
|
||||
0x7e, 0xd2, 0x66, 0x2d, 0x34, 0x79, 0xd4, 0x16, 0xec, 0x96, 0x7f, 0x3c, 0x0c, 0x26, 0xaa, 0x5b,
|
||||
0x13, 0xaa, 0xd1, 0xc7, 0x7d, 0x86, 0x50, 0x93, 0x6f, 0x0c, 0xe6, 0x89, 0x49, 0xae, 0xf1, 0xdd,
|
||||
0xb4, 0xf6, 0x00, 0x63, 0x6e, 0x5b, 0x6f, 0x0e, 0x57, 0x50, 0xee, 0x97, 0x2a, 0xa9, 0xb5, 0xdd,
|
||||
0xcb, 0x76, 0x5e, 0xef, 0x33, 0x35, 0x71, 0x9a, 0x79, 0x3c, 0x14, 0x0f, 0xa5, 0x37, 0xf6, 0x04,
|
||||
0xdf, 0x97, 0xde, 0x78, 0x27, 0xf9, 0x4f, 0xae, 0xa7, 0xa4, 0xca, 0xf2, 0xcf, 0xa3, 0xe8, 0x26,
|
||||
0x59, 0x16, 0x15, 0x07, 0x9f, 0x0d, 0xb5, 0x8c, 0xe2, 0xe1, 0xf3, 0x6b, 0xeb, 0xa9, 0x42, 0xfd,
|
||||
0xdb, 0x28, 0xba, 0x15, 0x28, 0x54, 0x13, 0x20, 0xd7, 0xb0, 0xee, 0x06, 0xca, 0x0f, 0xaf, 0xaf,
|
||||
0x48, 0x4d, 0xf7, 0x36, 0x3e, 0xe9, 0x7e, 0xef, 0x23, 0x60, 0x7b, 0x42, 0x7f, 0xef, 0xa3, 0x5f,
|
||||
0x0b, 0x6f, 0x41, 0xd5, 0x49, 0x89, 0x5a, 0x19, 0xf9, 0xb6, 0xa0, 0x64, 0xce, 0x82, 0x56, 0x44,
|
||||
0xf7, 0x7b, 0x39, 0x9f, 0x93, 0xe7, 0x6f, 0x0a, 0x96, 0x4f, 0x69, 0x27, 0x8d, 0xbc, 0xdf, 0x89,
|
||||
0xe6, 0xf0, 0xd6, 0x5d, 0x2d, 0x3d, 0xe1, 0xed, 0x32, 0xef, 0x21, 0xa5, 0xaf, 0x91, 0xe0, 0xd6,
|
||||
0x5d, 0x07, 0x25, 0xbc, 0xa9, 0x9c, 0x36, 0xe4, 0x0d, 0xa5, 0xb2, 0x8f, 0x86, 0xa0, 0x68, 0x01,
|
||||
0xa1, 0xbd, 0xe9, 0x13, 0x81, 0xc7, 0x21, 0x2b, 0x9d, 0x53, 0x81, 0xf5, 0x81, 0x34, 0xe1, 0x76,
|
||||
0x02, 0xe2, 0x4b, 0x60, 0x53, 0x28, 0x83, 0x6e, 0x35, 0x35, 0xc8, 0xad, 0x4d, 0xfb, 0xdc, 0x6e,
|
||||
0xf3, 0x6c, 0x31, 0xcf, 0x55, 0x63, 0x92, 0x6e, 0x6d, 0xaa, 0xdf, 0x2d, 0xa2, 0xf1, 0xa6, 0xa5,
|
||||
0x71, 0x2b, 0xd3, 0xcb, 0x47, 0x61, 0x33, 0x4e, 0x56, 0xb9, 0x36, 0x88, 0xa5, 0xeb, 0xa9, 0xc2,
|
||||
0xa8, 0xa7, 0x9e, 0x28, 0x92, 0xd6, 0x07, 0xd2, 0x78, 0xf7, 0xd0, 0x72, 0xab, 0xe3, 0x69, 0xa3,
|
||||
0xc7, 0x56, 0x27, 0xa4, 0x36, 0x87, 0x2b, 0xe0, 0xbd, 0x5a, 0x15, 0x55, 0xf5, 0xba, 0x68, 0x37,
|
||||
0xcd, 0xb2, 0x78, 0x2d, 0x10, 0x26, 0x2d, 0x14, 0xdc, 0xab, 0xf5, 0xc0, 0x44, 0x24, 0xb7, 0x7b,
|
||||
0x9b, 0x79, 0xdc, 0x67, 0x47, 0x52, 0x83, 0x22, 0xd9, 0xa6, 0xd1, 0x7e, 0x9b, 0xf5, 0xa8, 0x75,
|
||||
0x6d, 0xc7, 0xe1, 0x07, 0xd7, 0xa9, 0xf0, 0xc6, 0x60, 0x1e, 0x5d, 0x06, 0x90, 0x94, 0x9c, 0x59,
|
||||
0xee, 0x50, 0x26, 0x9c, 0x99, 0xe4, 0x6e, 0x0f, 0x85, 0xf6, 0x2c, 0x9b, 0x6e, 0xf4, 0x2a, 0x9d,
|
||||
0xce, 0x40, 0x78, 0xcf, 0xb1, 0x6c, 0x20, 0x78, 0x8e, 0x85, 0x40, 0xd4, 0x74, 0xcd, 0xef, 0x7a,
|
||||
0xb3, 0x76, 0x7f, 0xea, 0x6b, 0x3a, 0xa5, 0x6c, 0x51, 0xa1, 0xa6, 0xf3, 0xd2, 0x68, 0x34, 0xd0,
|
||||
0x6e, 0xd5, 0xcb, 0xe4, 0x8f, 0x42, 0x66, 0xd0, 0x1b, 0xe5, 0x6b, 0x83, 0x58, 0x34, 0xa3, 0x18,
|
||||
0x87, 0xe9, 0x3c, 0x15, 0xbe, 0x19, 0xc5, 0xb2, 0x51, 0x23, 0xa1, 0x19, 0xa5, 0x8b, 0x52, 0xd5,
|
||||
0xab, 0x73, 0x84, 0xfd, 0x69, 0xb8, 0x7a, 0x0d, 0x33, 0xac, 0x7a, 0x9a, 0xed, 0x1c, 0xbb, 0xe6,
|
||||
0x3a, 0x64, 0xc4, 0x85, 0x5a, 0x2c, 0x7b, 0x62, 0x5b, 0xbe, 0xee, 0x88, 0xc1, 0xd0, 0xa8, 0x43,
|
||||
0x29, 0xe0, 0xe3, 0x84, 0x9a, 0x6b, 0x4f, 0x86, 0x8b, 0x02, 0x58, 0xc9, 0xf2, 0xc4, 0xbb, 0x38,
|
||||
0x95, 0x06, 0x3b, 0x64, 0x68, 0x71, 0x4a, 0x6a, 0xa0, 0x43, 0x7d, 0xf7, 0x45, 0x45, 0x4f, 0x57,
|
||||
0xd0, 0x6f, 0x04, 0xba, 0xef, 0x29, 0x3e, 0x1c, 0x40, 0xe2, 0x43, 0xfd, 0x16, 0xd0, 0xdb, 0xf2,
|
||||
0x8d, 0xd3, 0x8f, 0x03, 0xa6, 0x5c, 0x34, 0xb4, 0x10, 0xa6, 0x55, 0x50, 0x50, 0xeb, 0x04, 0x17,
|
||||
0xc4, 0x8f, 0x61, 0xe5, 0x0b, 0x6a, 0x93, 0x9f, 0x4a, 0x24, 0x14, 0xd4, 0x5d, 0x14, 0xe5, 0x99,
|
||||
0xf6, 0x3a, 0xe8, 0x5e, 0x40, 0xdf, 0x5e, 0xfa, 0xdc, 0xef, 0xe5, 0x50, 0xcf, 0xd9, 0x49, 0x97,
|
||||
0xce, 0x29, 0x86, 0xa7, 0xa0, 0x3b, 0xe9, 0xd2, 0x7f, 0x88, 0xb1, 0x36, 0x88, 0xc5, 0x17, 0x06,
|
||||
0x98, 0x80, 0x37, 0xed, 0x49, 0xbe, 0xa7, 0xb8, 0x52, 0xde, 0x39, 0xca, 0x7f, 0xd0, 0x0f, 0x9a,
|
||||
0xeb, 0xb9, 0xc7, 0x25, 0x4f, 0xa0, 0xaa, 0xd4, 0x47, 0xd0, 0xdc, 0xfb, 0x4f, 0x4a, 0x36, 0x46,
|
||||
0x9f, 0x40, 0xbb, 0x13, 0x86, 0x94, 0xed, 0x2f, 0xa3, 0xb7, 0x0f, 0xf8, 0x6c, 0x02, 0xf9, 0x34,
|
||||
0xfe, 0x81, 0x7b, 0x21, 0x96, 0xcf, 0xc6, 0xf5, 0xcf, 0xda, 0xde, 0x0d, 0x4a, 0x6c, 0xae, 0xf4,
|
||||
0xed, 0xc0, 0xf9, 0x62, 0x36, 0x11, 0x4c, 0xa0, 0x2b, 0x7d, 0xf2, 0xf7, 0x71, 0x2d, 0x20, 0xae,
|
||||
0xf4, 0x39, 0x00, 0xb2, 0x77, 0x5a, 0x02, 0x78, 0xed, 0xd5, 0x82, 0xa0, 0x3d, 0x05, 0x98, 0x59,
|
||||
0x57, 0xdb, 0xab, 0x13, 0x5b, 0x7c, 0x05, 0xcf, 0xe8, 0x48, 0x29, 0x31, 0xeb, 0x76, 0x29, 0x13,
|
||||
0x0c, 0x4d, 0xf5, 0xe5, 0x37, 0x26, 0x16, 0xf3, 0x39, 0x2b, 0x57, 0x28, 0x18, 0x54, 0x2d, 0x2d,
|
||||
0x80, 0x08, 0x06, 0x2f, 0x68, 0xa2, 0xbc, 0x7d, 0xcc, 0xc9, 0xe5, 0x1e, 0x2f, 0xf9, 0x42, 0xa4,
|
||||
0x39, 0xe0, 0xef, 0x0c, 0xe8, 0x07, 0x6a, 0x33, 0x44, 0x94, 0x53, 0xac, 0xc9, 0x0a, 0x25, 0xd1,
|
||||
0xdc, 0x0e, 0x94, 0x9f, 0x12, 0xad, 0x04, 0x2f, 0xf1, 0xe9, 0x60, 0x63, 0x05, 0x43, 0x44, 0x56,
|
||||
0x48, 0xc2, 0xa8, 0xed, 0x8f, 0xd3, 0x7c, 0xe6, 0x6d, 0xfb, 0x63, 0xfb, 0x43, 0x7c, 0xb7, 0x68,
|
||||
0xc0, 0x8c, 0xef, 0xcd, 0x43, 0x6b, 0xbe, 0xe5, 0xa3, 0xde, 0x5b, 0xf4, 0x3e, 0x74, 0x9b, 0x20,
|
||||
0xc6, 0x77, 0x3f, 0x89, 0x5c, 0xbd, 0x28, 0x20, 0x87, 0x69, 0x7b, 0x07, 0xce, 0xe7, 0xca, 0x21,
|
||||
0x82, 0xae, 0x30, 0x69, 0x42, 0xe1, 0x10, 0x44, 0x99, 0x26, 0xd5, 0x04, 0xc4, 0x31, 0x2b, 0xd9,
|
||||
0x1c, 0x04, 0x94, 0x38, 0x14, 0x14, 0x32, 0x76, 0x18, 0x22, 0x14, 0x28, 0x56, 0x39, 0xfc, 0xfd,
|
||||
0xe8, 0xdd, 0x7a, 0x24, 0x84, 0x5c, 0x7d, 0xdb, 0xfc, 0xb9, 0xfc, 0xa3, 0x08, 0xf1, 0x7b, 0xda,
|
||||
0xc6, 0x44, 0x94, 0xc0, 0xe6, 0xad, 0xed, 0x77, 0xf4, 0xef, 0x12, 0xdc, 0x1c, 0xd5, 0xf3, 0xc0,
|
||||
0x11, 0x17, 0xe9, 0xeb, 0x7a, 0xe1, 0xa1, 0x8e, 0x79, 0xd0, 0x3c, 0x60, 0x8b, 0xc7, 0x81, 0xb7,
|
||||
0xdc, 0x7d, 0x9c, 0xe9, 0x89, 0xb6, 0xf4, 0x04, 0x8a, 0x0c, 0xf7, 0x44, 0x47, 0x5b, 0x02, 0x44,
|
||||
0x4f, 0xf4, 0x82, 0x66, 0x52, 0xb3, 0xc5, 0xa7, 0x10, 0xae, 0xcc, 0x29, 0x0c, 0xab, 0xcc, 0xa9,
|
||||
0x73, 0x89, 0x3e, 0x8b, 0xde, 0x3d, 0x84, 0xf9, 0x39, 0x94, 0xd5, 0x45, 0x5a, 0xec, 0xd5, 0x53,
|
||||
0x10, 0x13, 0x8b, 0x0a, 0xcd, 0xd3, 0x86, 0x18, 0x6b, 0x84, 0x98, 0xa7, 0x09, 0xd4, 0xf4, 0x75,
|
||||
0x03, 0xec, 0x57, 0x47, 0x6c, 0x0e, 0xf2, 0x9d, 0xfd, 0x78, 0x8d, 0x32, 0x62, 0x41, 0x44, 0x5f,
|
||||
0x27, 0x61, 0xeb, 0x7d, 0x1c, 0xc3, 0x9c, 0xc0, 0xac, 0x8e, 0xb0, 0xf2, 0x98, 0xad, 0xe6, 0x90,
|
||||
0x0b, 0x65, 0x12, 0xed, 0x52, 0x5a, 0x26, 0xfd, 0x3c, 0xb1, 0x4b, 0x39, 0x44, 0xcf, 0xca, 0x4a,
|
||||
0x9d, 0x07, 0x7f, 0xcc, 0x4b, 0xd1, 0xfc, 0xe5, 0x82, 0xb3, 0x32, 0x43, 0x59, 0xa9, 0xfb, 0x50,
|
||||
0x1d, 0x92, 0xc8, 0x4a, 0xc3, 0x1a, 0xd6, 0x27, 0x7f, 0x9d, 0x32, 0xbc, 0x84, 0x52, 0xc7, 0xc9,
|
||||
0xf3, 0x39, 0x4b, 0x33, 0x15, 0x0d, 0x5f, 0x04, 0x6c, 0x13, 0x3a, 0xc4, 0x27, 0x7f, 0x87, 0xea,
|
||||
0x5a, 0x1f, 0x49, 0x0e, 0x97, 0x10, 0x6d, 0x9a, 0xf6, 0xd8, 0x27, 0x36, 0x4d, 0xfb, 0xb5, 0xcc,
|
||||
0x5a, 0xc6, 0xb0, 0x92, 0x5b, 0x49, 0x62, 0x9b, 0x4f, 0xf1, 0x0e, 0x8a, 0x65, 0x13, 0x81, 0xc4,
|
||||
0x5a, 0x26, 0xa8, 0x60, 0x06, 0x7f, 0x83, 0xed, 0xa6, 0x39, 0xcb, 0xd2, 0x9f, 0xe2, 0xcb, 0xc1,
|
||||
0x96, 0x9d, 0x96, 0x20, 0x06, 0x7f, 0x3f, 0xe9, 0x73, 0xb5, 0x07, 0xe2, 0x34, 0xad, 0x87, 0xfe,
|
||||
0x07, 0x81, 0xe7, 0x26, 0x89, 0x7e, 0x57, 0x16, 0xa9, 0x5c, 0xfd, 0x6c, 0x14, 0xdd, 0xc4, 0x8f,
|
||||
0x75, 0xab, 0x28, 0x26, 0xf5, 0x9c, 0x7d, 0x02, 0x09, 0xa4, 0x85, 0x88, 0x3f, 0x0d, 0x3f, 0x2b,
|
||||
0x84, 0x13, 0x47, 0xcf, 0x03, 0xd4, 0xac, 0x03, 0xcd, 0x7a, 0x2c, 0x99, 0x34, 0x7f, 0xd2, 0xe7,
|
||||
0xac, 0x82, 0x52, 0x7d, 0xad, 0x7a, 0x0f, 0x04, 0xea, 0x9d, 0x16, 0x37, 0xb6, 0xc0, 0xba, 0xa2,
|
||||
0x44, 0xef, 0x0c, 0x6b, 0x98, 0xed, 0x0f, 0x8b, 0x3b, 0x81, 0x8a, 0x67, 0x4b, 0x90, 0xf7, 0xc3,
|
||||
0x1e, 0x93, 0xc6, 0x2c, 0x8a, 0xd8, 0xfe, 0xa0, 0x69, 0x73, 0xb9, 0xb1, 0xeb, 0x76, 0x2b, 0x5f,
|
||||
0xed, 0xe3, 0x43, 0x64, 0x8f, 0x25, 0x89, 0x11, 0x27, 0x5b, 0x01, 0xdc, 0xda, 0x1e, 0x2c, 0x39,
|
||||
0x9b, 0x26, 0xac, 0x12, 0xc7, 0x6c, 0x95, 0x71, 0x36, 0x95, 0xf3, 0x3a, 0xde, 0x1e, 0x6c, 0x99,
|
||||
0xb1, 0x0d, 0x51, 0xdb, 0x83, 0x14, 0xdc, 0xf8, 0x7c, 0xf6, 0xe1, 0x7f, 0x7f, 0x7d, 0x63, 0xf4,
|
||||
0xf3, 0xaf, 0x6f, 0x8c, 0xfe, 0xef, 0xeb, 0x1b, 0xa3, 0x9f, 0x7d, 0x73, 0xe3, 0xad, 0x9f, 0x7f,
|
||||
0x73, 0xe3, 0xad, 0xff, 0xfd, 0xe6, 0xc6, 0x5b, 0x5f, 0xbd, 0xad, 0xfe, 0x9a, 0xd3, 0xf9, 0x2f,
|
||||
0xc9, 0xbf, 0xc9, 0xf4, 0xf4, 0x17, 0x01, 0x00, 0x00, 0xff, 0xff, 0x82, 0x93, 0xb3, 0x87, 0xf1,
|
||||
0x69, 0x00, 0x00,
|
||||
// 4805 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x9d, 0xcd, 0x6f, 0x24, 0x49,
|
||||
0x56, 0xc0, 0xa7, 0x2e, 0x0c, 0xe4, 0xb2, 0x03, 0xd4, 0xc0, 0x30, 0x3b, 0xec, 0x76, 0xf7, 0xf4,
|
||||
0x74, 0xdb, 0xee, 0x76, 0xbb, 0xec, 0xe9, 0x9e, 0x8f, 0x65, 0x16, 0x09, 0xb9, 0xed, 0xb6, 0xc7,
|
||||
0xac, 0xed, 0x36, 0x2e, 0xbb, 0x5b, 0x1a, 0x09, 0x89, 0x70, 0xd6, 0x73, 0x39, 0x71, 0x56, 0x46,
|
||||
0x6e, 0x66, 0x54, 0xb9, 0x6b, 0x11, 0x08, 0x04, 0x02, 0x81, 0x40, 0xac, 0xf8, 0xba, 0x70, 0x40,
|
||||
0xe2, 0x1f, 0xe1, 0xca, 0x71, 0x0f, 0x1c, 0x38, 0xa2, 0x99, 0x7f, 0x64, 0x95, 0x91, 0x91, 0xf1,
|
||||
0xf1, 0x32, 0x5e, 0x64, 0x7a, 0x4e, 0xdd, 0xaa, 0xf7, 0x7b, 0xef, 0x45, 0x64, 0x7c, 0xbd, 0x17,
|
||||
0x11, 0x99, 0x8e, 0xee, 0xe6, 0x17, 0x9b, 0x79, 0xc1, 0x05, 0x2f, 0x37, 0x4b, 0x28, 0x16, 0x49,
|
||||
0x0c, 0xcd, 0xbf, 0x23, 0xf9, 0xf3, 0xf0, 0x6d, 0x96, 0x2d, 0xc5, 0x32, 0x87, 0x0f, 0xde, 0x37,
|
||||
0x64, 0xcc, 0x67, 0x33, 0x96, 0x4d, 0xca, 0x1a, 0xf9, 0xe0, 0x3d, 0x23, 0x81, 0x05, 0x64, 0x42,
|
||||
0xfd, 0xfe, 0xf4, 0xbf, 0xff, 0x77, 0x10, 0xbd, 0xb3, 0x93, 0x26, 0x90, 0x89, 0x1d, 0xa5, 0x31,
|
||||
0xfc, 0x2a, 0xfa, 0xee, 0x76, 0x9e, 0xef, 0x83, 0x78, 0x05, 0x45, 0x99, 0xf0, 0x6c, 0xf8, 0xd1,
|
||||
0x48, 0x39, 0x18, 0x9d, 0xe6, 0xf1, 0x68, 0x3b, 0xcf, 0x47, 0x46, 0x38, 0x3a, 0x85, 0x9f, 0xcc,
|
||||
0xa1, 0x14, 0x1f, 0x3c, 0x08, 0x43, 0x65, 0xce, 0xb3, 0x12, 0x86, 0x97, 0xd1, 0x6f, 0x6c, 0xe7,
|
||||
0xf9, 0x18, 0xc4, 0x2e, 0x54, 0x15, 0x18, 0x0b, 0x26, 0x60, 0xb8, 0xda, 0x52, 0x75, 0x01, 0xed,
|
||||
0x63, 0xad, 0x1b, 0x54, 0x7e, 0xce, 0xa2, 0xef, 0x54, 0x7e, 0xae, 0xe6, 0x62, 0xc2, 0x6f, 0xb2,
|
||||
0xe1, 0x87, 0x6d, 0x45, 0x25, 0xd2, 0xb6, 0xef, 0x87, 0x10, 0x65, 0xf5, 0x75, 0xf4, 0xab, 0xaf,
|
||||
0x59, 0x9a, 0x82, 0xd8, 0x29, 0xa0, 0x2a, 0xb8, 0xab, 0x53, 0x8b, 0x46, 0xb5, 0x4c, 0xdb, 0xfd,
|
||||
0x28, 0xc8, 0x28, 0xc3, 0x5f, 0x45, 0xdf, 0xad, 0x25, 0xa7, 0x10, 0xf3, 0x05, 0x14, 0x43, 0xaf,
|
||||
0x96, 0x12, 0x12, 0x8f, 0xbc, 0x05, 0x61, 0xdb, 0x3b, 0x3c, 0x5b, 0x40, 0x21, 0xfc, 0xb6, 0x95,
|
||||
0x30, 0x6c, 0xdb, 0x40, 0xca, 0xf6, 0xdf, 0x0d, 0xa2, 0xef, 0x6f, 0xc7, 0x31, 0x9f, 0x67, 0xe2,
|
||||
0x90, 0xc7, 0x2c, 0x3d, 0x4c, 0xb2, 0xeb, 0x63, 0xb8, 0xd9, 0xb9, 0xaa, 0xf8, 0x6c, 0x0a, 0xc3,
|
||||
0x67, 0xee, 0x53, 0xad, 0xd1, 0x91, 0x66, 0x47, 0x36, 0xac, 0x7d, 0x7f, 0x72, 0x3b, 0x25, 0x55,
|
||||
0x96, 0x7f, 0x1a, 0x44, 0x77, 0x70, 0x59, 0xc6, 0x3c, 0x5d, 0x80, 0x29, 0xcd, 0xa7, 0x1d, 0x86,
|
||||
0x5d, 0x5c, 0x97, 0xe7, 0xb3, 0xdb, 0xaa, 0xa9, 0x12, 0xa5, 0xd1, 0xbb, 0x76, 0x77, 0x19, 0x43,
|
||||
0x29, 0x87, 0xd3, 0x23, 0xba, 0x47, 0x28, 0x44, 0x7b, 0x7e, 0xdc, 0x07, 0x55, 0xde, 0x92, 0x68,
|
||||
0xa8, 0xbc, 0xa5, 0xbc, 0xd4, 0xce, 0xd6, 0xbc, 0x16, 0x2c, 0x42, 0xfb, 0x7a, 0xd4, 0x83, 0x54,
|
||||
0xae, 0xfe, 0x38, 0xfa, 0xb5, 0xd7, 0xbc, 0xb8, 0x2e, 0x73, 0x16, 0x83, 0x1a, 0x0a, 0x0f, 0x5d,
|
||||
0xed, 0x46, 0x8a, 0x47, 0xc3, 0x4a, 0x17, 0x66, 0x75, 0xda, 0x46, 0xf8, 0x32, 0x07, 0x3c, 0x07,
|
||||
0x19, 0xc5, 0x4a, 0x48, 0x75, 0x5a, 0x0c, 0x29, 0xdb, 0xd7, 0xd1, 0xd0, 0xd8, 0xbe, 0xf8, 0x13,
|
||||
0x88, 0xc5, 0xf6, 0x64, 0x82, 0x5b, 0xc5, 0xe8, 0x4a, 0x62, 0xb4, 0x3d, 0x99, 0x50, 0xad, 0xe2,
|
||||
0x47, 0x95, 0xb3, 0x9b, 0xe8, 0x3d, 0xe4, 0xec, 0x30, 0x29, 0xa5, 0xc3, 0x8d, 0xb0, 0x15, 0x85,
|
||||
0x69, 0xa7, 0xa3, 0xbe, 0xb8, 0x72, 0xfc, 0x17, 0x83, 0xe8, 0x7b, 0x1e, 0xcf, 0xa7, 0x30, 0xe3,
|
||||
0x0b, 0x18, 0x6e, 0x75, 0x5b, 0xab, 0x49, 0xed, 0xff, 0xe3, 0x5b, 0x68, 0x78, 0xba, 0xc9, 0x18,
|
||||
0x52, 0x88, 0x05, 0xd9, 0x4d, 0x6a, 0x71, 0x67, 0x37, 0xd1, 0x98, 0x35, 0xc2, 0x1a, 0xe1, 0x3e,
|
||||
0x88, 0x9d, 0x79, 0x51, 0x40, 0x26, 0xc8, 0xb6, 0x34, 0x48, 0x67, 0x5b, 0x3a, 0xa8, 0xa7, 0x3e,
|
||||
0xfb, 0x20, 0xb6, 0xd3, 0x94, 0xac, 0x4f, 0x2d, 0xee, 0xac, 0x8f, 0xc6, 0x94, 0x87, 0x38, 0xfa,
|
||||
0x75, 0xeb, 0x89, 0x89, 0x83, 0xec, 0x92, 0x0f, 0xe9, 0x67, 0x21, 0xe5, 0xda, 0xc7, 0x6a, 0x27,
|
||||
0xe7, 0xa9, 0xc6, 0x8b, 0x37, 0x39, 0x2f, 0xe8, 0x66, 0xa9, 0xc5, 0x9d, 0xd5, 0xd0, 0x98, 0xf2,
|
||||
0xf0, 0x47, 0xd1, 0x3b, 0x6a, 0x96, 0x6c, 0xd6, 0xb3, 0x07, 0xde, 0x29, 0x14, 0x2f, 0x68, 0x0f,
|
||||
0x3b, 0x28, 0x33, 0x39, 0x28, 0x99, 0x9a, 0x7c, 0x3e, 0xf2, 0xea, 0xa1, 0xa9, 0xe7, 0x41, 0x18,
|
||||
0x6a, 0xd9, 0xde, 0x85, 0x14, 0x48, 0xdb, 0xb5, 0xb0, 0xc3, 0xb6, 0x86, 0x94, 0xed, 0x22, 0xfa,
|
||||
0x2d, 0xfd, 0x58, 0xaa, 0x75, 0x54, 0xca, 0xab, 0x49, 0x7a, 0x9d, 0xa8, 0xb7, 0x0d, 0x69, 0x5f,
|
||||
0x4f, 0xfa, 0xc1, 0xad, 0xfa, 0xa8, 0x11, 0xe8, 0xaf, 0x0f, 0x1a, 0x7f, 0x0f, 0xc2, 0x90, 0xb2,
|
||||
0xfd, 0xf7, 0x83, 0xe8, 0x07, 0x4a, 0xf6, 0x22, 0x63, 0x17, 0x29, 0xc8, 0x25, 0xf1, 0x18, 0xc4,
|
||||
0x0d, 0x2f, 0xae, 0xc7, 0xcb, 0x2c, 0x26, 0x96, 0x7f, 0x3f, 0xdc, 0xb1, 0xfc, 0x93, 0x4a, 0x56,
|
||||
0xc4, 0xa7, 0x2a, 0x2a, 0x78, 0x8e, 0x23, 0xbe, 0xa6, 0x06, 0x82, 0xe7, 0x54, 0xc4, 0xe7, 0x22,
|
||||
0x2d, 0xab, 0x47, 0xd5, 0xb4, 0xe9, 0xb7, 0x7a, 0x64, 0xcf, 0x93, 0xf7, 0x43, 0x88, 0x99, 0xb6,
|
||||
0x9a, 0x0e, 0xcc, 0xb3, 0xcb, 0x64, 0x7a, 0x9e, 0x4f, 0xaa, 0x6e, 0xfc, 0xc8, 0xdf, 0x43, 0x2d,
|
||||
0x84, 0x98, 0xb6, 0x08, 0x54, 0x79, 0xfb, 0x47, 0x13, 0x18, 0xa9, 0xa1, 0xb4, 0x57, 0xf0, 0xd9,
|
||||
0x21, 0x4c, 0x59, 0xbc, 0x54, 0xe3, 0xff, 0x93, 0xd0, 0xc0, 0xc3, 0xb4, 0x2e, 0xc4, 0xa7, 0xb7,
|
||||
0xd4, 0x52, 0xe5, 0xf9, 0xcf, 0x41, 0xf4, 0xa0, 0xa9, 0xfe, 0x15, 0xcb, 0xa6, 0xa0, 0xda, 0xb3,
|
||||
0x2e, 0xfd, 0x76, 0x36, 0x39, 0x85, 0x52, 0xb0, 0x42, 0x0c, 0xbf, 0xf0, 0x57, 0x32, 0xa4, 0xa3,
|
||||
0xcb, 0xf6, 0xa3, 0x6f, 0xa5, 0x6b, 0x5a, 0x7d, 0x5c, 0x4d, 0x6c, 0x6a, 0x0a, 0x70, 0x5b, 0x5d,
|
||||
0x4a, 0xf0, 0x04, 0x70, 0x3f, 0x84, 0x98, 0x56, 0x97, 0x82, 0x83, 0x6c, 0x91, 0x08, 0xd8, 0x87,
|
||||
0x0c, 0x8a, 0x76, 0xab, 0xd7, 0xaa, 0x2e, 0x42, 0xb4, 0x3a, 0x81, 0x9a, 0xc9, 0xc6, 0xf1, 0xa6,
|
||||
0x17, 0xc7, 0xf5, 0x80, 0x91, 0xd6, 0xf2, 0xf8, 0xa4, 0x1f, 0x6c, 0xb2, 0x3b, 0xcb, 0xe7, 0x29,
|
||||
0x2c, 0xf8, 0x35, 0xce, 0xee, 0x6c, 0x13, 0x35, 0x40, 0x64, 0x77, 0x5e, 0xd0, 0xac, 0x60, 0x96,
|
||||
0x9f, 0x57, 0x09, 0xdc, 0xa0, 0x15, 0xcc, 0x56, 0xae, 0xc4, 0xc4, 0x0a, 0xe6, 0xc1, 0x94, 0x87,
|
||||
0xe3, 0xe8, 0x57, 0xa4, 0xf0, 0x0f, 0x78, 0x92, 0x0d, 0xef, 0x7a, 0x94, 0x2a, 0x81, 0xb6, 0x7a,
|
||||
0x8f, 0x06, 0x50, 0x89, 0xab, 0x5f, 0x77, 0x58, 0x16, 0x43, 0xea, 0x2d, 0xb1, 0x11, 0x07, 0x4b,
|
||||
0xec, 0x60, 0x26, 0x74, 0x90, 0xc2, 0x6a, 0xfe, 0x1a, 0x5f, 0xb1, 0x22, 0xc9, 0xa6, 0x43, 0x9f,
|
||||
0xae, 0x25, 0x27, 0x42, 0x07, 0x1f, 0x87, 0xba, 0xb0, 0x52, 0xdc, 0xce, 0xf3, 0xa2, 0x9a, 0x16,
|
||||
0x7d, 0x5d, 0xd8, 0x45, 0x82, 0x5d, 0xb8, 0x85, 0xfa, 0xbd, 0xed, 0x42, 0x9c, 0x26, 0x59, 0xd0,
|
||||
0x9b, 0x42, 0xfa, 0x78, 0x33, 0x28, 0xea, 0xbc, 0x87, 0xc0, 0x16, 0xd0, 0xd4, 0xcc, 0xf7, 0x64,
|
||||
0x6c, 0x20, 0xd8, 0x79, 0x11, 0x68, 0xf2, 0x34, 0x29, 0x3e, 0x62, 0xd7, 0x50, 0x3d, 0x60, 0xa8,
|
||||
0xd6, 0xb5, 0xa1, 0x4f, 0xdf, 0x21, 0x88, 0x3c, 0xcd, 0x4f, 0x2a, 0x57, 0xf3, 0xe8, 0x3d, 0x29,
|
||||
0x3f, 0x61, 0x85, 0x48, 0xe2, 0x24, 0x67, 0x59, 0x13, 0xff, 0xfb, 0xc6, 0x75, 0x8b, 0xd2, 0x2e,
|
||||
0x37, 0x7a, 0xd2, 0xca, 0xed, 0xbf, 0x0f, 0xa2, 0x0f, 0xb1, 0xdf, 0x13, 0x28, 0x66, 0x89, 0x4c,
|
||||
0x23, 0xcb, 0x7a, 0x12, 0x1e, 0x7e, 0x1e, 0x36, 0xda, 0x52, 0xd0, 0xa5, 0xf9, 0xe1, 0xed, 0x15,
|
||||
0x55, 0xc1, 0xfe, 0x30, 0x8a, 0xea, 0x74, 0x45, 0xa6, 0x94, 0xee, 0xa8, 0x55, 0x79, 0x8c, 0x93,
|
||||
0x4f, 0x7e, 0x18, 0x20, 0xcc, 0x52, 0x51, 0xff, 0x2e, 0x33, 0xe5, 0xa1, 0x57, 0x43, 0x8a, 0x88,
|
||||
0xa5, 0x02, 0x21, 0xb8, 0xa0, 0xe3, 0x2b, 0x7e, 0xe3, 0x2f, 0x68, 0x25, 0x09, 0x17, 0x54, 0x11,
|
||||
0x66, 0xef, 0x4a, 0x15, 0xd4, 0xb7, 0x77, 0xd5, 0x14, 0x23, 0xb4, 0x77, 0x85, 0x19, 0x65, 0x98,
|
||||
0x47, 0xbf, 0x69, 0x1b, 0x7e, 0xce, 0xf9, 0xf5, 0x8c, 0x15, 0xd7, 0xc3, 0xc7, 0xb4, 0x72, 0xc3,
|
||||
0x68, 0x47, 0xeb, 0xbd, 0x58, 0x33, 0x2d, 0xd8, 0x0e, 0xab, 0x40, 0xe3, 0xbc, 0x48, 0xd1, 0xb4,
|
||||
0xe0, 0xd8, 0x50, 0x08, 0x31, 0x2d, 0x10, 0xa8, 0x99, 0xb9, 0x6d, 0x6f, 0x63, 0xc0, 0xd9, 0x92,
|
||||
0xa3, 0x3e, 0x06, 0x2a, 0x5b, 0xf2, 0x60, 0xb8, 0x0b, 0xed, 0x17, 0x2c, 0xbf, 0xf2, 0x77, 0x21,
|
||||
0x29, 0x0a, 0x77, 0xa1, 0x06, 0xc1, 0xed, 0x3d, 0x06, 0x56, 0xc4, 0x57, 0xfe, 0xf6, 0xae, 0x65,
|
||||
0xe1, 0xf6, 0xd6, 0x0c, 0x6e, 0xef, 0x5a, 0xf0, 0x3a, 0x11, 0x57, 0x47, 0x20, 0x98, 0xbf, 0xbd,
|
||||
0x5d, 0x26, 0xdc, 0xde, 0x2d, 0xd6, 0x44, 0x32, 0xb6, 0xc3, 0xf1, 0xfc, 0xa2, 0x8c, 0x8b, 0xe4,
|
||||
0x02, 0x86, 0x01, 0x2b, 0x1a, 0x22, 0x22, 0x19, 0x12, 0x36, 0x93, 0xb4, 0xf2, 0xd9, 0xc8, 0x0e,
|
||||
0x26, 0x25, 0x9a, 0xa4, 0x1b, 0x1b, 0x16, 0x41, 0x4c, 0xd2, 0x7e, 0x12, 0x57, 0x6f, 0xbf, 0xe0,
|
||||
0xf3, 0xbc, 0xec, 0xa8, 0x1e, 0x82, 0xc2, 0xd5, 0x6b, 0xc3, 0xca, 0xe7, 0x9b, 0xe8, 0xb7, 0xed,
|
||||
0x47, 0x7a, 0x9e, 0x95, 0xda, 0xeb, 0x06, 0xfd, 0x9c, 0x2c, 0x8c, 0xd8, 0x96, 0x0a, 0xe0, 0x26,
|
||||
0x4c, 0x69, 0x3c, 0x8b, 0x5d, 0x10, 0x2c, 0x49, 0xcb, 0xe1, 0x8a, 0xdf, 0x46, 0x23, 0x27, 0xc2,
|
||||
0x14, 0x1f, 0x87, 0xc7, 0xec, 0xee, 0x3c, 0x4f, 0x93, 0xb8, 0xbd, 0x3f, 0xa9, 0x74, 0xb5, 0x38,
|
||||
0x3c, 0x66, 0x6d, 0x0c, 0xcf, 0x41, 0x63, 0x10, 0xf5, 0x7f, 0xce, 0x96, 0x39, 0xf8, 0xe7, 0x20,
|
||||
0x07, 0x09, 0xcf, 0x41, 0x18, 0xc5, 0xf5, 0x19, 0x83, 0x38, 0x64, 0x4b, 0x3e, 0x27, 0xe6, 0x20,
|
||||
0x2d, 0x0e, 0xd7, 0xc7, 0xc6, 0x4c, 0xa4, 0xa0, 0x3d, 0x1c, 0x64, 0x02, 0x8a, 0x8c, 0xa5, 0x7b,
|
||||
0x29, 0x9b, 0x96, 0x43, 0x62, 0xdc, 0xb8, 0x14, 0x11, 0x29, 0xd0, 0xb4, 0xe7, 0x31, 0x1e, 0x94,
|
||||
0x7b, 0x6c, 0xc1, 0x8b, 0x44, 0xd0, 0x8f, 0xd1, 0x20, 0x9d, 0x8f, 0xd1, 0x41, 0xbd, 0xde, 0xb6,
|
||||
0x8b, 0xf8, 0x2a, 0x59, 0xc0, 0x24, 0xe0, 0xad, 0x41, 0x7a, 0x78, 0xb3, 0x50, 0x4f, 0xa3, 0x8d,
|
||||
0xf9, 0xbc, 0x88, 0x81, 0x6c, 0xb4, 0x5a, 0xdc, 0xd9, 0x68, 0x1a, 0x53, 0x1e, 0xfe, 0x7a, 0x10,
|
||||
0xfd, 0x4e, 0x2d, 0xb5, 0x37, 0x0d, 0x77, 0x59, 0x79, 0x75, 0xc1, 0x59, 0x31, 0x19, 0x7e, 0xec,
|
||||
0xb3, 0xe3, 0x45, 0xb5, 0xeb, 0xa7, 0xb7, 0x51, 0xc1, 0x8f, 0xf5, 0x30, 0x29, 0xad, 0x11, 0xe7,
|
||||
0x7d, 0xac, 0x0e, 0x12, 0x7e, 0xac, 0x18, 0xc5, 0x13, 0x88, 0x94, 0xd7, 0x09, 0xfa, 0x0a, 0xa9,
|
||||
0xef, 0x66, 0xe9, 0xab, 0x9d, 0x1c, 0x9e, 0x1f, 0x2b, 0xa1, 0xdb, 0x5b, 0x36, 0x28, 0x1b, 0xfe,
|
||||
0x1e, 0x33, 0xea, 0x8b, 0x93, 0x9e, 0xf5, 0xa8, 0x08, 0x7b, 0x6e, 0x8d, 0x8c, 0x51, 0x5f, 0x9c,
|
||||
0xf0, 0x6c, 0x4d, 0x6b, 0x21, 0xcf, 0x9e, 0xa9, 0x6d, 0xd4, 0x17, 0xc7, 0x11, 0x85, 0x62, 0x9a,
|
||||
0x75, 0xe1, 0x71, 0xc0, 0x0e, 0x5e, 0x1b, 0xd6, 0x7b, 0xb1, 0xb8, 0xc7, 0x6e, 0xe7, 0x79, 0xba,
|
||||
0x3c, 0x83, 0x59, 0x9e, 0x92, 0x3d, 0xd6, 0x41, 0xc2, 0x3d, 0x16, 0xa3, 0x38, 0xbe, 0x3b, 0xe3,
|
||||
0x55, 0xf4, 0xe8, 0x8d, 0xef, 0xa4, 0x28, 0x1c, 0xdf, 0x35, 0x08, 0x8e, 0x50, 0xce, 0xf8, 0x0e,
|
||||
0x4f, 0x53, 0x88, 0x45, 0xfb, 0xb8, 0x4f, 0x6b, 0x1a, 0x22, 0x1c, 0xa1, 0x20, 0xd2, 0x64, 0xc6,
|
||||
0x4d, 0x36, 0xc2, 0x0a, 0x78, 0xbe, 0x3c, 0x4c, 0xb2, 0xeb, 0xa1, 0x7f, 0x31, 0x36, 0x00, 0x91,
|
||||
0x19, 0x7b, 0x41, 0x9c, 0xf5, 0x9c, 0x67, 0x13, 0xee, 0xcf, 0x7a, 0x2a, 0x49, 0x38, 0xeb, 0x51,
|
||||
0x04, 0x36, 0x79, 0x0a, 0x94, 0xc9, 0x4a, 0x12, 0x36, 0xa9, 0x08, 0xdf, 0x04, 0xa4, 0xf6, 0x4f,
|
||||
0xc9, 0x09, 0x08, 0xed, 0x98, 0xae, 0x76, 0x72, 0xb8, 0x87, 0x36, 0xe9, 0xcf, 0x1e, 0x88, 0xf8,
|
||||
0xca, 0xdf, 0x43, 0x1d, 0x24, 0xdc, 0x43, 0x31, 0x8a, 0xab, 0x74, 0xc6, 0x75, 0xfa, 0xb6, 0xe2,
|
||||
0xef, 0x1f, 0xad, 0xd4, 0x6d, 0xb5, 0x93, 0xc3, 0x09, 0xc9, 0xc1, 0x4c, 0x3e, 0x33, 0x6f, 0x27,
|
||||
0xaf, 0x65, 0xe1, 0x84, 0x44, 0x33, 0xb8, 0xf4, 0xb5, 0xa0, 0x7a, 0x9c, 0xfe, 0xd2, 0x1b, 0x79,
|
||||
0xb8, 0xf4, 0x0e, 0xa7, 0x9c, 0xfc, 0xeb, 0x20, 0xba, 0x6b, 0x7b, 0x39, 0xe6, 0xd5, 0x18, 0x79,
|
||||
0xc5, 0xd2, 0x64, 0xc2, 0x04, 0x9c, 0xf1, 0x6b, 0xc8, 0xd0, 0x8e, 0x86, 0x5b, 0xda, 0x9a, 0x1f,
|
||||
0x39, 0x0a, 0xc4, 0x8e, 0x46, 0x2f, 0x45, 0xdc, 0x4f, 0x6a, 0xfa, 0xbc, 0x84, 0x1d, 0x56, 0x12,
|
||||
0x33, 0x99, 0x83, 0x84, 0xfb, 0x09, 0x46, 0x71, 0x94, 0x58, 0xcb, 0x5f, 0xbc, 0xc9, 0xa1, 0x48,
|
||||
0x20, 0x8b, 0xc1, 0x1f, 0x25, 0x62, 0x2a, 0x1c, 0x25, 0x7a, 0xe8, 0x56, 0xc2, 0xaf, 0x27, 0xa7,
|
||||
0xf6, 0x89, 0x3d, 0x26, 0x02, 0x27, 0xf6, 0x04, 0x8a, 0x2b, 0x69, 0x00, 0xef, 0xa6, 0x59, 0xcb,
|
||||
0x4a, 0x70, 0xd3, 0x8c, 0xa6, 0x5b, 0xdb, 0x28, 0x9a, 0x19, 0x57, 0xc3, 0xa4, 0xa3, 0xe8, 0x63,
|
||||
0x7b, 0xb8, 0xac, 0xf7, 0x62, 0xfd, 0xfb, 0x36, 0xa7, 0x90, 0x32, 0xb9, 0x84, 0x04, 0x36, 0x47,
|
||||
0x1a, 0xa6, 0xcf, 0xbe, 0x8d, 0xc5, 0x2a, 0x87, 0x7f, 0x39, 0x88, 0x3e, 0xf0, 0x79, 0x7c, 0x99,
|
||||
0x4b, 0xbf, 0x5b, 0xdd, 0xb6, 0x6a, 0x92, 0xb8, 0x92, 0x10, 0xd6, 0x50, 0x65, 0xf8, 0xd3, 0xe8,
|
||||
0xfd, 0x46, 0x64, 0x6e, 0x2c, 0xa8, 0x02, 0xb8, 0x61, 0x8b, 0x2e, 0x3f, 0xe6, 0xb4, 0xfb, 0xcd,
|
||||
0xde, 0xbc, 0xc9, 0x08, 0xdc, 0x72, 0x95, 0x28, 0x23, 0xd0, 0x36, 0x94, 0x98, 0xc8, 0x08, 0x3c,
|
||||
0x18, 0x5e, 0xa9, 0x1b, 0xa4, 0x1a, 0x27, 0xbe, 0x39, 0x4e, 0x9b, 0xb0, 0x47, 0xc9, 0x5a, 0x37,
|
||||
0x88, 0xfb, 0x4e, 0x23, 0x56, 0x81, 0xf8, 0xe3, 0x90, 0x05, 0x14, 0x8c, 0xaf, 0xf7, 0x62, 0x95,
|
||||
0xc3, 0x3f, 0x8f, 0xbe, 0xd7, 0xaa, 0xd8, 0x1e, 0x30, 0x31, 0x2f, 0x60, 0x32, 0xdc, 0xec, 0x28,
|
||||
0x77, 0x03, 0x6a, 0xd7, 0x5b, 0xfd, 0x15, 0x94, 0xff, 0xbf, 0x1d, 0x44, 0xdf, 0x77, 0xb9, 0xba,
|
||||
0x89, 0x75, 0x19, 0x9e, 0x86, 0x4c, 0xba, 0xac, 0x2e, 0xc6, 0xb3, 0x5b, 0xe9, 0xb4, 0x92, 0x3e,
|
||||
0xbb, 0x23, 0x6f, 0x2f, 0x58, 0x92, 0xca, 0x83, 0x84, 0x8f, 0x43, 0x46, 0x1d, 0x34, 0x98, 0xf4,
|
||||
0x91, 0x2a, 0xad, 0x59, 0x52, 0x8e, 0x37, 0x2b, 0x59, 0x78, 0x42, 0x8f, 0x4a, 0x4f, 0xae, 0xb0,
|
||||
0xd1, 0x93, 0x56, 0x6e, 0x45, 0xb3, 0x59, 0x56, 0xfd, 0x6c, 0x77, 0x72, 0x9f, 0x57, 0xa5, 0xea,
|
||||
0xe9, 0xe9, 0x1b, 0x3d, 0x69, 0xe5, 0xf5, 0xcf, 0xa2, 0xf7, 0xdb, 0x5e, 0xd5, 0xa2, 0xb0, 0xd9,
|
||||
0x69, 0x0a, 0xad, 0x0b, 0x5b, 0xfd, 0x15, 0x4c, 0xa8, 0xff, 0x65, 0x52, 0x0a, 0x5e, 0x2c, 0xc7,
|
||||
0x57, 0xfc, 0xa6, 0xb9, 0x95, 0xeb, 0x8e, 0x56, 0x05, 0x8c, 0x2c, 0x82, 0x08, 0xf5, 0xfd, 0x64,
|
||||
0xcb, 0x95, 0xb9, 0xbd, 0x5b, 0x12, 0xae, 0x2c, 0xa2, 0xc3, 0x95, 0x4b, 0x9a, 0xb9, 0xaa, 0xa9,
|
||||
0x95, 0xb9, 0x6a, 0xbc, 0xea, 0x2f, 0x6a, 0xfb, 0xba, 0xf1, 0x5a, 0x37, 0x68, 0xa2, 0x07, 0x25,
|
||||
0xde, 0x4d, 0x2e, 0x2f, 0x75, 0x9d, 0xfc, 0x25, 0xb5, 0x11, 0x22, 0x7a, 0x20, 0x50, 0x93, 0xec,
|
||||
0xed, 0x25, 0x29, 0xbc, 0xbc, 0xbc, 0x4c, 0x39, 0x9b, 0xa0, 0x64, 0xaf, 0x92, 0x8c, 0x94, 0x88,
|
||||
0x48, 0xf6, 0x10, 0x62, 0x42, 0xdc, 0x4a, 0x20, 0xcf, 0xba, 0x1a, 0xd3, 0x2b, 0x6d, 0x3d, 0x5b,
|
||||
0x4e, 0x84, 0xb8, 0x3e, 0xce, 0x2c, 0x4f, 0x95, 0xb4, 0x1a, 0xf0, 0x8d, 0x8f, 0x87, 0x6d, 0x5d,
|
||||
0x4b, 0x4c, 0x2c, 0x4f, 0x1e, 0xcc, 0x64, 0x63, 0x95, 0xf0, 0x3c, 0x97, 0xc6, 0xef, 0xb5, 0xb5,
|
||||
0x6a, 0x09, 0x91, 0x8d, 0xb9, 0x84, 0xc9, 0x2a, 0xaa, 0xdf, 0x77, 0xf9, 0x4d, 0x26, 0x8d, 0x7a,
|
||||
0x9e, 0x66, 0x23, 0x23, 0xb2, 0x0a, 0xcc, 0x28, 0xc3, 0x3f, 0x8e, 0x7e, 0x59, 0x1a, 0x2e, 0x78,
|
||||
0x3e, 0xbc, 0xe3, 0x51, 0x28, 0xac, 0x9b, 0x44, 0x77, 0x49, 0xb9, 0xb9, 0x10, 0xa7, 0xdb, 0xef,
|
||||
0xbc, 0x64, 0x53, 0x40, 0x17, 0xe2, 0x4c, 0xab, 0x48, 0x29, 0x71, 0x21, 0xae, 0x4d, 0x99, 0x4b,
|
||||
0x5e, 0x95, 0xec, 0x98, 0x4f, 0x94, 0x75, 0x4f, 0x0d, 0xb5, 0x90, 0xb8, 0xe4, 0xd5, 0x82, 0xcc,
|
||||
0xf1, 0xc4, 0x31, 0x5b, 0x24, 0x53, 0xbd, 0xd4, 0xd4, 0x33, 0x56, 0x89, 0x8e, 0x27, 0x0c, 0x33,
|
||||
0xb2, 0x20, 0xe2, 0x78, 0x82, 0x84, 0x95, 0xcf, 0x7f, 0x19, 0x44, 0xf7, 0x0c, 0xb3, 0xdf, 0xec,
|
||||
0x1a, 0x1d, 0x64, 0x97, 0xfc, 0x75, 0x22, 0xae, 0x0e, 0x93, 0xec, 0xba, 0x1c, 0x7e, 0x46, 0x99,
|
||||
0xf4, 0xf3, 0xba, 0x28, 0x9f, 0xdf, 0x5a, 0xcf, 0xc4, 0x8e, 0xcd, 0xe6, 0x8e, 0x39, 0x2b, 0xac,
|
||||
0x35, 0x50, 0xec, 0xa8, 0xf7, 0x80, 0x30, 0x47, 0xc4, 0x8e, 0x21, 0xde, 0x34, 0xb1, 0x76, 0x9e,
|
||||
0xf2, 0x0c, 0x37, 0xb1, 0xb1, 0x50, 0x09, 0x89, 0x26, 0x6e, 0x41, 0x66, 0x26, 0x6e, 0x44, 0xf5,
|
||||
0x3e, 0xc4, 0x76, 0x9a, 0xa2, 0x99, 0x58, 0xab, 0x6a, 0x80, 0x98, 0x89, 0xbd, 0xa0, 0xf2, 0x73,
|
||||
0x1a, 0x7d, 0xa7, 0x7a, 0xa4, 0x27, 0x05, 0x2c, 0x12, 0xc0, 0xc7, 0xda, 0x96, 0x84, 0x18, 0xff,
|
||||
0x2e, 0x61, 0x46, 0xd6, 0x79, 0x56, 0xe6, 0x29, 0x2b, 0xaf, 0xd4, 0x41, 0xa7, 0x5b, 0xe7, 0x46,
|
||||
0x88, 0x8f, 0x3a, 0x1f, 0x76, 0x50, 0x66, 0xe2, 0x6d, 0x64, 0x7a, 0x8a, 0x59, 0xf1, 0xab, 0xb6,
|
||||
0xa6, 0x99, 0xd5, 0x4e, 0xce, 0xec, 0xbc, 0xee, 0xb3, 0x34, 0x85, 0x62, 0xd9, 0xc8, 0x8e, 0x58,
|
||||
0x96, 0x5c, 0x42, 0x29, 0xd0, 0xce, 0xab, 0xa2, 0x46, 0x18, 0x23, 0x76, 0x5e, 0x03, 0xb8, 0x89,
|
||||
0xe3, 0x91, 0xe7, 0x83, 0x6c, 0x02, 0x6f, 0x50, 0x1c, 0x8f, 0xed, 0x48, 0x86, 0x88, 0xe3, 0x29,
|
||||
0xd6, 0x2c, 0x8f, 0xcf, 0x53, 0x1e, 0x5f, 0xab, 0x25, 0xc0, 0x6d, 0x60, 0x29, 0xc1, 0x6b, 0xc0,
|
||||
0xfd, 0x10, 0x62, 0x16, 0x01, 0x29, 0x38, 0x85, 0x3c, 0x65, 0x31, 0xbe, 0xdb, 0x50, 0xeb, 0x28,
|
||||
0x19, 0xb1, 0x08, 0x60, 0x06, 0x15, 0x57, 0xdd, 0x99, 0xf0, 0x15, 0x17, 0x5d, 0x99, 0xb8, 0x1f,
|
||||
0x42, 0xcc, 0x32, 0x28, 0x05, 0xe3, 0x3c, 0x4d, 0x04, 0x1a, 0x06, 0xb5, 0x86, 0x94, 0x10, 0xc3,
|
||||
0xc0, 0x25, 0x90, 0xc9, 0x23, 0x28, 0xa6, 0xe0, 0x35, 0x29, 0x25, 0x41, 0x93, 0x0d, 0x61, 0xae,
|
||||
0xc0, 0xd5, 0x75, 0xe7, 0xf9, 0x12, 0x5d, 0x81, 0x53, 0xd5, 0xe2, 0xf9, 0x92, 0xb8, 0x02, 0xe7,
|
||||
0x00, 0xa8, 0x88, 0x27, 0xac, 0x14, 0xfe, 0x22, 0x4a, 0x49, 0xb0, 0x88, 0x0d, 0x61, 0xd6, 0xe8,
|
||||
0xba, 0x88, 0x73, 0x81, 0xd6, 0x68, 0x55, 0x00, 0xeb, 0x24, 0xf4, 0x2e, 0x29, 0x37, 0x33, 0x49,
|
||||
0xdd, 0x2a, 0x20, 0xf6, 0x12, 0x48, 0x27, 0x25, 0x9a, 0x49, 0xd4, 0x73, 0x6f, 0xa4, 0xc4, 0x4c,
|
||||
0xd2, 0xa6, 0x50, 0x57, 0x52, 0x3b, 0xc6, 0xbe, 0xda, 0xa1, 0xcd, 0xe2, 0xfb, 0x21, 0xc4, 0xcc,
|
||||
0x4f, 0x4d, 0xa1, 0x77, 0x58, 0x51, 0x24, 0xd5, 0xe2, 0xbf, 0xe2, 0x2f, 0x50, 0x23, 0x27, 0xe6,
|
||||
0x27, 0x1f, 0x87, 0x86, 0x57, 0x33, 0x71, 0xfb, 0x0a, 0x86, 0xa7, 0xee, 0x8f, 0x82, 0x8c, 0x89,
|
||||
0x38, 0xa5, 0xc4, 0x3a, 0xca, 0xf3, 0x3d, 0x4d, 0xcf, 0x49, 0xde, 0x4a, 0x17, 0x66, 0x5d, 0x51,
|
||||
0xd7, 0x2e, 0x8e, 0xf8, 0x02, 0xce, 0xf8, 0x8b, 0x37, 0x49, 0x29, 0x92, 0x6c, 0xaa, 0x56, 0xee,
|
||||
0x67, 0x84, 0x25, 0x1f, 0x4c, 0x5c, 0x51, 0xef, 0x54, 0x32, 0x01, 0x04, 0x2a, 0xcb, 0x31, 0xdc,
|
||||
0x78, 0x03, 0x08, 0x6c, 0x51, 0x73, 0x44, 0x00, 0x11, 0xe2, 0xcd, 0x0e, 0x8a, 0x76, 0xae, 0xde,
|
||||
0xe3, 0x3b, 0xe3, 0x4d, 0x2c, 0x47, 0x59, 0xc3, 0x20, 0x91, 0xc4, 0x06, 0x15, 0x4c, 0x66, 0xa9,
|
||||
0xfd, 0x9b, 0x21, 0xb6, 0x46, 0xd8, 0x69, 0x0f, 0xb3, 0x47, 0x3d, 0x48, 0x8f, 0x2b, 0x73, 0x1e,
|
||||
0x4d, 0xb9, 0x6a, 0x1f, 0x47, 0x3f, 0xea, 0x41, 0x5a, 0xbb, 0x31, 0x76, 0xb5, 0x9e, 0xb3, 0xf8,
|
||||
0x7a, 0x5a, 0xf0, 0x79, 0x36, 0xd9, 0xe1, 0x29, 0x2f, 0xd0, 0x6e, 0x8c, 0x53, 0x6a, 0x84, 0x12,
|
||||
0xbb, 0x31, 0x1d, 0x2a, 0x26, 0x82, 0xb3, 0x4b, 0xb1, 0x9d, 0x26, 0x53, 0x9c, 0x4b, 0x3b, 0x86,
|
||||
0x24, 0x40, 0x44, 0x70, 0x5e, 0xd0, 0xd3, 0x89, 0xea, 0x5c, 0x5b, 0x24, 0x31, 0x4b, 0x6b, 0x7f,
|
||||
0x9b, 0xb4, 0x19, 0x07, 0xec, 0xec, 0x44, 0x1e, 0x05, 0x4f, 0x3d, 0xcf, 0xe6, 0x45, 0x76, 0x90,
|
||||
0x09, 0x4e, 0xd6, 0xb3, 0x01, 0x3a, 0xeb, 0x69, 0x81, 0x68, 0x5a, 0x3d, 0x83, 0x37, 0x55, 0x69,
|
||||
0xaa, 0x7f, 0x7c, 0xd3, 0x6a, 0xf5, 0xfb, 0x48, 0xc9, 0x43, 0xd3, 0x2a, 0xe2, 0x50, 0x65, 0x94,
|
||||
0x93, 0xba, 0xc3, 0x04, 0xb4, 0xdd, 0x6e, 0xb2, 0xd6, 0x0d, 0xfa, 0xfd, 0x8c, 0xc5, 0x32, 0x85,
|
||||
0x90, 0x1f, 0x09, 0xf4, 0xf1, 0xd3, 0x80, 0x66, 0xa3, 0xc5, 0xa9, 0xcf, 0x15, 0xc4, 0xd7, 0xad,
|
||||
0xeb, 0x35, 0x6e, 0x41, 0x6b, 0x84, 0xd8, 0x68, 0x21, 0x50, 0x7f, 0x13, 0x1d, 0xc4, 0x3c, 0x0b,
|
||||
0x35, 0x51, 0x25, 0xef, 0xd3, 0x44, 0x8a, 0x33, 0xc9, 0xaf, 0x96, 0xaa, 0x9e, 0x59, 0x37, 0xd3,
|
||||
0x3a, 0x61, 0xc1, 0x86, 0x88, 0xe4, 0x97, 0x84, 0x4d, 0x4c, 0x8e, 0x7d, 0x1e, 0xb5, 0xef, 0xd3,
|
||||
0xb6, 0xac, 0x1c, 0xd1, 0xf7, 0x69, 0x29, 0x96, 0xae, 0x64, 0xdd, 0x47, 0x3a, 0xac, 0xb8, 0xfd,
|
||||
0xe4, 0x49, 0x3f, 0xd8, 0xa4, 0x3c, 0x8e, 0xcf, 0x9d, 0x14, 0x58, 0x51, 0x7b, 0xdd, 0x08, 0x18,
|
||||
0x32, 0x18, 0x91, 0xf2, 0x04, 0x70, 0x34, 0x85, 0x39, 0x9e, 0x77, 0x78, 0x26, 0x20, 0x13, 0xbe,
|
||||
0x29, 0xcc, 0x35, 0xa6, 0xc0, 0xd0, 0x14, 0x46, 0x29, 0xa0, 0x7e, 0x2b, 0xf7, 0x83, 0x40, 0x1c,
|
||||
0xb3, 0x99, 0x37, 0x62, 0xab, 0xf7, 0x7a, 0x6a, 0x79, 0xa8, 0xdf, 0x22, 0xce, 0x3a, 0x6a, 0xb3,
|
||||
0xbd, 0x9c, 0xb1, 0x62, 0xaa, 0x77, 0x37, 0x26, 0xc3, 0x2d, 0xda, 0x8e, 0x4b, 0x12, 0x47, 0x6d,
|
||||
0x61, 0x0d, 0x34, 0xed, 0x1c, 0xcc, 0xd8, 0x54, 0xd7, 0xd4, 0x53, 0x03, 0x29, 0x6f, 0x55, 0x75,
|
||||
0xad, 0x1b, 0x44, 0x7e, 0x5e, 0x25, 0x13, 0xe0, 0x01, 0x3f, 0x52, 0xde, 0xc7, 0x0f, 0x06, 0x51,
|
||||
0xf4, 0x56, 0xd5, 0xbb, 0xce, 0xe8, 0xb6, 0xb3, 0x89, 0xca, 0x63, 0x47, 0xc4, 0xe3, 0x41, 0x5c,
|
||||
0x28, 0x7a, 0x23, 0x78, 0x34, 0x46, 0x9b, 0x0d, 0xda, 0xd0, 0x18, 0xd5, 0xfb, 0xaf, 0x7d, 0xc6,
|
||||
0xa8, 0x0f, 0x56, 0x3e, 0x7f, 0xaa, 0xc6, 0xe8, 0x2e, 0x13, 0xac, 0x8a, 0xdb, 0x5f, 0x25, 0x70,
|
||||
0xa3, 0x12, 0x61, 0x4f, 0x7d, 0x1b, 0x6a, 0x24, 0x5f, 0xa4, 0x42, 0x59, 0xf1, 0x66, 0x6f, 0x3e,
|
||||
0xe0, 0x5b, 0x65, 0x08, 0x9d, 0xbe, 0x51, 0xaa, 0xb0, 0xd9, 0x9b, 0x0f, 0xf8, 0x56, 0x6f, 0x68,
|
||||
0x76, 0xfa, 0x46, 0xaf, 0x69, 0x6e, 0xf6, 0xe6, 0x95, 0xef, 0xbf, 0x6a, 0x06, 0xae, 0xed, 0xbc,
|
||||
0x8a, 0xc3, 0x62, 0x91, 0x2c, 0xc0, 0x17, 0x4e, 0xba, 0xf6, 0x34, 0x1a, 0x0a, 0x27, 0x69, 0x15,
|
||||
0xeb, 0xb3, 0x1e, 0xbe, 0x52, 0x9c, 0xf0, 0x32, 0x91, 0x47, 0xe5, 0xcf, 0x7a, 0x18, 0x6d, 0xe0,
|
||||
0x50, 0xd2, 0x14, 0x52, 0x32, 0x07, 0x8d, 0x0e, 0x6a, 0x6e, 0xd3, 0x3e, 0x09, 0xd8, 0x6b, 0x5f,
|
||||
0xaa, 0xdd, 0xe8, 0x49, 0x9b, 0x23, 0x3f, 0x87, 0xb1, 0xcf, 0x1a, 0x43, 0xad, 0xea, 0x3d, 0x6e,
|
||||
0xdc, 0xea, 0xaf, 0xa0, 0xdc, 0xff, 0x4d, 0x93, 0x57, 0x60, 0xff, 0x6a, 0x10, 0x3c, 0xed, 0x63,
|
||||
0x11, 0x0d, 0x84, 0x67, 0xb7, 0xd2, 0x51, 0x05, 0xf9, 0x8f, 0x41, 0x74, 0xdf, 0x5b, 0x10, 0xf7,
|
||||
0xd4, 0xf9, 0x77, 0xfb, 0xd8, 0xf6, 0x9f, 0x3e, 0x7f, 0xf1, 0x6d, 0x54, 0x55, 0xe9, 0xfe, 0xa1,
|
||||
0x49, 0xef, 0x1b, 0x0d, 0xf9, 0xc6, 0xc3, 0xcb, 0x62, 0x02, 0x85, 0x1a, 0xb1, 0xa1, 0x4e, 0x67,
|
||||
0x60, 0x3c, 0x6e, 0x3f, 0xbd, 0xa5, 0x96, 0xf5, 0x09, 0x1a, 0x07, 0x56, 0x6f, 0x9b, 0x59, 0xe5,
|
||||
0x09, 0x59, 0xb6, 0x68, 0x5c, 0xa0, 0xcf, 0x6e, 0xab, 0x46, 0x8d, 0x64, 0x0b, 0x96, 0x6f, 0xb4,
|
||||
0x3f, 0xeb, 0x69, 0xd8, 0x79, 0xc7, 0xfd, 0x93, 0xdb, 0x29, 0xa9, 0xb2, 0xfc, 0xd7, 0x20, 0x7a,
|
||||
0xe8, 0xb0, 0xe6, 0xb4, 0x03, 0xed, 0xc9, 0xfc, 0x28, 0x60, 0x9f, 0x52, 0xd2, 0x85, 0xfb, 0xbd,
|
||||
0x6f, 0xa7, 0x6c, 0xbe, 0xd7, 0xe2, 0xa8, 0xec, 0x25, 0xa9, 0x80, 0xa2, 0xfd, 0xbd, 0x16, 0xd7,
|
||||
0x6e, 0x4d, 0x8d, 0xe8, 0xef, 0xb5, 0x04, 0x70, 0xeb, 0x7b, 0x2d, 0x1e, 0xcf, 0xde, 0xef, 0xb5,
|
||||
0x78, 0xad, 0x05, 0xbf, 0xd7, 0x12, 0xd6, 0xa0, 0x16, 0x9f, 0xa6, 0x08, 0xf5, 0xae, 0x7a, 0x2f,
|
||||
0x8b, 0xee, 0x26, 0xfb, 0xd3, 0xdb, 0xa8, 0x10, 0xcb, 0x6f, 0xcd, 0xc9, 0xbb, 0x70, 0x3d, 0x9e,
|
||||
0xa9, 0x73, 0x1f, 0x6e, 0xb3, 0x37, 0xaf, 0x7c, 0xff, 0x44, 0xe5, 0x5e, 0x7a, 0xb1, 0xe1, 0x85,
|
||||
0xfc, 0x56, 0xcf, 0x7a, 0x68, 0xf1, 0xa8, 0x2c, 0xd8, 0x2d, 0xff, 0xa4, 0x1f, 0x4c, 0x54, 0xb7,
|
||||
0x22, 0x54, 0xa3, 0x8f, 0xba, 0x0c, 0xa1, 0x26, 0xdf, 0xec, 0xcd, 0x13, 0x8b, 0x5c, 0xed, 0xbb,
|
||||
0x6e, 0xed, 0x1e, 0xc6, 0xdc, 0xb6, 0xde, 0xea, 0xaf, 0xa0, 0xdc, 0x2f, 0x54, 0x50, 0x6b, 0xbb,
|
||||
0x97, 0xed, 0xbc, 0xd1, 0x65, 0x6a, 0xec, 0x34, 0xf3, 0xa8, 0x2f, 0x1e, 0x0a, 0x6f, 0xec, 0x05,
|
||||
0xbe, 0x2b, 0xbc, 0xf1, 0x2e, 0xf2, 0x9f, 0xdc, 0x4e, 0x49, 0x95, 0xe5, 0x9f, 0x07, 0xd1, 0x5d,
|
||||
0xb2, 0x2c, 0xaa, 0x1f, 0x7c, 0xd6, 0xd7, 0x32, 0xea, 0x0f, 0x9f, 0xdf, 0x5a, 0x4f, 0x15, 0xea,
|
||||
0xdf, 0x06, 0xd1, 0xbd, 0x40, 0xa1, 0xea, 0x0e, 0x72, 0x0b, 0xeb, 0x6e, 0x47, 0xf9, 0xe1, 0xed,
|
||||
0x15, 0xa9, 0xe5, 0xde, 0xc6, 0xc7, 0xed, 0x0f, 0x99, 0x04, 0x6c, 0x8f, 0xe9, 0x0f, 0x99, 0x74,
|
||||
0x6b, 0xe1, 0x2d, 0xa8, 0x2a, 0x28, 0x51, 0x99, 0x91, 0x6f, 0x0b, 0x4a, 0xc6, 0x2c, 0x28, 0x23,
|
||||
0x5a, 0xed, 0xe4, 0x7c, 0x4e, 0x5e, 0xbc, 0xc9, 0x59, 0x36, 0xa1, 0x9d, 0xd4, 0xf2, 0x6e, 0x27,
|
||||
0x9a, 0xc3, 0x5b, 0x77, 0x95, 0xf4, 0x94, 0x37, 0x69, 0xde, 0x23, 0x4a, 0x5f, 0x23, 0xc1, 0xad,
|
||||
0xbb, 0x16, 0x4a, 0x78, 0x53, 0x31, 0x6d, 0xc8, 0x1b, 0x0a, 0x65, 0x1f, 0xf7, 0x41, 0x51, 0x02,
|
||||
0xa1, 0xbd, 0xe9, 0x13, 0x81, 0x27, 0x21, 0x2b, 0xad, 0x53, 0x81, 0x8d, 0x9e, 0x34, 0xe1, 0x76,
|
||||
0x0c, 0xe2, 0x4b, 0x60, 0x13, 0x28, 0x82, 0x6e, 0x35, 0xd5, 0xcb, 0xad, 0x4d, 0xfb, 0xdc, 0xee,
|
||||
0xf0, 0x74, 0x3e, 0xcb, 0x54, 0x63, 0x92, 0x6e, 0x6d, 0xaa, 0xdb, 0x2d, 0xa2, 0xf1, 0xa6, 0xa5,
|
||||
0x71, 0x2b, 0xc3, 0xcb, 0xc7, 0x61, 0x33, 0x4e, 0x54, 0xb9, 0xde, 0x8b, 0xa5, 0xeb, 0xa9, 0xba,
|
||||
0x51, 0x47, 0x3d, 0x51, 0x4f, 0xda, 0xe8, 0x49, 0xe3, 0xdd, 0x43, 0xcb, 0xad, 0xee, 0x4f, 0x9b,
|
||||
0x1d, 0xb6, 0x5a, 0x5d, 0x6a, 0xab, 0xbf, 0x02, 0xde, 0xab, 0x55, 0xbd, 0xaa, 0xca, 0x8b, 0xf6,
|
||||
0x92, 0x34, 0x1d, 0xae, 0x07, 0xba, 0x49, 0x03, 0x05, 0xf7, 0x6a, 0x3d, 0x30, 0xd1, 0x93, 0x9b,
|
||||
0xbd, 0xcd, 0x6c, 0xd8, 0x65, 0x47, 0x52, 0xbd, 0x7a, 0xb2, 0x4d, 0xa3, 0xfd, 0x36, 0xeb, 0x51,
|
||||
0xeb, 0xda, 0x8e, 0xc2, 0x0f, 0xae, 0x55, 0xe1, 0xcd, 0xde, 0x3c, 0xba, 0x0c, 0x20, 0x29, 0xb9,
|
||||
0xb2, 0x3c, 0xa0, 0x4c, 0x38, 0x2b, 0xc9, 0xc3, 0x0e, 0x0a, 0xed, 0x59, 0xd6, 0xc3, 0xe8, 0x75,
|
||||
0x32, 0x99, 0x82, 0xf0, 0x9e, 0x63, 0xd9, 0x40, 0xf0, 0x1c, 0x0b, 0x81, 0xa8, 0xe9, 0xea, 0xdf,
|
||||
0xf5, 0x66, 0xed, 0xc1, 0xc4, 0xd7, 0x74, 0x4a, 0xd9, 0xa2, 0x42, 0x4d, 0xe7, 0xa5, 0xd1, 0x6c,
|
||||
0xa0, 0xdd, 0xaa, 0x97, 0xd6, 0x1f, 0x87, 0xcc, 0xa0, 0x37, 0xd7, 0xd7, 0x7b, 0xb1, 0x68, 0x45,
|
||||
0x31, 0x0e, 0x93, 0x59, 0x22, 0x7c, 0x2b, 0x8a, 0x65, 0xa3, 0x42, 0x42, 0x2b, 0x4a, 0x1b, 0xa5,
|
||||
0xaa, 0x57, 0xc5, 0x08, 0x07, 0x93, 0x70, 0xf5, 0x6a, 0xa6, 0x5f, 0xf5, 0x34, 0xdb, 0x3a, 0x76,
|
||||
0xcd, 0x74, 0x97, 0x11, 0x57, 0x2a, 0x59, 0xf6, 0xf4, 0x6d, 0xf9, 0x5a, 0x25, 0x06, 0x43, 0xb3,
|
||||
0x0e, 0xa5, 0x80, 0x8f, 0x13, 0x2a, 0xae, 0x39, 0x19, 0xce, 0x73, 0x60, 0x05, 0xcb, 0x62, 0x6f,
|
||||
0x72, 0x2a, 0x0d, 0xb6, 0xc8, 0x50, 0x72, 0x4a, 0x6a, 0xa0, 0x43, 0x7d, 0xf7, 0x85, 0x48, 0xcf,
|
||||
0x50, 0xd0, 0x6f, 0x1e, 0xba, 0xef, 0x43, 0x3e, 0xea, 0x41, 0xe2, 0x43, 0xfd, 0x06, 0xd0, 0xdb,
|
||||
0xf2, 0xb5, 0xd3, 0x8f, 0x03, 0xa6, 0x5c, 0x34, 0x94, 0x08, 0xd3, 0x2a, 0xa8, 0x53, 0xeb, 0x00,
|
||||
0x17, 0xc4, 0x8f, 0x61, 0xe9, 0xeb, 0xd4, 0x26, 0x3e, 0x95, 0x48, 0xa8, 0x53, 0xb7, 0x51, 0x14,
|
||||
0x67, 0xda, 0x79, 0xd0, 0x4a, 0x40, 0xdf, 0x4e, 0x7d, 0x56, 0x3b, 0x39, 0x34, 0x72, 0x76, 0x93,
|
||||
0x85, 0x73, 0x8a, 0xe1, 0x29, 0xe8, 0x6e, 0xb2, 0xf0, 0x1f, 0x62, 0xac, 0xf7, 0x62, 0xf1, 0x85,
|
||||
0x01, 0x26, 0xe0, 0x4d, 0x73, 0x92, 0xef, 0x29, 0xae, 0x94, 0xb7, 0x8e, 0xf2, 0xd7, 0xba, 0x41,
|
||||
0x73, 0x3d, 0xf7, 0xa4, 0xe0, 0x31, 0x94, 0xa5, 0xfa, 0xba, 0x9b, 0x7b, 0xff, 0x49, 0xc9, 0x46,
|
||||
0xe8, 0xdb, 0x6e, 0x0f, 0xc2, 0x90, 0xb2, 0xfd, 0x65, 0xf4, 0xf6, 0x21, 0x9f, 0x8e, 0x21, 0x9b,
|
||||
0x0c, 0x7f, 0xe0, 0x5e, 0x88, 0xe5, 0xd3, 0x51, 0xf5, 0xb3, 0xb6, 0x77, 0x87, 0x12, 0x9b, 0x2b,
|
||||
0x7d, 0xbb, 0x70, 0x31, 0x9f, 0x8e, 0x05, 0x13, 0xe8, 0x4a, 0x9f, 0xfc, 0x7d, 0x54, 0x09, 0x88,
|
||||
0x2b, 0x7d, 0x0e, 0x80, 0xec, 0x9d, 0x15, 0x00, 0x5e, 0x7b, 0x95, 0x20, 0x68, 0x4f, 0x01, 0x66,
|
||||
0xd5, 0xd5, 0xf6, 0xaa, 0xc0, 0x16, 0x5f, 0xc1, 0x33, 0x3a, 0x52, 0x4a, 0xac, 0xba, 0x6d, 0xca,
|
||||
0x74, 0x86, 0xba, 0xfa, 0xf2, 0x5b, 0x16, 0xf3, 0xd9, 0x8c, 0x15, 0x4b, 0xd4, 0x19, 0x54, 0x2d,
|
||||
0x2d, 0x80, 0xe8, 0x0c, 0x5e, 0xd0, 0xf4, 0xf2, 0xe6, 0x31, 0xc7, 0xd7, 0xfb, 0xbc, 0xe0, 0x73,
|
||||
0x91, 0x64, 0x80, 0xbf, 0x67, 0xa0, 0x1f, 0xa8, 0xcd, 0x10, 0xbd, 0x9c, 0x62, 0x4d, 0x54, 0x28,
|
||||
0x89, 0xfa, 0x76, 0xa0, 0xfc, 0x46, 0x6a, 0x29, 0x78, 0x81, 0x4f, 0x07, 0x6b, 0x2b, 0x18, 0x22,
|
||||
0xa2, 0x42, 0x12, 0x46, 0x6d, 0x7f, 0x92, 0x64, 0x53, 0x6f, 0xdb, 0x9f, 0xd8, 0x5f, 0x18, 0xbc,
|
||||
0x47, 0x03, 0x66, 0x7e, 0xaf, 0x1f, 0x5a, 0xfd, 0xcd, 0x20, 0xf5, 0x7e, 0xa4, 0xf7, 0xa1, 0xdb,
|
||||
0x04, 0x31, 0xbf, 0xfb, 0x49, 0xe4, 0xea, 0x65, 0x0e, 0x19, 0x4c, 0x9a, 0x3b, 0x70, 0x3e, 0x57,
|
||||
0x0e, 0x11, 0x74, 0x85, 0x49, 0xd3, 0x15, 0x8e, 0x40, 0x14, 0x49, 0x5c, 0x8e, 0x41, 0x9c, 0xb0,
|
||||
0x82, 0xcd, 0x40, 0x40, 0x81, 0xbb, 0x82, 0x42, 0x46, 0x0e, 0x43, 0x74, 0x05, 0x8a, 0x55, 0x0e,
|
||||
0x7f, 0x3f, 0x7a, 0xb7, 0x9a, 0x09, 0x21, 0x53, 0x1f, 0x6d, 0x7f, 0x21, 0xff, 0xda, 0xc3, 0xf0,
|
||||
0x3d, 0x6d, 0x63, 0x2c, 0x0a, 0x60, 0xb3, 0xc6, 0xf6, 0x3b, 0xfa, 0x77, 0x09, 0x6e, 0x0d, 0xaa,
|
||||
0x75, 0xe0, 0x98, 0x8b, 0xe4, 0xb2, 0x4a, 0x3c, 0xd4, 0x31, 0x0f, 0x5a, 0x07, 0x6c, 0xf1, 0x28,
|
||||
0xf0, 0x36, 0xbd, 0x8f, 0x33, 0x23, 0xd1, 0x96, 0x9e, 0x42, 0x9e, 0xe2, 0x91, 0xe8, 0x68, 0x4b,
|
||||
0x80, 0x18, 0x89, 0x5e, 0xd0, 0x2c, 0x6a, 0xb6, 0xf8, 0x0c, 0xc2, 0x95, 0x39, 0x83, 0x7e, 0x95,
|
||||
0x39, 0x73, 0x2e, 0xd1, 0xa7, 0xd1, 0xbb, 0x47, 0x30, 0xbb, 0x80, 0xa2, 0xbc, 0x4a, 0xf2, 0xfd,
|
||||
0x6a, 0x09, 0x62, 0x62, 0x8e, 0x5f, 0x30, 0x33, 0xc4, 0x48, 0x23, 0xc4, 0x3a, 0x4d, 0xa0, 0x66,
|
||||
0xac, 0x1b, 0xe0, 0xa0, 0x3c, 0x66, 0x33, 0x90, 0xdf, 0x06, 0x18, 0xae, 0x53, 0x46, 0x2c, 0x88,
|
||||
0x18, 0xeb, 0x24, 0x6c, 0xbd, 0x8f, 0x63, 0x98, 0x53, 0x98, 0x56, 0x3d, 0xac, 0x38, 0x61, 0xcb,
|
||||
0x19, 0x64, 0x42, 0x99, 0x44, 0xbb, 0x94, 0x96, 0x49, 0x3f, 0x4f, 0xec, 0x52, 0xf6, 0xd1, 0xb3,
|
||||
0xa2, 0x52, 0xe7, 0xc1, 0x9f, 0xf0, 0x42, 0xd4, 0x7f, 0x92, 0xe1, 0xbc, 0x48, 0x51, 0x54, 0xea,
|
||||
0x3e, 0x54, 0x87, 0x24, 0xa2, 0xd2, 0xb0, 0x86, 0xf5, 0x2d, 0x63, 0xa7, 0x0c, 0xaf, 0xa0, 0xd0,
|
||||
0xfd, 0xe4, 0xc5, 0x8c, 0x25, 0xa9, 0xea, 0x0d, 0x5f, 0x04, 0x6c, 0x13, 0x3a, 0xc4, 0xb7, 0x8c,
|
||||
0xfb, 0xea, 0x5a, 0x5f, 0x7f, 0x0e, 0x97, 0x10, 0x6d, 0x9a, 0x76, 0xd8, 0x27, 0x36, 0x4d, 0xbb,
|
||||
0xb5, 0x4c, 0x2e, 0x63, 0x58, 0xc9, 0x2d, 0x25, 0xb1, 0xc3, 0x27, 0x78, 0x07, 0xc5, 0xb2, 0x89,
|
||||
0x40, 0x22, 0x97, 0x09, 0x2a, 0x98, 0xc9, 0xdf, 0x60, 0x7b, 0x49, 0xc6, 0xd2, 0xe4, 0xa7, 0xf8,
|
||||
0x72, 0xb0, 0x65, 0xa7, 0x21, 0x88, 0xc9, 0xdf, 0x4f, 0xfa, 0x5c, 0xed, 0x83, 0x38, 0x4b, 0xaa,
|
||||
0xa9, 0x7f, 0x2d, 0xf0, 0xdc, 0x24, 0xd1, 0xed, 0xca, 0x22, 0x95, 0xab, 0x9f, 0x0d, 0xa2, 0xbb,
|
||||
0xf8, 0xb1, 0x6e, 0xe7, 0xf9, 0xb8, 0x5a, 0xb3, 0x4f, 0x21, 0x86, 0x24, 0x17, 0xc3, 0x4f, 0xc3,
|
||||
0xcf, 0x0a, 0xe1, 0xc4, 0xd1, 0x73, 0x0f, 0x35, 0xeb, 0x40, 0xb3, 0x9a, 0x4b, 0xc6, 0xf5, 0xdf,
|
||||
0x2a, 0x3a, 0x2f, 0xa1, 0x50, 0x9f, 0xe1, 0xde, 0x07, 0x81, 0x46, 0xa7, 0xc5, 0x8d, 0x2c, 0xb0,
|
||||
0xaa, 0x28, 0x31, 0x3a, 0xc3, 0x1a, 0x66, 0xfb, 0xc3, 0xe2, 0x4e, 0xa1, 0xe4, 0xe9, 0x02, 0xe4,
|
||||
0xfd, 0xb0, 0x27, 0xa4, 0x31, 0x8b, 0x22, 0xb6, 0x3f, 0x68, 0xda, 0x5c, 0x6e, 0x6c, 0xbb, 0xdd,
|
||||
0xce, 0x96, 0x07, 0xf8, 0x10, 0xd9, 0x63, 0x49, 0x62, 0xc4, 0xc9, 0x56, 0x00, 0xb7, 0xb6, 0x07,
|
||||
0x0b, 0xce, 0x26, 0x31, 0x2b, 0xc5, 0x09, 0x5b, 0xa6, 0x9c, 0x4d, 0xe4, 0xba, 0x8e, 0xb7, 0x07,
|
||||
0x1b, 0x66, 0x64, 0x43, 0xd4, 0xf6, 0x20, 0x05, 0xd7, 0x3e, 0x9f, 0x7f, 0xf8, 0x3f, 0x5f, 0xdf,
|
||||
0x19, 0xfc, 0xfc, 0xeb, 0x3b, 0x83, 0xff, 0xff, 0xfa, 0xce, 0xe0, 0x67, 0xdf, 0xdc, 0x79, 0xeb,
|
||||
0xe7, 0xdf, 0xdc, 0x79, 0xeb, 0xff, 0xbe, 0xb9, 0xf3, 0xd6, 0x57, 0x6f, 0xab, 0x3f, 0x53, 0x75,
|
||||
0xf1, 0x4b, 0xf2, 0x8f, 0x4d, 0x3d, 0xfb, 0x45, 0x00, 0x00, 0x00, 0xff, 0xff, 0x71, 0x16, 0x84,
|
||||
0x92, 0xca, 0x6a, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
|
@ -400,6 +402,7 @@ type ClientCommandsHandler interface {
|
|||
ObjectCreateSet(context.Context, *pb.RpcObjectCreateSetRequest) *pb.RpcObjectCreateSetResponse
|
||||
ObjectGraph(context.Context, *pb.RpcObjectGraphRequest) *pb.RpcObjectGraphResponse
|
||||
ObjectSearch(context.Context, *pb.RpcObjectSearchRequest) *pb.RpcObjectSearchResponse
|
||||
ObjectSearchWithMeta(context.Context, *pb.RpcObjectSearchWithMetaRequest) *pb.RpcObjectSearchWithMetaResponse
|
||||
ObjectSearchSubscribe(context.Context, *pb.RpcObjectSearchSubscribeRequest) *pb.RpcObjectSearchSubscribeResponse
|
||||
ObjectSubscribeIds(context.Context, *pb.RpcObjectSubscribeIdsRequest) *pb.RpcObjectSubscribeIdsResponse
|
||||
ObjectGroupsSubscribe(context.Context, *pb.RpcObjectGroupsSubscribeRequest) *pb.RpcObjectGroupsSubscribeResponse
|
||||
|
@ -461,10 +464,11 @@ type ClientCommandsHandler interface {
|
|||
HistoryShowVersion(context.Context, *pb.RpcHistoryShowVersionRequest) *pb.RpcHistoryShowVersionResponse
|
||||
HistoryGetVersions(context.Context, *pb.RpcHistoryGetVersionsRequest) *pb.RpcHistoryGetVersionsResponse
|
||||
HistorySetVersion(context.Context, *pb.RpcHistorySetVersionRequest) *pb.RpcHistorySetVersionResponse
|
||||
HistoryDiffVersions(context.Context, *pb.RpcHistoryDiffVersionsRequest) *pb.RpcHistoryDiffVersionsResponse
|
||||
// Files
|
||||
// ***
|
||||
FileOffload(context.Context, *pb.RpcFileOffloadRequest) *pb.RpcFileOffloadResponse
|
||||
FileSpaceOffload(context.Context, *pb.RpcFileSpaceOffloadRequest) *pb.RpcFileSpaceOffloadResponse
|
||||
FileReconcile(context.Context, *pb.RpcFileReconcileRequest) *pb.RpcFileReconcileResponse
|
||||
FileListOffload(context.Context, *pb.RpcFileListOffloadRequest) *pb.RpcFileListOffloadResponse
|
||||
FileUpload(context.Context, *pb.RpcFileUploadRequest) *pb.RpcFileUploadResponse
|
||||
FileDownload(context.Context, *pb.RpcFileDownloadRequest) *pb.RpcFileDownloadResponse
|
||||
|
@ -609,6 +613,7 @@ type ClientCommandsHandler interface {
|
|||
// Get current subscription status (tier, expiration date, etc.)
|
||||
// WARNING: can be cached by Anytype Heart
|
||||
MembershipGetStatus(context.Context, *pb.RpcMembershipGetStatusRequest) *pb.RpcMembershipGetStatusResponse
|
||||
// Check if the requested name is valid and vacant for the requested tier
|
||||
MembershipIsNameValid(context.Context, *pb.RpcMembershipIsNameValidRequest) *pb.RpcMembershipIsNameValidResponse
|
||||
// Buy a subscription, will return a payment URL. The user should be redirected to this URL to complete the payment.
|
||||
MembershipRegisterPaymentRequest(context.Context, *pb.RpcMembershipRegisterPaymentRequestRequest) *pb.RpcMembershipRegisterPaymentRequestResponse
|
||||
|
@ -1722,6 +1727,26 @@ func ObjectSearch(b []byte) (resp []byte) {
|
|||
return resp
|
||||
}
|
||||
|
||||
func ObjectSearchWithMeta(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
if r := recover(); r != nil {
|
||||
resp, _ = (&pb.RpcObjectSearchWithMetaResponse{Error: &pb.RpcObjectSearchWithMetaResponseError{Code: pb.RpcObjectSearchWithMetaResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
|
||||
PanicHandler(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
in := new(pb.RpcObjectSearchWithMetaRequest)
|
||||
if err := in.Unmarshal(b); err != nil {
|
||||
resp, _ = (&pb.RpcObjectSearchWithMetaResponse{Error: &pb.RpcObjectSearchWithMetaResponseError{Code: pb.RpcObjectSearchWithMetaResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
resp, _ = clientCommandsHandler.ObjectSearchWithMeta(context.Background(), in).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
func ObjectSearchSubscribe(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
|
@ -2742,6 +2767,46 @@ func HistorySetVersion(b []byte) (resp []byte) {
|
|||
return resp
|
||||
}
|
||||
|
||||
func HistoryDiffVersions(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
if r := recover(); r != nil {
|
||||
resp, _ = (&pb.RpcHistoryDiffVersionsResponse{Error: &pb.RpcHistoryDiffVersionsResponseError{Code: pb.RpcHistoryDiffVersionsResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
|
||||
PanicHandler(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
in := new(pb.RpcHistoryDiffVersionsRequest)
|
||||
if err := in.Unmarshal(b); err != nil {
|
||||
resp, _ = (&pb.RpcHistoryDiffVersionsResponse{Error: &pb.RpcHistoryDiffVersionsResponseError{Code: pb.RpcHistoryDiffVersionsResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
resp, _ = clientCommandsHandler.HistoryDiffVersions(context.Background(), in).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
func FileOffload(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
if r := recover(); r != nil {
|
||||
resp, _ = (&pb.RpcFileOffloadResponse{Error: &pb.RpcFileOffloadResponseError{Code: pb.RpcFileOffloadResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
|
||||
PanicHandler(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
in := new(pb.RpcFileOffloadRequest)
|
||||
if err := in.Unmarshal(b); err != nil {
|
||||
resp, _ = (&pb.RpcFileOffloadResponse{Error: &pb.RpcFileOffloadResponseError{Code: pb.RpcFileOffloadResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
resp, _ = clientCommandsHandler.FileOffload(context.Background(), in).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
func FileSpaceOffload(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
|
@ -2762,26 +2827,6 @@ func FileSpaceOffload(b []byte) (resp []byte) {
|
|||
return resp
|
||||
}
|
||||
|
||||
func FileReconcile(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
if r := recover(); r != nil {
|
||||
resp, _ = (&pb.RpcFileReconcileResponse{Error: &pb.RpcFileReconcileResponseError{Code: pb.RpcFileReconcileResponseError_UNKNOWN_ERROR, Description: "panic recovered"}}).Marshal()
|
||||
PanicHandler(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
in := new(pb.RpcFileReconcileRequest)
|
||||
if err := in.Unmarshal(b); err != nil {
|
||||
resp, _ = (&pb.RpcFileReconcileResponse{Error: &pb.RpcFileReconcileResponseError{Code: pb.RpcFileReconcileResponseError_BAD_INPUT, Description: err.Error()}}).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
resp, _ = clientCommandsHandler.FileReconcile(context.Background(), in).Marshal()
|
||||
return resp
|
||||
}
|
||||
|
||||
func FileListOffload(b []byte) (resp []byte) {
|
||||
defer func() {
|
||||
if PanicHandler != nil {
|
||||
|
@ -5596,6 +5641,8 @@ func CommandAsync(cmd string, data []byte, callback func(data []byte)) {
|
|||
cd = ObjectGraph(data)
|
||||
case "ObjectSearch":
|
||||
cd = ObjectSearch(data)
|
||||
case "ObjectSearchWithMeta":
|
||||
cd = ObjectSearchWithMeta(data)
|
||||
case "ObjectSearchSubscribe":
|
||||
cd = ObjectSearchSubscribe(data)
|
||||
case "ObjectSubscribeIds":
|
||||
|
@ -5698,10 +5745,12 @@ func CommandAsync(cmd string, data []byte, callback func(data []byte)) {
|
|||
cd = HistoryGetVersions(data)
|
||||
case "HistorySetVersion":
|
||||
cd = HistorySetVersion(data)
|
||||
case "HistoryDiffVersions":
|
||||
cd = HistoryDiffVersions(data)
|
||||
case "FileOffload":
|
||||
cd = FileOffload(data)
|
||||
case "FileSpaceOffload":
|
||||
cd = FileSpaceOffload(data)
|
||||
case "FileReconcile":
|
||||
cd = FileReconcile(data)
|
||||
case "FileListOffload":
|
||||
cd = FileListOffload(data)
|
||||
case "FileUpload":
|
||||
|
@ -6750,6 +6799,20 @@ func (h *ClientCommandsHandlerProxy) ObjectSearch(ctx context.Context, req *pb.R
|
|||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcObjectSearchResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) ObjectSearchWithMeta(ctx context.Context, req *pb.RpcObjectSearchWithMetaRequest) *pb.RpcObjectSearchWithMetaResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.ObjectSearchWithMeta(ctx, req.(*pb.RpcObjectSearchWithMetaRequest)), nil
|
||||
}
|
||||
for _, interceptor := range h.interceptors {
|
||||
toCall := actualCall
|
||||
currentInterceptor := interceptor
|
||||
actualCall = func(ctx context.Context, req any) (any, error) {
|
||||
return currentInterceptor(ctx, req, "ObjectSearchWithMeta", toCall)
|
||||
}
|
||||
}
|
||||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcObjectSearchWithMetaResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) ObjectSearchSubscribe(ctx context.Context, req *pb.RpcObjectSearchSubscribeRequest) *pb.RpcObjectSearchSubscribeResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.ObjectSearchSubscribe(ctx, req.(*pb.RpcObjectSearchSubscribeRequest)), nil
|
||||
|
@ -7464,6 +7527,34 @@ func (h *ClientCommandsHandlerProxy) HistorySetVersion(ctx context.Context, req
|
|||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcHistorySetVersionResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) HistoryDiffVersions(ctx context.Context, req *pb.RpcHistoryDiffVersionsRequest) *pb.RpcHistoryDiffVersionsResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.HistoryDiffVersions(ctx, req.(*pb.RpcHistoryDiffVersionsRequest)), nil
|
||||
}
|
||||
for _, interceptor := range h.interceptors {
|
||||
toCall := actualCall
|
||||
currentInterceptor := interceptor
|
||||
actualCall = func(ctx context.Context, req any) (any, error) {
|
||||
return currentInterceptor(ctx, req, "HistoryDiffVersions", toCall)
|
||||
}
|
||||
}
|
||||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcHistoryDiffVersionsResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) FileOffload(ctx context.Context, req *pb.RpcFileOffloadRequest) *pb.RpcFileOffloadResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.FileOffload(ctx, req.(*pb.RpcFileOffloadRequest)), nil
|
||||
}
|
||||
for _, interceptor := range h.interceptors {
|
||||
toCall := actualCall
|
||||
currentInterceptor := interceptor
|
||||
actualCall = func(ctx context.Context, req any) (any, error) {
|
||||
return currentInterceptor(ctx, req, "FileOffload", toCall)
|
||||
}
|
||||
}
|
||||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcFileOffloadResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) FileSpaceOffload(ctx context.Context, req *pb.RpcFileSpaceOffloadRequest) *pb.RpcFileSpaceOffloadResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.FileSpaceOffload(ctx, req.(*pb.RpcFileSpaceOffloadRequest)), nil
|
||||
|
@ -7478,20 +7569,6 @@ func (h *ClientCommandsHandlerProxy) FileSpaceOffload(ctx context.Context, req *
|
|||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcFileSpaceOffloadResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) FileReconcile(ctx context.Context, req *pb.RpcFileReconcileRequest) *pb.RpcFileReconcileResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.FileReconcile(ctx, req.(*pb.RpcFileReconcileRequest)), nil
|
||||
}
|
||||
for _, interceptor := range h.interceptors {
|
||||
toCall := actualCall
|
||||
currentInterceptor := interceptor
|
||||
actualCall = func(ctx context.Context, req any) (any, error) {
|
||||
return currentInterceptor(ctx, req, "FileReconcile", toCall)
|
||||
}
|
||||
}
|
||||
call, _ := actualCall(ctx, req)
|
||||
return call.(*pb.RpcFileReconcileResponse)
|
||||
}
|
||||
func (h *ClientCommandsHandlerProxy) FileListOffload(ctx context.Context, req *pb.RpcFileListOffloadRequest) *pb.RpcFileListOffloadResponse {
|
||||
actualCall := func(ctx context.Context, req any) (any, error) {
|
||||
return h.client.FileListOffload(ctx, req.(*pb.RpcFileListOffloadRequest)), nil
|
||||
|
|
|
@ -139,40 +139,6 @@ func handleZip(input, output string) {
|
|||
}
|
||||
}
|
||||
|
||||
func handleDirectory(input, output string) {
|
||||
err := filepath.Walk(input, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
// Get relative path
|
||||
rel, err := filepath.Rel(input, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outputFile := filepath.Join(output, rel)
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
processFile(File{
|
||||
Name: f.Name(),
|
||||
RC: f,
|
||||
}, outputFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to process directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func createZipFromDirectory(input, output string) {
|
||||
// create a new zip file
|
||||
newZipFile, err := os.Create(output)
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/samber/lo"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/widget"
|
||||
|
@ -214,39 +213,6 @@ func validateBlockLinks(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
func validateFileKeys(s *pb.SnapshotWithType, _ *useCaseInfo) (err error) {
|
||||
id := pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
for _, r := range s.Snapshot.Data.RelationLinks {
|
||||
if r.Format == model.RelationFormat_file || r.Key == bundle.RelationKeyCoverId.String() {
|
||||
for _, hash := range pbtypes.GetStringList(s.Snapshot.GetData().GetDetails(), r.Key) {
|
||||
if r.Format != model.RelationFormat_file {
|
||||
_, err := cid.Parse(hash)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !snapshotHasKeyForHash(s, hash) {
|
||||
err = multierror.Append(err, fmt.Errorf("object '%s' has file detail '%s' has hash '%s' which keys are not in the snapshot", id, r.Key, hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, b := range s.Snapshot.Data.Blocks {
|
||||
if v, ok := simple.New(b).(simple.FileHashes); ok {
|
||||
hashes := v.FillFileHashes([]string{})
|
||||
if len(hashes) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, hash := range hashes {
|
||||
if !snapshotHasKeyForHash(s, hash) {
|
||||
err = multierror.Append(err, fmt.Errorf("file block '%s' of object '%s' has hash '%s' which keys are not in the snapshot", b.Id, id, hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func validateDeleted(s *pb.SnapshotWithType, _ *useCaseInfo) error {
|
||||
id := pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
|
||||
|
@ -294,15 +260,6 @@ func getRelationLinkByKey(links []*model.RelationLink, key string) *model.Relati
|
|||
return nil
|
||||
}
|
||||
|
||||
func snapshotHasKeyForHash(s *pb.SnapshotWithType, hash string) bool {
|
||||
for _, k := range s.Snapshot.FileKeys {
|
||||
if k.Hash == hash && len(k.Keys) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isLinkRelation(k string) bool {
|
||||
return k == bundle.RelationKeyLinks.String() || k == bundle.RelationKeySourceObject.String() || k == bundle.RelationKeyBacklinks.String()
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/anyproto/any-sync/accountservice"
|
||||
"github.com/anyproto/any-sync/app"
|
||||
|
@ -59,7 +58,6 @@ type service struct {
|
|||
coordClient coordinatorclient.CoordinatorClient
|
||||
|
||||
picker cache.ObjectGetter
|
||||
once sync.Once
|
||||
personalSpaceId string
|
||||
}
|
||||
|
||||
|
|
|
@ -194,8 +194,6 @@ func Bootstrap(a *app.App, components ...app.Component) {
|
|||
a.Register(c)
|
||||
}
|
||||
|
||||
const fileWatcherUpdateInterval = 5 * time.Second
|
||||
|
||||
a.
|
||||
// Data storages
|
||||
Register(clientds.New()).
|
||||
|
@ -258,7 +256,7 @@ func Bootstrap(a *app.App, components ...app.Component) {
|
|||
Register(treemanager.New()).
|
||||
Register(block.New()).
|
||||
Register(indexer.New()).
|
||||
Register(syncstatus.New(fileWatcherUpdateInterval)).
|
||||
Register(syncstatus.New()).
|
||||
Register(history.New()).
|
||||
Register(gateway.New()).
|
||||
Register(export.New()).
|
||||
|
|
|
@ -82,6 +82,10 @@ type Config struct {
|
|||
nodeConf nodeconf.Configuration
|
||||
}
|
||||
|
||||
func (c *Config) IsLocalOnlyMode() bool {
|
||||
return c.NetworkMode == pb.RpcAccount_LocalOnly
|
||||
}
|
||||
|
||||
type FSConfig struct {
|
||||
IPFSStorageAddr string
|
||||
}
|
||||
|
|
|
@ -82,15 +82,14 @@ func (mw *Middleware) ObjectOpen(cctx context.Context, req *pb.RpcObjectOpenRequ
|
|||
return m
|
||||
}
|
||||
|
||||
id := domain.FullID{
|
||||
SpaceID: req.SpaceId,
|
||||
ObjectID: req.ObjectId,
|
||||
}
|
||||
err := mw.doBlockService(func(bs *block.Service) (err error) {
|
||||
id := domain.FullID{
|
||||
SpaceID: req.SpaceId,
|
||||
ObjectID: req.ObjectId,
|
||||
}
|
||||
obj, err = bs.OpenBlock(ctx, id, req.IncludeRelationsAsDependentObjects)
|
||||
return err
|
||||
})
|
||||
|
||||
code := mapErrorCode(err,
|
||||
errToCode(spacestorage.ErrTreeStorageAlreadyDeleted, pb.RpcObjectOpenResponseError_OBJECT_DELETED),
|
||||
errToCode(source.ErrUnknownDataFormat, pb.RpcObjectOpenResponseError_ANYTYPE_NEEDS_UPGRADE),
|
||||
|
@ -111,15 +110,14 @@ func (mw *Middleware) ObjectShow(cctx context.Context, req *pb.RpcObjectShowRequ
|
|||
return m
|
||||
}
|
||||
|
||||
id := domain.FullID{
|
||||
SpaceID: req.SpaceId,
|
||||
ObjectID: req.ObjectId,
|
||||
}
|
||||
err := mw.doBlockService(func(bs *block.Service) (err error) {
|
||||
id := domain.FullID{
|
||||
SpaceID: req.SpaceId,
|
||||
ObjectID: req.ObjectId,
|
||||
}
|
||||
obj, err = bs.ShowBlock(id, req.IncludeRelationsAsDependentObjects)
|
||||
return err
|
||||
})
|
||||
|
||||
code := mapErrorCode(err,
|
||||
errToCode(spacestorage.ErrTreeStorageAlreadyDeleted, pb.RpcObjectShowResponseError_OBJECT_DELETED),
|
||||
errToCode(source.ErrUnknownDataFormat, pb.RpcObjectShowResponseError_ANYTYPE_NEEDS_UPGRADE),
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
|
@ -240,7 +241,7 @@ func (s *service) ContentUpdaters(spaceID string, url string, parseBlock bool) (
|
|||
|
||||
updaters := make(chan func(contentBookmark *bookmark.ObjectContent), 1)
|
||||
|
||||
data, body, err := s.linkPreview.Fetch(ctx, url)
|
||||
data, body, isFile, err := s.linkPreview.Fetch(ctx, url)
|
||||
if err != nil {
|
||||
updaters <- func(c *bookmark.ObjectContent) {
|
||||
if c.BookmarkContent == nil {
|
||||
|
@ -312,6 +313,10 @@ func (s *service) ContentUpdaters(spaceID string, url string, parseBlock bool) (
|
|||
go func() {
|
||||
defer wg.Done()
|
||||
updaters <- func(c *bookmark.ObjectContent) {
|
||||
if isFile {
|
||||
s.handleFileBlock(c, url)
|
||||
return
|
||||
}
|
||||
blocks, _, err := anymark.HTMLToBlocks(body, url)
|
||||
if err != nil {
|
||||
log.Errorf("parse blocks: %s", err)
|
||||
|
@ -328,6 +333,19 @@ func (s *service) ContentUpdaters(spaceID string, url string, parseBlock bool) (
|
|||
return updaters, nil
|
||||
}
|
||||
|
||||
func (s *service) handleFileBlock(c *bookmark.ObjectContent, url string) {
|
||||
c.Blocks = append(
|
||||
c.Blocks,
|
||||
&model.Block{
|
||||
Id: bson.NewObjectId().Hex(),
|
||||
Content: &model.BlockContentOfFile{
|
||||
File: &model.BlockContentFile{
|
||||
Name: url,
|
||||
}},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (s *service) fetcher(spaceID string, blockID string, params bookmark.FetchParams) error {
|
||||
updaters, err := s.ContentUpdaters(spaceID, params.Url, false)
|
||||
if err != nil {
|
||||
|
|
67
core/block/bookmark/bookmark_service_test.go
Normal file
67
core/block/bookmark/bookmark_service_test.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package bookmark
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/linkpreview/mock_linkpreview"
|
||||
)
|
||||
|
||||
func TestService_FetchBookmarkContent(t *testing.T) {
|
||||
t.Run("link to html page - create blocks", func(t *testing.T) {
|
||||
// given
|
||||
preview := mock_linkpreview.NewMockLinkPreview(t)
|
||||
preview.EXPECT().Fetch(mock.Anything, "http://test.com").Return(model.LinkPreview{}, []byte(testHtml), false, nil)
|
||||
|
||||
s := &service{linkPreview: preview}
|
||||
|
||||
// when
|
||||
updaters := s.FetchBookmarkContent("space", "http://test.com", true)
|
||||
|
||||
// then
|
||||
content := updaters()
|
||||
assert.Len(t, content.Blocks, 2)
|
||||
})
|
||||
t.Run("link to file - create one block with file", func(t *testing.T) {
|
||||
// given
|
||||
preview := mock_linkpreview.NewMockLinkPreview(t)
|
||||
preview.EXPECT().Fetch(mock.Anything, "http://test.com").Return(model.LinkPreview{}, nil, true, nil)
|
||||
|
||||
s := &service{linkPreview: preview}
|
||||
|
||||
// when
|
||||
updaters := s.FetchBookmarkContent("space", "http://test.com", true)
|
||||
|
||||
// then
|
||||
content := updaters()
|
||||
assert.Len(t, content.Blocks, 1)
|
||||
assert.NotNil(t, content.Blocks[0].GetFile())
|
||||
assert.Equal(t, "http://test.com", content.Blocks[0].GetFile().GetName())
|
||||
})
|
||||
t.Run("link to file - create one block with file, image is base64", func(t *testing.T) {
|
||||
// given
|
||||
preview := mock_linkpreview.NewMockLinkPreview(t)
|
||||
preview.EXPECT().Fetch(mock.Anything, "http://test.com").Return(model.LinkPreview{}, []byte(testHtmlBase64), false, nil)
|
||||
|
||||
s := &service{linkPreview: preview}
|
||||
|
||||
// when
|
||||
updaters := s.FetchBookmarkContent("space", "http://test.com", true)
|
||||
|
||||
// then
|
||||
content := updaters()
|
||||
assert.Len(t, content.Blocks, 1)
|
||||
assert.NotNil(t, content.Blocks[0].GetFile())
|
||||
})
|
||||
}
|
||||
|
||||
const testHtml = `<html><head>
|
||||
<title>Title</title>
|
||||
|
||||
Test
|
||||
</head></html>`
|
||||
|
||||
const testHtmlBase64 = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\">"
|
|
@ -239,7 +239,7 @@ func (s *Service) DeleteDataviewView(ctx session.Context, req pb.RpcBlockDatavie
|
|||
|
||||
func (s *Service) SetDataviewActiveView(ctx session.Context, req pb.RpcBlockDataviewViewSetActiveRequest) error {
|
||||
return cache.Do(s, req.ContextId, func(b dataview.Dataview) error {
|
||||
return b.SetActiveView(ctx, req.BlockId, req.ViewId, int(req.Limit), int(req.Offset))
|
||||
return b.SetActiveView(ctx, req.BlockId, req.ViewId)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -493,6 +493,7 @@ func (s *Service) UploadBlockFile(ctx session.Context, req UploadRequest, groupI
|
|||
_, err = b.Upload(ctx, req.BlockId, file.FileSource{
|
||||
Path: req.FilePath,
|
||||
Url: req.Url,
|
||||
Bytes: req.Bytes,
|
||||
GroupID: groupID,
|
||||
Origin: req.ObjectOrigin,
|
||||
}, false)
|
||||
|
@ -505,6 +506,7 @@ func (s *Service) UploadBlockFileSync(ctx session.Context, req UploadRequest) (e
|
|||
_, err = b.Upload(ctx, req.BlockId, file.FileSource{
|
||||
Path: req.FilePath,
|
||||
Url: req.Url,
|
||||
Bytes: req.Bytes,
|
||||
Origin: req.ObjectOrigin,
|
||||
}, true)
|
||||
return err
|
||||
|
@ -534,8 +536,6 @@ func (s *Service) UploadFile(ctx context.Context, spaceId string, req FileUpload
|
|||
upl.SetAdditionalDetails(req.Details)
|
||||
if req.Type != model.BlockContentFile_None {
|
||||
upl.SetType(req.Type)
|
||||
} else {
|
||||
upl.AutoType(true)
|
||||
}
|
||||
if req.LocalPath != "" {
|
||||
upl.SetFile(req.LocalPath)
|
||||
|
@ -576,6 +576,7 @@ func (s *Service) UploadFileBlock(
|
|||
fileObjectId, err = b.Upload(nil, req.BlockId, file.FileSource{
|
||||
Path: req.FilePath,
|
||||
Url: req.Url,
|
||||
Bytes: req.Bytes,
|
||||
GroupID: "",
|
||||
Origin: req.ObjectOrigin,
|
||||
}, true)
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/uri"
|
||||
|
@ -28,11 +27,10 @@ type CreateAndFetchRequest struct {
|
|||
Origin objectorigin.ObjectOrigin
|
||||
}
|
||||
|
||||
func NewBookmark(sb smartblock.SmartBlock, bookmarkSvc BookmarkService, objectStore objectstore.ObjectStore) Bookmark {
|
||||
func NewBookmark(sb smartblock.SmartBlock, bookmarkSvc BookmarkService) Bookmark {
|
||||
return &sbookmark{
|
||||
SmartBlock: sb,
|
||||
bookmarkSvc: bookmarkSvc,
|
||||
objectStore: objectStore,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +48,6 @@ type BookmarkService interface {
|
|||
type sbookmark struct {
|
||||
smartblock.SmartBlock
|
||||
bookmarkSvc BookmarkService
|
||||
objectStore objectstore.ObjectStore
|
||||
}
|
||||
|
||||
type BlockService interface {
|
||||
|
|
|
@ -66,8 +66,14 @@ type clipboard struct {
|
|||
fileObjectService fileobject.Service
|
||||
}
|
||||
|
||||
func (cb *clipboard) Paste(ctx session.Context, req *pb.RpcBlockPasteRequest, groupId string) (blockIds []string, uploadArr []pb.RpcBlockUploadRequest, caretPosition int32, isSameBlockCaret bool, err error) {
|
||||
func (cb *clipboard) Paste(ctx session.Context, req *pb.RpcBlockPasteRequest, groupId string) (
|
||||
blockIds []string, uploadArr []pb.RpcBlockUploadRequest, caretPosition int32, isSameBlockCaret bool, err error,
|
||||
) {
|
||||
caretPosition = -1
|
||||
if err = cb.Restrictions().Object.Check(model.Restrictions_Blocks); err != nil {
|
||||
return nil, nil, caretPosition, false, err
|
||||
}
|
||||
|
||||
if len(req.FileSlot) > 0 {
|
||||
blockIds, err = cb.pasteFiles(ctx, req)
|
||||
return
|
||||
|
@ -251,21 +257,22 @@ func unlinkAndClearBlocks(
|
|||
}
|
||||
|
||||
func assertBlocks(stateBlocks []*model.Block, requestBlocks []*model.Block) (map[string]*model.Block, error) {
|
||||
if len(requestBlocks) == 0 || requestBlocks[0].Id == "" {
|
||||
if len(requestBlocks) == 0 || requestBlocks[0].GetId() == "" {
|
||||
return nil, errors.New("nothing to cut")
|
||||
}
|
||||
|
||||
idToBlockMap := make(map[string]*model.Block)
|
||||
for _, stateBlock := range stateBlocks {
|
||||
idToBlockMap[stateBlock.Id] = stateBlock
|
||||
idToBlockMap[stateBlock.GetId()] = stateBlock
|
||||
}
|
||||
|
||||
for _, requestBlock := range requestBlocks {
|
||||
if requestBlock.Id == "" {
|
||||
reqId := requestBlock.GetId()
|
||||
if reqId == "" {
|
||||
return nil, errors.New("empty requestBlock id")
|
||||
}
|
||||
if stateBlock, ok := idToBlockMap[requestBlock.Id]; !ok {
|
||||
return nil, fmt.Errorf("requestBlock with id %s not found", stateBlock.Id)
|
||||
if _, ok := idToBlockMap[reqId]; !ok {
|
||||
return nil, fmt.Errorf("requestBlock with id %s not found", reqId)
|
||||
}
|
||||
}
|
||||
return idToBlockMap, nil
|
||||
|
@ -575,7 +582,7 @@ func (cb *clipboard) addRelationLinksToDataview(d *model.BlockContentDataview) (
|
|||
}
|
||||
|
||||
func (cb *clipboard) newHTMLConverter(s *state.State) *html.HTML {
|
||||
return html.NewHTMLConverter(cb.SpaceID(), cb.fileService, s, cb.fileObjectService)
|
||||
return html.NewHTMLConverter(cb.fileService, s, cb.fileObjectService)
|
||||
}
|
||||
|
||||
func renderText(s *state.State, ignoreStyle bool) string {
|
||||
|
|
|
@ -22,8 +22,6 @@ import (
|
|||
var emptyMarks [][]*model.BlockContentTextMark
|
||||
|
||||
var bold = model.BlockContentTextMark_Bold
|
||||
var italic = model.BlockContentTextMark_Italic
|
||||
var fontRed = model.BlockContentTextMark_TextColor
|
||||
|
||||
func page(blocks ...*model.Block) (sb *smarttest.SmartTest) {
|
||||
sb = smarttest.New("test")
|
||||
|
@ -116,23 +114,6 @@ func shouldBe(sb *smarttest.SmartTest, t *testing.T, shouldBeBLocks ...*model.Bl
|
|||
}
|
||||
}
|
||||
|
||||
func shouldBeDebug(sb *smarttest.SmartTest, t *testing.T, shouldBeBLocks ...*model.Block) {
|
||||
realBlocks := []*model.Block{}
|
||||
cIds := sb.Pick("test").Model().ChildrenIds
|
||||
for _, cId := range cIds {
|
||||
realBlocks = append(realBlocks, sb.Pick(cId).Model())
|
||||
}
|
||||
fmt.Println(len(realBlocks), len(shouldBeBLocks))
|
||||
|
||||
for i, realBlock := range realBlocks {
|
||||
fmt.Println("Real ", i, realBlock)
|
||||
}
|
||||
|
||||
for i, b := range shouldBeBLocks {
|
||||
fmt.Println("Should ", i, b)
|
||||
}
|
||||
}
|
||||
|
||||
func createBlocks(idsArr []string, textArr []string, marksArr [][]*model.BlockContentTextMark) []*model.Block {
|
||||
blocks := []*model.Block{}
|
||||
for i := 0; i < len(textArr); i++ {
|
||||
|
@ -199,18 +180,6 @@ func checkBlockText(t *testing.T, sb *smarttest.SmartTest, textArr []string) {
|
|||
assert.Equal(t, textArr, textArr2)
|
||||
}
|
||||
|
||||
func checkBlockTextDebug(t *testing.T, sb *smarttest.SmartTest, textArr []string) {
|
||||
for i, _ := range textArr {
|
||||
fmt.Println(textArr[i])
|
||||
}
|
||||
|
||||
fmt.Println("--------")
|
||||
cIds := sb.Pick("test").Model().ChildrenIds
|
||||
for _, c := range cIds {
|
||||
fmt.Println("ID:", sb.Pick(c).Model().Id, "cId:", c, "Text:", sb.Pick(c).Model().GetText())
|
||||
}
|
||||
}
|
||||
|
||||
func checkBlockMarks(t *testing.T, sb *smarttest.SmartTest, marksArr [][]*model.BlockContentTextMark) {
|
||||
cIds := sb.Pick("test").Model().ChildrenIds
|
||||
require.Equal(t, len(cIds), len(marksArr))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package clipboard
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
|
@ -13,6 +14,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock/smarttest"
|
||||
"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/restriction"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
_ "github.com/anyproto/anytype-heart/core/block/simple/base"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple/text"
|
||||
|
@ -617,6 +619,25 @@ func TestClipboard_TitleOps(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
t.Run("paste - when base64 file", func(t *testing.T) {
|
||||
// given
|
||||
sb := smarttest.New("text")
|
||||
require.NoError(t, smartblock.ObjectApplyTemplate(sb, nil, template.WithTitle))
|
||||
sb.Doc = testutil.BuildStateFromAST(blockbuilder.Root(
|
||||
blockbuilder.ID("root"),
|
||||
))
|
||||
|
||||
// when
|
||||
cb := newFixture(t, sb)
|
||||
_, _, _, _, err := cb.Paste(nil, &pb.RpcBlockPasteRequest{
|
||||
HtmlSlot: `<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=">`,
|
||||
}, "")
|
||||
|
||||
// then
|
||||
assert.Equal(t, "image", sb.Doc.Blocks()[len(sb.Doc.Blocks())-1].GetFile().Name)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("single to empty title", func(t *testing.T) {
|
||||
st := withTitle(t, "")
|
||||
cb := newFixture(t, st)
|
||||
|
@ -1058,6 +1079,20 @@ func TestClipboard_TitleOps(t *testing.T) {
|
|||
require.Len(t, anySlot, 1)
|
||||
assert.Equal(t, "it", anySlot[0].GetText().Text)
|
||||
})
|
||||
|
||||
t.Run("do not paste if Blocks restriction is set to smartblock", func(t *testing.T) {
|
||||
// given
|
||||
sb := smarttest.New("test")
|
||||
sb.SetRestrictions(restriction.Restrictions{Object: restriction.ObjectRestrictions{model.Restrictions_Blocks}})
|
||||
cb := newFixture(t, sb)
|
||||
|
||||
// when
|
||||
_, _, _, _, err := cb.Paste(nil, nil, "")
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
assert.True(t, errors.Is(err, restriction.ErrRestricted))
|
||||
})
|
||||
}
|
||||
|
||||
func addDescription(st *smarttest.SmartTest, description string) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package clipboard
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/samber/lo"
|
||||
|
@ -15,6 +17,9 @@ import (
|
|||
textutil "github.com/anyproto/anytype-heart/util/text"
|
||||
)
|
||||
|
||||
const base64ImagePrefix = "data:image"
|
||||
const base64Prefix = ";base64,"
|
||||
|
||||
type pasteCtrl struct {
|
||||
// doc state
|
||||
s *state.State
|
||||
|
@ -310,16 +315,42 @@ func (p *pasteCtrl) removeSelection() {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *pasteCtrl) processFiles() {
|
||||
func (p *pasteCtrl) processFiles() (err error) {
|
||||
p.ps.Iterate(func(b simple.Block) (isContinue bool) {
|
||||
if file := b.Model().GetFile(); file != nil && file.State == model.BlockContentFile_Empty {
|
||||
p.uploadArr = append(p.uploadArr, pb.RpcBlockUploadRequest{
|
||||
BlockId: b.Model().Id,
|
||||
Url: file.Name,
|
||||
})
|
||||
if strings.HasPrefix(file.Name, base64ImagePrefix) {
|
||||
err = p.handleBase64(b, file)
|
||||
if err != nil {
|
||||
log.Errorf("error handling base64 image: %v", err)
|
||||
}
|
||||
} else {
|
||||
p.uploadArr = append(p.uploadArr, pb.RpcBlockUploadRequest{
|
||||
BlockId: b.Model().Id,
|
||||
Url: file.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (p *pasteCtrl) handleBase64(b simple.Block, file *model.BlockContentFile) error {
|
||||
index := strings.Index(file.Name, base64Prefix)
|
||||
if index > 0 {
|
||||
file.Name = file.Name[index+len(base64Prefix):]
|
||||
fileContent, err := base64.StdEncoding.DecodeString(file.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file.Name = "image"
|
||||
p.uploadArr = append(p.uploadArr, pb.RpcBlockUploadRequest{
|
||||
BlockId: b.Model().Id,
|
||||
Bytes: fileContent,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
return errors.New("invalid base64 image")
|
||||
}
|
||||
|
||||
func (p *pasteCtrl) normalize() {
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
|
@ -22,14 +21,12 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/badgerhelper"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
||||
const DefaultDetailsFieldName = "_defaultRecordFields"
|
||||
|
||||
var log = logging.Logger("anytype-mw-editor-dataview")
|
||||
var ErrMultiupdateWasNotAllowed = fmt.Errorf("multiupdate was not allowed")
|
||||
|
||||
type Dataview interface {
|
||||
SetSource(ctx session.Context, blockId string, source []string) (err error)
|
||||
|
@ -39,7 +36,7 @@ type Dataview interface {
|
|||
GetDataview(blockID string) (*model.BlockContentDataview, error)
|
||||
|
||||
DeleteView(ctx session.Context, blockId string, viewId string, showEvent bool) error
|
||||
SetActiveView(ctx session.Context, blockId string, activeViewId string, limit int, offset int) error
|
||||
SetActiveView(ctx session.Context, blockId string, activeViewId string) error
|
||||
CreateView(ctx session.Context, blockID string,
|
||||
view model.BlockContentDataviewView, source []string) (*model.BlockContentDataviewView, error)
|
||||
SetViewPosition(ctx session.Context, blockId string, viewId string, position uint32) error
|
||||
|
@ -59,6 +56,7 @@ func NewDataview(sb smartblock.SmartBlock, objectStore objectstore.ObjectStore)
|
|||
objectStore: objectStore,
|
||||
}
|
||||
sb.AddHook(dv.checkDVBlocks, smartblock.HookBeforeApply)
|
||||
sb.AddHook(dv.injectActiveViews, smartblock.HookBeforeApply)
|
||||
return dv
|
||||
}
|
||||
|
||||
|
@ -205,7 +203,7 @@ func (d *sdataview) UpdateView(ctx session.Context, blockID string, viewID strin
|
|||
return d.Apply(s, smartblock.NoEvent)
|
||||
}
|
||||
|
||||
func (d *sdataview) SetActiveView(ctx session.Context, id string, activeViewId string, limit int, offset int) error {
|
||||
func (d *sdataview) SetActiveView(ctx session.Context, id string, activeViewId string) error {
|
||||
s := d.NewStateCtx(ctx)
|
||||
|
||||
dvBlock, err := getDataviewBlock(s, id)
|
||||
|
@ -218,8 +216,12 @@ func (d *sdataview) SetActiveView(ctx session.Context, id string, activeViewId s
|
|||
}
|
||||
dvBlock.SetActiveView(activeViewId)
|
||||
|
||||
if err = d.objectStore.SetActiveView(d.Id(), id, activeViewId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SmartBlock.CheckSubscriptions()
|
||||
return d.Apply(s)
|
||||
return d.Apply(s, smartblock.NoHooks)
|
||||
}
|
||||
|
||||
func (d *sdataview) SetViewPosition(ctx session.Context, blockId string, viewId string, position uint32) (err error) {
|
||||
|
@ -423,6 +425,34 @@ func (d *sdataview) checkDVBlocks(info smartblock.ApplyInfo) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (d *sdataview) injectActiveViews(info smartblock.ApplyInfo) (err error) {
|
||||
s := info.State
|
||||
views, err := d.objectStore.GetActiveViews(d.Id())
|
||||
if badgerhelper.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
log.With("objectId", s.RootId()).Warnf("failed to get list of active views from store: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for blockId, viewId := range views {
|
||||
b := s.Pick(blockId)
|
||||
if b == nil {
|
||||
log.With("objectId", s.RootId()).Warnf("failed to get block '%s' to inject active view", blockId)
|
||||
continue
|
||||
}
|
||||
dv := b.Model().GetDataview()
|
||||
if dv == nil {
|
||||
log.With("objectId", s.RootId()).Warnf("block '%s' is not dataview, so cannot inject active view", blockId)
|
||||
continue
|
||||
}
|
||||
dv.ActiveView = viewId
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDataviewBlock(s *state.State, id string) (dataview.Block, error) {
|
||||
b := s.Get(id)
|
||||
if b == nil {
|
||||
|
@ -434,83 +464,6 @@ func getDataviewBlock(s *state.State, id string) (dataview.Block, error) {
|
|||
return nil, fmt.Errorf("not a dataview block")
|
||||
}
|
||||
|
||||
func getEntryID(entry database.Record) string {
|
||||
if entry.Details == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return pbtypes.GetString(entry.Details, bundle.RelationKeyId.String())
|
||||
}
|
||||
|
||||
type recordInsertedAtPosition struct {
|
||||
position int
|
||||
entry *types.Struct
|
||||
}
|
||||
|
||||
type recordsInsertedAtPosition struct {
|
||||
position int
|
||||
entries []*types.Struct
|
||||
}
|
||||
|
||||
func calculateEntriesDiff(a, b []database.Record) (updated []*types.Struct, removed []string, insertedGroupedByPosition []recordsInsertedAtPosition) {
|
||||
var inserted []recordInsertedAtPosition
|
||||
|
||||
var existing = make(map[string]*types.Struct, len(a))
|
||||
for _, record := range a {
|
||||
existing[getEntryID(record)] = record.Details
|
||||
}
|
||||
|
||||
var existingInNew = make(map[string]struct{}, len(b))
|
||||
for i, entry := range b {
|
||||
id := getEntryID(entry)
|
||||
if prev, exists := existing[id]; exists {
|
||||
if len(a) <= i || getEntryID(a[i]) != id {
|
||||
// todo: return as moved?
|
||||
removed = append(removed, id)
|
||||
inserted = append(inserted, recordInsertedAtPosition{i, entry.Details})
|
||||
} else {
|
||||
if !prev.Equal(entry.Details) {
|
||||
updated = append(updated, entry.Details)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inserted = append(inserted, recordInsertedAtPosition{i, entry.Details})
|
||||
}
|
||||
|
||||
existingInNew[id] = struct{}{}
|
||||
}
|
||||
|
||||
for id := range existing {
|
||||
if _, exists := existingInNew[id]; !exists {
|
||||
removed = append(removed, id)
|
||||
}
|
||||
}
|
||||
|
||||
var insertedToTheLastPosition = recordsInsertedAtPosition{position: -1}
|
||||
var lastPos = -1
|
||||
|
||||
if len(inserted) > 0 {
|
||||
insertedToTheLastPosition.position = inserted[0].position
|
||||
lastPos = inserted[0].position - 1
|
||||
}
|
||||
|
||||
for _, entry := range inserted {
|
||||
if entry.position > lastPos+1 {
|
||||
// split the insert portion
|
||||
insertedGroupedByPosition = append(insertedGroupedByPosition, insertedToTheLastPosition)
|
||||
insertedToTheLastPosition = recordsInsertedAtPosition{position: entry.position}
|
||||
}
|
||||
|
||||
lastPos = entry.position
|
||||
insertedToTheLastPosition.entries = append(insertedToTheLastPosition.entries, entry.entry)
|
||||
}
|
||||
if len(insertedToTheLastPosition.entries) > 0 {
|
||||
insertedGroupedByPosition = append(insertedGroupedByPosition, insertedToTheLastPosition)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func BlockBySource(objectStore objectstore.ObjectStore, source []string) (*model.BlockContentOfDataview, error) {
|
||||
schema, err := SchemaBySources(source, objectStore)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,82 +1,52 @@
|
|||
package dataview
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock/smarttest"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple/dataview"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/database"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/mock_objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
func Test_calculateEntriesDiff(t *testing.T) {
|
||||
a := []database.Record{
|
||||
{Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"id": pbtypes.String("id1"),
|
||||
"name": pbtypes.String("name1"),
|
||||
},
|
||||
}},
|
||||
{Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"id": pbtypes.String("id2"),
|
||||
"name": pbtypes.String("name2"),
|
||||
},
|
||||
}},
|
||||
{Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"id": pbtypes.String("id3"),
|
||||
"name": pbtypes.String("name3"),
|
||||
},
|
||||
}},
|
||||
const objId = "root"
|
||||
|
||||
type fixture struct {
|
||||
store *mock_objectstore.MockObjectStore
|
||||
sb *smarttest.SmartTest
|
||||
|
||||
*sdataview
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
store := mock_objectstore.NewMockObjectStore(t)
|
||||
sb := smarttest.New(objId)
|
||||
|
||||
dv := NewDataview(sb, store).(*sdataview)
|
||||
|
||||
return &fixture{
|
||||
store: store,
|
||||
sb: sb,
|
||||
sdataview: dv,
|
||||
}
|
||||
|
||||
b := []database.Record{
|
||||
{Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"id": pbtypes.String("id1"),
|
||||
"name": pbtypes.String("name1_change"),
|
||||
},
|
||||
}},
|
||||
{Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"id": pbtypes.String("id2"),
|
||||
"name": pbtypes.String("name2"),
|
||||
},
|
||||
}},
|
||||
{Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"id": pbtypes.String("id4"),
|
||||
"name": pbtypes.String("name4"),
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
updated, removed, inserted := calculateEntriesDiff(a, b)
|
||||
|
||||
require.Len(t, updated, 1)
|
||||
require.Len(t, removed, 1)
|
||||
require.Len(t, inserted, 1)
|
||||
|
||||
require.Equal(t, b[0].Details, updated[0])
|
||||
require.Equal(t, "id3", removed[0])
|
||||
require.Equal(t, 2, inserted[0].position)
|
||||
require.Equal(t, []*types.Struct{b[2].Details}, inserted[0].entries)
|
||||
}
|
||||
|
||||
func TestDataviewCollectionImpl_SetViewPosition(t *testing.T) {
|
||||
newTestDv := func() (Dataview, *smarttest.SmartTest) {
|
||||
sb := smarttest.New("root")
|
||||
sbs := sb.Doc.(*state.State)
|
||||
sbs.Add(simple.New(&model.Block{Id: "root", ChildrenIds: []string{"dv"}}))
|
||||
fx := newFixture(t)
|
||||
sbs := fx.sb.Doc.(*state.State)
|
||||
sbs.Add(simple.New(&model.Block{Id: objId, ChildrenIds: []string{"dv"}}))
|
||||
sbs.Add(simple.New(&model.Block{Id: "dv", Content: &model.BlockContentOfDataview{
|
||||
Dataview: &model.BlockContentDataview{
|
||||
Views: []*model.BlockContentDataviewView{
|
||||
|
@ -86,8 +56,8 @@ func TestDataviewCollectionImpl_SetViewPosition(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}}))
|
||||
|
||||
return NewDataview(sb, nil), sb
|
||||
fx.store.EXPECT().GetActiveViews(mock.Anything).Return(nil, nil).Maybe()
|
||||
return fx.sdataview, fx.sb
|
||||
}
|
||||
assertViewPositions := func(viewId string, pos uint32, exp []string) {
|
||||
dv, sb := newTestDv()
|
||||
|
@ -107,3 +77,81 @@ func TestDataviewCollectionImpl_SetViewPosition(t *testing.T) {
|
|||
assertViewPositions("1", 0, []string{"1", "2", "3"})
|
||||
assertViewPositions("1", 42, []string{"2", "3", "1"})
|
||||
}
|
||||
|
||||
func TestInjectActiveView(t *testing.T) {
|
||||
dv1 := "dataview1"
|
||||
dv2 := "dataview2"
|
||||
dv3 := "dataview3"
|
||||
|
||||
getInfo := func() smartblock.ApplyInfo {
|
||||
st := state.NewDoc(objId, map[string]simple.Block{
|
||||
objId: simple.New(&model.Block{Id: objId, ChildrenIds: []string{dv1, dv2, dv3}}),
|
||||
dv1: dataview.NewDataview(&model.Block{
|
||||
Id: dv1,
|
||||
Content: &model.BlockContentOfDataview{Dataview: &model.BlockContentDataview{}},
|
||||
}),
|
||||
dv2: dataview.NewDataview(&model.Block{
|
||||
Id: dv2,
|
||||
Content: &model.BlockContentOfDataview{Dataview: &model.BlockContentDataview{}},
|
||||
}),
|
||||
dv3: dataview.NewDataview(&model.Block{
|
||||
Id: dv3,
|
||||
Content: &model.BlockContentOfDataview{Dataview: &model.BlockContentDataview{}},
|
||||
}),
|
||||
}).(*state.State)
|
||||
return smartblock.ApplyInfo{State: st}
|
||||
}
|
||||
|
||||
t.Run("inject active views to dataview blocks", func(t *testing.T) {
|
||||
// given
|
||||
blocksToView := map[string]string{dv1: "view1", dv2: "view2"}
|
||||
fx := newFixture(t)
|
||||
fx.store.EXPECT().GetActiveViews(mock.Anything).RunAndReturn(func(id string) (map[string]string, error) {
|
||||
assert.Equal(t, objId, id)
|
||||
return blocksToView, nil
|
||||
})
|
||||
info := getInfo()
|
||||
|
||||
// when
|
||||
err := fx.injectActiveViews(info)
|
||||
st := info.State
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, blocksToView[dv1], st.Pick(dv1).Model().GetDataview().ActiveView)
|
||||
assert.Equal(t, blocksToView[dv2], st.Pick(dv2).Model().GetDataview().ActiveView)
|
||||
assert.Empty(t, st.Pick(dv3).Model().GetDataview().ActiveView)
|
||||
})
|
||||
|
||||
t.Run("do nothing if active views are not found in DB", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(t)
|
||||
fx.store.EXPECT().GetActiveViews(mock.Anything).RunAndReturn(func(id string) (map[string]string, error) {
|
||||
assert.Equal(t, objId, id)
|
||||
return nil, badger.ErrKeyNotFound
|
||||
})
|
||||
info := getInfo()
|
||||
|
||||
// when
|
||||
err := fx.injectActiveViews(info)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("fail on other DB error", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(t)
|
||||
fx.store.EXPECT().GetActiveViews(mock.Anything).RunAndReturn(func(id string) (map[string]string, error) {
|
||||
assert.Equal(t, objId, id)
|
||||
return nil, errors.New("badger was stolen by UFO")
|
||||
})
|
||||
info := getInfo()
|
||||
|
||||
// when
|
||||
err := fx.injectActiveViews(info)
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -123,8 +123,10 @@ func (f *ObjectFactory) InitObject(space smartblock.Space, id string, initCtx *s
|
|||
sb.SetLocker(ot)
|
||||
}
|
||||
|
||||
// we probably don't need any locks here, because the object is initialized synchronously
|
||||
initCtx.Source = sc
|
||||
// adding locks as a temporary measure to find the place where we have races in our code
|
||||
sb.Lock()
|
||||
defer sb.Unlock()
|
||||
err = sb.Init(initCtx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init smartblock: %w", err)
|
||||
|
@ -176,7 +178,7 @@ func (f *ObjectFactory) New(space smartblock.Space, sbType coresb.SmartBlockType
|
|||
case coresb.SmartBlockTypeMissingObject:
|
||||
return NewMissingObject(sb), nil
|
||||
case coresb.SmartBlockTypeWidget:
|
||||
return NewWidgetObject(sb, f.objectStore, f.layoutConverter, f.accountService), nil
|
||||
return NewWidgetObject(sb, f.objectStore, f.layoutConverter), nil
|
||||
case coresb.SmartBlockTypeNotificationObject:
|
||||
return NewNotificationObject(sb), nil
|
||||
case coresb.SmartBlockTypeSubObject:
|
||||
|
|
|
@ -220,6 +220,9 @@ func (sf *sfile) updateFile(ctx session.Context, id, groupId string, apply func(
|
|||
}
|
||||
|
||||
func (sf *sfile) DropFiles(req pb.RpcFileDropRequest) (err error) {
|
||||
if err = sf.Restrictions().Object.Check(model.Restrictions_Blocks); err != nil {
|
||||
return err
|
||||
}
|
||||
proc := &dropFilesProcess{
|
||||
spaceID: sf.SpaceID(),
|
||||
processService: sf.processService,
|
||||
|
@ -561,7 +564,6 @@ func (dp *dropFilesProcess) addFile(f *dropFileInfo) {
|
|||
upl := dp.fileUploaderFactory.NewUploader(dp.spaceID, objectorigin.DragAndDrop())
|
||||
res := upl.
|
||||
SetName(f.name).
|
||||
AutoType(true).
|
||||
SetFile(f.path).
|
||||
Upload(context.Background())
|
||||
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package file
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/cache/mock_cache"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock/smarttest"
|
||||
"github.com/anyproto/anytype-heart/core/block/restriction"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/tests/blockbuilder"
|
||||
|
@ -101,3 +105,18 @@ func TestFile(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropFiles(t *testing.T) {
|
||||
t.Run("do not drop files to object with Blocks restriction", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(t)
|
||||
fx.sb.SetRestrictions(restriction.Restrictions{Object: restriction.ObjectRestrictions{model.Restrictions_Blocks}})
|
||||
|
||||
// when
|
||||
err := fx.sfile.DropFiles(pb.RpcFileDropRequest{})
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
assert.True(t, errors.Is(err, restriction.ErrRestricted))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ func (f *ObjectFactory) newPage(sb smartblock.SmartBlock) *Page {
|
|||
f.fileService,
|
||||
f.fileObjectService,
|
||||
),
|
||||
Bookmark: bookmark.NewBookmark(sb, f.bookmarkService, f.objectStore),
|
||||
Bookmark: bookmark.NewBookmark(sb, f.bookmarkService),
|
||||
Dataview: dataview.NewDataview(sb, f.objectStore),
|
||||
TableEditor: table.NewEditor(sb),
|
||||
objectStore: f.objectStore,
|
||||
|
|
|
@ -56,7 +56,7 @@ func (f *ObjectFactory) newProfile(sb smartblock.SmartBlock) *Profile {
|
|||
f.fileService,
|
||||
f.fileObjectService,
|
||||
),
|
||||
Bookmark: bookmark.NewBookmark(sb, f.bookmarkService, f.objectStore),
|
||||
Bookmark: bookmark.NewBookmark(sb, f.bookmarkService),
|
||||
TableEditor: table.NewEditor(sb),
|
||||
eventSender: f.eventSender,
|
||||
fileObjectService: f.fileObjectService,
|
||||
|
|
|
@ -347,7 +347,7 @@ func (sb *smartBlock) Init(ctx *InitContext) (err error) {
|
|||
}
|
||||
ctx.State.AddBundledRelations(relKeys...)
|
||||
if ctx.IsNewObject && ctx.State != nil {
|
||||
source.NewSubObjectsAndProfileLinksMigration(sb.Type(), sb.space, sb.currentParticipantId, "", sb.objectStore).Migrate(ctx.State)
|
||||
source.NewSubObjectsAndProfileLinksMigration(sb.Type(), sb.space, sb.currentParticipantId, sb.objectStore).Migrate(ctx.State)
|
||||
}
|
||||
|
||||
if err = sb.injectLocalDetails(ctx.State); err != nil {
|
||||
|
@ -753,7 +753,7 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
|
|||
}
|
||||
|
||||
func (sb *smartBlock) ResetToVersion(s *state.State) (err error) {
|
||||
source.NewSubObjectsAndProfileLinksMigration(sb.Type(), sb.space, sb.currentParticipantId, "", sb.objectStore).Migrate(s)
|
||||
source.NewSubObjectsAndProfileLinksMigration(sb.Type(), sb.space, sb.currentParticipantId, sb.objectStore).Migrate(s)
|
||||
s.SetParent(sb.Doc.(*state.State))
|
||||
sb.storeFileKeys(s)
|
||||
sb.injectLocalDetails(s)
|
||||
|
@ -1195,14 +1195,6 @@ func (sb *smartBlock) AddHookOnce(id string, f HookCallback, events ...Hook) {
|
|||
}
|
||||
}
|
||||
|
||||
func (sb *smartBlock) baseRelations() []*model.Relation {
|
||||
rels := []*model.Relation{bundle.MustGetRelation(bundle.RelationKeyId), bundle.MustGetRelation(bundle.RelationKeyLayout), bundle.MustGetRelation(bundle.RelationKeyIconEmoji), bundle.MustGetRelation(bundle.RelationKeyName)}
|
||||
for _, rel := range rels {
|
||||
rel.Scope = model.Relation_object
|
||||
}
|
||||
return rels
|
||||
}
|
||||
|
||||
// deprecated, use RelationLinks instead
|
||||
func (sb *smartBlock) Relations(s *state.State) relationutils.Relations {
|
||||
var links []*model.RelationLink
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
|
||||
var (
|
||||
maxChildrenThreshold = 40
|
||||
blockSizeLimit = 1 * 1024 * 1024
|
||||
detailSizeLimit = 65 * 1024
|
||||
|
||||
detailSizeLimit = 65 * 1024
|
||||
)
|
||||
|
||||
func (s *State) Normalize(withLayouts bool) (err error) {
|
||||
|
|
|
@ -29,6 +29,9 @@ func (s *State) InsertTo(targetId string, reqPos model.BlockPosition, ids ...str
|
|||
if targetId == "" {
|
||||
reqPos = model.Block_Inner
|
||||
target = s.Get(s.RootId())
|
||||
if target == nil {
|
||||
return fmt.Errorf("target (root) block not found")
|
||||
}
|
||||
} else {
|
||||
target = s.Get(targetId)
|
||||
if target == nil {
|
||||
|
|
|
@ -2596,12 +2596,3 @@ func TestState_RootId(t *testing.T) {
|
|||
// assert.True(t, assertAllDetailsLessThenLimit(s.CombinedDetails()))
|
||||
// })
|
||||
// }
|
||||
|
||||
func assertAllDetailsLessThenLimit(details *types.Struct) bool {
|
||||
for _, v := range details.Fields {
|
||||
if v.Size() > detailSizeLimit {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
||||
const textSizeLimit = 64 * 1024
|
||||
|
||||
var setTextApplyInterval = time.Second * 3
|
||||
|
||||
type Text interface {
|
||||
|
|
|
@ -20,8 +20,7 @@ func init() {
|
|||
func NewBlock(b *model.Block) simple.Block {
|
||||
if c := b.GetTable(); c != nil {
|
||||
return &block{
|
||||
Base: base.NewBase(b).(*base.Base),
|
||||
content: c,
|
||||
Base: base.NewBase(b).(*base.Base),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -35,7 +34,6 @@ type Block interface {
|
|||
|
||||
type block struct {
|
||||
*base.Base
|
||||
content *model.BlockContentTable
|
||||
}
|
||||
|
||||
func (b *block) Copy() simple.Block {
|
||||
|
|
|
@ -29,7 +29,6 @@ func NewWidgetObject(
|
|||
sb smartblock.SmartBlock,
|
||||
objectStore objectstore.ObjectStore,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
accountService accountService,
|
||||
) *WidgetObject {
|
||||
bs := basic.NewBasic(sb, objectStore, layoutConverter)
|
||||
return &WidgetObject{
|
||||
|
@ -37,7 +36,7 @@ func NewWidgetObject(
|
|||
Movable: bs,
|
||||
Updatable: bs,
|
||||
IHistory: basic.NewHistory(sb),
|
||||
Widget: widget.NewWidget(sb, accountService),
|
||||
Widget: widget.NewWidget(sb),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,14 +21,8 @@ type Widget interface {
|
|||
CreateBlock(s *state.State, req *pb.RpcBlockCreateWidgetRequest) (string, error)
|
||||
}
|
||||
|
||||
type accountService interface {
|
||||
PersonalSpaceID() string
|
||||
MyParticipantId(string) string
|
||||
}
|
||||
|
||||
type widget struct {
|
||||
smartblock.SmartBlock
|
||||
accountService accountService
|
||||
}
|
||||
|
||||
type ImportWidgetFlags struct {
|
||||
|
@ -62,10 +56,9 @@ func IsPredefinedWidgetTargetId(targetID string) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func NewWidget(sb smartblock.SmartBlock, accountService accountService) Widget {
|
||||
func NewWidget(sb smartblock.SmartBlock) Widget {
|
||||
return &widget{
|
||||
SmartBlock: sb,
|
||||
accountService: accountService,
|
||||
SmartBlock: sb,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
@ -25,7 +24,6 @@ type Workspaces struct {
|
|||
stext.Text
|
||||
|
||||
spaceService spaceService
|
||||
objectStore objectstore.ObjectStore
|
||||
config *config.Config
|
||||
migrator subObjectsMigrator
|
||||
}
|
||||
|
@ -41,7 +39,6 @@ func (f *ObjectFactory) newWorkspace(sb smartblock.SmartBlock) *Workspaces {
|
|||
f.eventSender,
|
||||
),
|
||||
Dataview: dataview.NewDataview(sb, f.objectStore),
|
||||
objectStore: f.objectStore,
|
||||
spaceService: f.spaceService,
|
||||
config: f.config,
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock/smarttest"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/migration"
|
||||
"github.com/anyproto/anytype-heart/util/testMock"
|
||||
)
|
||||
|
||||
func TestWorkspaces_FileInfo(t *testing.T) {
|
||||
|
@ -47,15 +46,11 @@ func (m migratorStub) migrateSubObjects(st *state.State) {
|
|||
|
||||
func NewWorkspacesTest(ctrl *gomock.Controller) (*Workspaces, error) {
|
||||
sb := smarttest.New("root")
|
||||
objectStore := testMock.NewMockObjectStore(ctrl)
|
||||
objectStore.EXPECT().GetDetails(gomock.Any()).AnyTimes()
|
||||
objectStore.EXPECT().Query(gomock.Any()).AnyTimes()
|
||||
a := &Workspaces{
|
||||
SmartBlock: sb,
|
||||
spaceService: &spaceServiceStub{},
|
||||
migrator: migratorStub{},
|
||||
config: &config.Config{},
|
||||
objectStore: objectStore,
|
||||
}
|
||||
initCtx := &smartblock.InitContext{
|
||||
IsNewObject: true,
|
||||
|
|
|
@ -24,7 +24,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/cache"
|
||||
sb "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/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/block/process"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/converter"
|
||||
|
@ -73,7 +72,6 @@ type export struct {
|
|||
objectStore objectstore.ObjectStore
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
fileService files.Service
|
||||
resolver idresolver.Resolver
|
||||
spaceService space.Service
|
||||
accountService account.Service
|
||||
notificationService notifications.Notifications
|
||||
|
@ -88,7 +86,6 @@ func (e *export) Init(a *app.App) (err error) {
|
|||
e.objectStore = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
e.fileService = app.MustComponent[files.Service](a)
|
||||
e.picker = app.MustComponent[cache.ObjectGetter](a)
|
||||
e.resolver = a.MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
e.sbtProvider = app.MustComponent[typeprovider.SmartBlockTypeProvider](a)
|
||||
e.spaceService = app.MustComponent[space.Service](a)
|
||||
e.accountService = app.MustComponent[account.Service](a)
|
||||
|
@ -665,7 +662,6 @@ func validType(sbType smartblock.SmartBlockType) bool {
|
|||
sbType == smartblock.SmartBlockTypePage ||
|
||||
sbType == smartblock.SmartBlockTypeSubObject ||
|
||||
sbType == smartblock.SmartBlockTypeTemplate ||
|
||||
sbType == smartblock.SmartBlockTypeDate ||
|
||||
sbType == smartblock.SmartBlockTypeWorkspace ||
|
||||
sbType == smartblock.SmartBlockTypeWidget ||
|
||||
sbType == smartblock.SmartBlockTypeObjectType ||
|
||||
|
@ -692,32 +688,33 @@ func (e *export) cleanupFile(wr writer) {
|
|||
}
|
||||
|
||||
func (e *export) getRelatedDerivedObjects(objects map[string]*types.Struct) ([]database.Record, error) {
|
||||
derivedObjects, err := e.iterateObjects(objects)
|
||||
derivedObjects, typesAndTemplates, err := e.iterateObjects(objects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(derivedObjects) > 0 {
|
||||
// get derived objects only from types and templates,
|
||||
// because relations currently have only system relations and object type
|
||||
if len(typesAndTemplates) > 0 {
|
||||
derivedObjectsMap := make(map[string]*types.Struct, 0)
|
||||
for _, object := range derivedObjects {
|
||||
for _, object := range typesAndTemplates {
|
||||
id := object.Get(bundle.RelationKeyId.String()).GetStringValue()
|
||||
derivedObjectsMap[id] = object.Details
|
||||
}
|
||||
iteratedObjects, err := e.iterateObjects(derivedObjectsMap)
|
||||
iteratedObjects, typesAndTemplates, err := e.iterateObjects(derivedObjectsMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
derivedObjects = append(derivedObjects, iteratedObjects...)
|
||||
derivedObjects = append(derivedObjects, typesAndTemplates...)
|
||||
}
|
||||
return derivedObjects, nil
|
||||
}
|
||||
|
||||
func (e *export) iterateObjects(objects map[string]*types.Struct) ([]database.Record, error) {
|
||||
var (
|
||||
derivedObjects []database.Record
|
||||
relations []string
|
||||
)
|
||||
func (e *export) iterateObjects(objects map[string]*types.Struct,
|
||||
) (allObjects []database.Record, typesAndTemplates []database.Record, err error) {
|
||||
var relations []string
|
||||
for id, object := range objects {
|
||||
err := cache.Do(e.picker, id, func(b sb.SmartBlock) error {
|
||||
err = cache.Do(e.picker, id, func(b sb.SmartBlock) error {
|
||||
state := b.NewState()
|
||||
relations = e.getObjectRelations(state, relations)
|
||||
details := state.Details()
|
||||
|
@ -731,14 +728,14 @@ func (e *export) iterateObjects(objects map[string]*types.Struct) ([]database.Re
|
|||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
derivedObjects, err = e.processObject(object, derivedObjects, relations)
|
||||
allObjects, typesAndTemplates, err = e.processObject(object, allObjects, typesAndTemplates, relations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return derivedObjects, nil
|
||||
return allObjects, typesAndTemplates, nil
|
||||
}
|
||||
|
||||
func (e *export) getDataviewRelations(state *state.State) ([]string, error) {
|
||||
|
@ -771,60 +768,69 @@ func (e *export) isObjectWithDataview(details *types.Struct) bool {
|
|||
|
||||
func (e *export) processObject(object *types.Struct,
|
||||
derivedObjects []database.Record,
|
||||
typesAndTemplates []database.Record,
|
||||
relations []string,
|
||||
) ([]database.Record, error) {
|
||||
) ([]database.Record, []database.Record, error) {
|
||||
for _, relation := range relations {
|
||||
storeRelation, err := e.getRelation(relation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if storeRelation != nil {
|
||||
derivedObjects, err = e.addRelationAndOptions(storeRelation, object, derivedObjects, relation)
|
||||
derivedObjects, err = e.addRelationAndOptions(storeRelation, derivedObjects, relation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
objectTypeId := pbtypes.GetString(object, bundle.RelationKeyType.String())
|
||||
|
||||
derivedObjects, err := e.addObjectType(objectTypeId, derivedObjects)
|
||||
var err error
|
||||
derivedObjects, typesAndTemplates, err = e.addObjectType(objectTypeId, derivedObjects, typesAndTemplates)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
derivedObjects, err = e.addTemplates(objectTypeId, derivedObjects)
|
||||
derivedObjects, typesAndTemplates, err = e.addTemplates(objectTypeId, derivedObjects, typesAndTemplates)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return e.handleSetOfRelation(object, derivedObjects)
|
||||
derivedObjects, err = e.handleSetOfRelation(object, derivedObjects)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return derivedObjects, typesAndTemplates, nil
|
||||
}
|
||||
|
||||
func (e *export) addObjectType(objectTypeId string, derivedObjects []database.Record) ([]database.Record, error) {
|
||||
func (e *export) addObjectType(objectTypeId string, derivedObjects []database.Record, typesAndTemplates []database.Record) ([]database.Record, []database.Record, error) {
|
||||
objectTypeDetails, err := e.objectStore.GetDetails(objectTypeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if objectTypeDetails == nil || objectTypeDetails.Details == nil || len(objectTypeDetails.Details.Fields) == 0 {
|
||||
return derivedObjects, nil
|
||||
return derivedObjects, typesAndTemplates, nil
|
||||
}
|
||||
uniqueKey := pbtypes.GetString(objectTypeDetails.Details, bundle.RelationKeyUniqueKey.String())
|
||||
key, err := domain.GetTypeKeyFromRawUniqueKey(uniqueKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if bundle.IsInternalType(key) {
|
||||
return derivedObjects, nil
|
||||
return derivedObjects, typesAndTemplates, nil
|
||||
}
|
||||
recommendedRelations := pbtypes.GetStringList(objectTypeDetails.Details, bundle.RelationKeyRecommendedRelations.String())
|
||||
for _, relation := range recommendedRelations {
|
||||
if relation == addr.MissingObject {
|
||||
continue
|
||||
}
|
||||
details, err := e.objectStore.GetDetails(relation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
relationKey := pbtypes.GetString(details.Details, bundle.RelationKeyUniqueKey.String())
|
||||
uniqueKey, err := domain.UnmarshalUniqueKey(relationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if bundle.IsSystemRelation(domain.RelationKey(uniqueKey.InternalKey())) {
|
||||
continue
|
||||
|
@ -832,7 +838,8 @@ func (e *export) addObjectType(objectTypeId string, derivedObjects []database.Re
|
|||
derivedObjects = append(derivedObjects, database.Record{Details: details.Details})
|
||||
}
|
||||
derivedObjects = append(derivedObjects, database.Record{Details: objectTypeDetails.Details})
|
||||
return derivedObjects, nil
|
||||
typesAndTemplates = append(typesAndTemplates, database.Record{Details: objectTypeDetails.Details})
|
||||
return derivedObjects, typesAndTemplates, nil
|
||||
}
|
||||
|
||||
func (e *export) getRelation(key string) (*database.Record, error) {
|
||||
|
@ -868,17 +875,15 @@ func (e *export) getRelation(key string) (*database.Record, error) {
|
|||
return &relation[0], nil
|
||||
}
|
||||
|
||||
func (e *export) addRelationAndOptions(relation *database.Record, object *types.Struct, derivedObjects []database.Record, relationKey string) ([]database.Record, error) {
|
||||
func (e *export) addRelationAndOptions(relation *database.Record, derivedObjects []database.Record, relationKey string) ([]database.Record, error) {
|
||||
derivedObjects = e.addRelation(*relation, derivedObjects)
|
||||
format := pbtypes.GetInt64(relation.Details, bundle.RelationKeyRelationFormat.String())
|
||||
if format == int64(model.RelationFormat_tag) || format == int64(model.RelationFormat_status) {
|
||||
if value := pbtypes.Get(object, relationKey); value != nil {
|
||||
relationOptions, err := e.getRelationOptions(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
derivedObjects = append(derivedObjects, relationOptions...)
|
||||
relationOptions, err := e.getRelationOptions(relationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
derivedObjects = append(derivedObjects, relationOptions...)
|
||||
}
|
||||
|
||||
return derivedObjects, nil
|
||||
|
@ -893,20 +898,19 @@ func (e *export) addRelation(relation database.Record, derivedObjects []database
|
|||
return derivedObjects
|
||||
}
|
||||
|
||||
func (e *export) getRelationOptions(relationOptions *types.Value) ([]database.Record, error) {
|
||||
var filter *model.BlockContentDataviewFilter
|
||||
if relationOptions.GetStringValue() != "" {
|
||||
filter = e.getFilterForStringOption(relationOptions, filter)
|
||||
}
|
||||
if relationOptions.GetListValue() != nil && len(relationOptions.GetListValue().Values) != 0 {
|
||||
filter = e.getFilterForOptionsList(relationOptions, filter)
|
||||
}
|
||||
if filter == nil {
|
||||
return nil, nil
|
||||
}
|
||||
func (e *export) getRelationOptions(relationKey string) ([]database.Record, error) {
|
||||
relationOptionsDetails, err := e.objectStore.Query(database.Query{
|
||||
Filters: []*model.BlockContentDataviewFilter{
|
||||
filter,
|
||||
{
|
||||
RelationKey: bundle.RelationKeyLayout.String(),
|
||||
Condition: model.BlockContentDataviewFilter_Equal,
|
||||
Value: pbtypes.Int64(int64(model.ObjectType_relationOption)),
|
||||
},
|
||||
{
|
||||
RelationKey: bundle.RelationKeyRelationKey.String(),
|
||||
Condition: model.BlockContentDataviewFilter_Equal,
|
||||
Value: pbtypes.String(relationKey),
|
||||
},
|
||||
{
|
||||
RelationKey: bundle.RelationKeyIsArchived.String(),
|
||||
Condition: model.BlockContentDataviewFilter_Equal,
|
||||
|
@ -925,30 +929,7 @@ func (e *export) getRelationOptions(relationOptions *types.Value) ([]database.Re
|
|||
return relationOptionsDetails, nil
|
||||
}
|
||||
|
||||
func (e *export) getFilterForOptionsList(relationOptions *types.Value, filter *model.BlockContentDataviewFilter) *model.BlockContentDataviewFilter {
|
||||
ids := make([]string, 0, len(relationOptions.GetListValue().Values))
|
||||
for _, id := range relationOptions.GetListValue().Values {
|
||||
ids = append(ids, id.GetStringValue())
|
||||
}
|
||||
filter = &model.BlockContentDataviewFilter{
|
||||
RelationKey: bundle.RelationKeyId.String(),
|
||||
Condition: model.BlockContentDataviewFilter_In,
|
||||
Value: pbtypes.StringList(ids),
|
||||
}
|
||||
return filter
|
||||
}
|
||||
|
||||
func (e *export) getFilterForStringOption(value *types.Value, filter *model.BlockContentDataviewFilter) *model.BlockContentDataviewFilter {
|
||||
id := value.GetStringValue()
|
||||
filter = &model.BlockContentDataviewFilter{
|
||||
RelationKey: bundle.RelationKeyId.String(),
|
||||
Condition: model.BlockContentDataviewFilter_Equal,
|
||||
Value: pbtypes.String(id),
|
||||
}
|
||||
return filter
|
||||
}
|
||||
|
||||
func (e *export) addTemplates(id string, derivedObjects []database.Record) ([]database.Record, error) {
|
||||
func (e *export) addTemplates(id string, derivedObjects []database.Record, typesAndTemplates []database.Record) ([]database.Record, []database.Record, error) {
|
||||
templates, err := e.objectStore.Query(database.Query{
|
||||
Filters: []*model.BlockContentDataviewFilter{
|
||||
{
|
||||
|
@ -969,10 +950,11 @@ func (e *export) addTemplates(id string, derivedObjects []database.Record) ([]da
|
|||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
derivedObjects = append(derivedObjects, templates...)
|
||||
return derivedObjects, nil
|
||||
typesAndTemplates = append(typesAndTemplates, templates...)
|
||||
return derivedObjects, typesAndTemplates, nil
|
||||
}
|
||||
|
||||
func (e *export) handleSetOfRelation(object *types.Struct, derivedObjects []database.Record) ([]database.Record, error) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider/mock_typeprovider"
|
||||
|
@ -184,7 +185,6 @@ func Test_docsForExport(t *testing.T) {
|
|||
objectGetter := mock_cache.NewMockObjectGetter(t)
|
||||
|
||||
smartBlockTest := smarttest.New("id")
|
||||
smartBlockRelation := smarttest.New("key")
|
||||
doc := smartBlockTest.NewState().SetDetails(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyId.String(): pbtypes.String("id"),
|
||||
|
@ -201,7 +201,279 @@ func Test_docsForExport(t *testing.T) {
|
|||
smartBlockTest.Doc = doc
|
||||
|
||||
objectGetter.EXPECT().GetObject(context.Background(), "id").Return(smartBlockTest, nil)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), "key").Return(smartBlockRelation, nil)
|
||||
|
||||
e := &export{
|
||||
objectStore: storeFixture,
|
||||
picker: objectGetter,
|
||||
}
|
||||
|
||||
// when
|
||||
docsForExport, err := e.docsForExport("spaceId", pb.RpcObjectListExportRequest{
|
||||
SpaceId: "spaceId",
|
||||
ObjectIds: []string{"id"},
|
||||
Format: model.Export_Protobuf,
|
||||
})
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2, len(docsForExport))
|
||||
})
|
||||
|
||||
t.Run("get relation options - no relation options", func(t *testing.T) {
|
||||
// given
|
||||
storeFixture := objectstore.NewStoreFixture(t)
|
||||
relationKey := "key"
|
||||
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, relationKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
storeFixture.AddObjects(t, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String("id"),
|
||||
domain.RelationKey(relationKey): pbtypes.String("value"),
|
||||
bundle.RelationKeyType: pbtypes.String("objectType"),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyRelationKey: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(uniqueKey.Marshal()),
|
||||
bundle.RelationKeyRelationFormat: pbtypes.Int64(int64(model.RelationFormat_status)),
|
||||
},
|
||||
})
|
||||
|
||||
objectGetter := mock_cache.NewMockObjectGetter(t)
|
||||
|
||||
smartBlockTest := smarttest.New("id")
|
||||
doc := smartBlockTest.NewState().SetDetails(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyId.String(): pbtypes.String("id"),
|
||||
relationKey: pbtypes.String("value"),
|
||||
bundle.RelationKeyType.String(): pbtypes.String("objectType"),
|
||||
}})
|
||||
doc.AddRelationLinks(&model.RelationLink{
|
||||
Key: bundle.RelationKeyId.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
}, &model.RelationLink{
|
||||
Key: relationKey,
|
||||
Format: model.RelationFormat_tag,
|
||||
})
|
||||
smartBlockTest.Doc = doc
|
||||
|
||||
objectGetter.EXPECT().GetObject(context.Background(), "id").Return(smartBlockTest, nil)
|
||||
|
||||
e := &export{
|
||||
objectStore: storeFixture,
|
||||
picker: objectGetter,
|
||||
}
|
||||
|
||||
// when
|
||||
docsForExport, err := e.docsForExport("spaceId", pb.RpcObjectListExportRequest{
|
||||
SpaceId: "spaceId",
|
||||
ObjectIds: []string{"id"},
|
||||
Format: model.Export_Protobuf,
|
||||
})
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2, len(docsForExport))
|
||||
})
|
||||
t.Run("get relation options - 1 relation option", func(t *testing.T) {
|
||||
// given
|
||||
storeFixture := objectstore.NewStoreFixture(t)
|
||||
relationKey := "key"
|
||||
optionId := "optionId"
|
||||
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, relationKey)
|
||||
assert.Nil(t, err)
|
||||
optionUniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelationOption, optionId)
|
||||
assert.Nil(t, err)
|
||||
|
||||
storeFixture.AddObjects(t, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String("id"),
|
||||
domain.RelationKey(relationKey): pbtypes.String(optionId),
|
||||
bundle.RelationKeyType: pbtypes.String("objectType"),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyRelationKey: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(uniqueKey.Marshal()),
|
||||
bundle.RelationKeyRelationFormat: pbtypes.Int64(int64(model.RelationFormat_tag)),
|
||||
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_relation)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(optionId),
|
||||
bundle.RelationKeyRelationKey: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(optionUniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_relationOption)),
|
||||
},
|
||||
})
|
||||
|
||||
objectGetter := mock_cache.NewMockObjectGetter(t)
|
||||
|
||||
smartBlockTest := smarttest.New("id")
|
||||
doc := smartBlockTest.NewState().SetDetails(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyId.String(): pbtypes.String("id"),
|
||||
relationKey: pbtypes.String("value"),
|
||||
bundle.RelationKeyType.String(): pbtypes.String("objectType"),
|
||||
}})
|
||||
doc.AddRelationLinks(&model.RelationLink{
|
||||
Key: bundle.RelationKeyId.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
}, &model.RelationLink{
|
||||
Key: relationKey,
|
||||
Format: model.RelationFormat_tag,
|
||||
})
|
||||
smartBlockTest.Doc = doc
|
||||
|
||||
objectGetter.EXPECT().GetObject(context.Background(), "id").Return(smartBlockTest, nil)
|
||||
|
||||
e := &export{
|
||||
objectStore: storeFixture,
|
||||
picker: objectGetter,
|
||||
}
|
||||
|
||||
// when
|
||||
docsForExport, err := e.docsForExport("spaceId", pb.RpcObjectListExportRequest{
|
||||
SpaceId: "spaceId",
|
||||
ObjectIds: []string{"id"},
|
||||
Format: model.Export_Protobuf,
|
||||
})
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 3, len(docsForExport))
|
||||
var objectIds []string
|
||||
for objectId := range docsForExport {
|
||||
objectIds = append(objectIds, objectId)
|
||||
}
|
||||
assert.Contains(t, objectIds, optionId)
|
||||
})
|
||||
t.Run("get derived objects - relation, object type with recommended relations, template with link", func(t *testing.T) {
|
||||
// given
|
||||
storeFixture := objectstore.NewStoreFixture(t)
|
||||
relationKey := "key"
|
||||
objectTypeKey := "customObjectType"
|
||||
objectTypeUniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeObjectType, objectTypeKey)
|
||||
assert.Nil(t, err)
|
||||
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, relationKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
recommendedRelationKey := "recommendedRelationKey"
|
||||
recommendedRelationUniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, recommendedRelationKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
templateId := "templateId"
|
||||
|
||||
linkedObjectId := "linkedObjectId"
|
||||
storeFixture.AddObjects(t, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String("id"),
|
||||
domain.RelationKey(relationKey): pbtypes.String("test"),
|
||||
bundle.RelationKeyType: pbtypes.String(objectTypeKey),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyRelationKey: pbtypes.String(relationKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(uniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_relation)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(objectTypeKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(objectTypeUniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_objectType)),
|
||||
bundle.RelationKeyRecommendedRelations: pbtypes.StringList([]string{recommendedRelationKey}),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(recommendedRelationKey),
|
||||
bundle.RelationKeyRelationKey: pbtypes.String(recommendedRelationKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(recommendedRelationUniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_relation)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(templateId),
|
||||
bundle.RelationKeyTargetObjectType: pbtypes.String(objectTypeKey),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(linkedObjectId),
|
||||
bundle.RelationKeyType: pbtypes.String(objectTypeKey),
|
||||
},
|
||||
})
|
||||
|
||||
err = storeFixture.UpdateObjectLinks(templateId, []string{linkedObjectId})
|
||||
assert.Nil(t, err)
|
||||
|
||||
objectGetter := mock_cache.NewMockObjectGetter(t)
|
||||
|
||||
smartBlockTest := smarttest.New("id")
|
||||
smartBlockTemplate := smarttest.New(templateId)
|
||||
smartBlockObjectType := smarttest.New(objectTypeKey)
|
||||
doc := smartBlockTest.NewState().SetDetails(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyId.String(): pbtypes.String("id"),
|
||||
relationKey: pbtypes.String("value"),
|
||||
bundle.RelationKeyType.String(): pbtypes.String("objectType"),
|
||||
}})
|
||||
doc.AddRelationLinks(&model.RelationLink{
|
||||
Key: bundle.RelationKeyId.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
}, &model.RelationLink{
|
||||
Key: relationKey,
|
||||
Format: model.RelationFormat_tag,
|
||||
})
|
||||
smartBlockTest.Doc = doc
|
||||
|
||||
objectGetter.EXPECT().GetObject(context.Background(), "id").Return(smartBlockTest, nil)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), templateId).Return(smartBlockTemplate, nil)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), objectTypeKey).Return(smartBlockObjectType, nil)
|
||||
|
||||
provider := mock_typeprovider.NewMockSmartBlockTypeProvider(t)
|
||||
provider.EXPECT().Type("spaceId", linkedObjectId).Return(smartblock.SmartBlockTypePage, nil)
|
||||
|
||||
e := &export{
|
||||
objectStore: storeFixture,
|
||||
picker: objectGetter,
|
||||
sbtProvider: provider,
|
||||
}
|
||||
|
||||
// when
|
||||
docsForExport, err := e.docsForExport("spaceId", pb.RpcObjectListExportRequest{
|
||||
SpaceId: "spaceId",
|
||||
ObjectIds: []string{"id"},
|
||||
Format: model.Export_Protobuf,
|
||||
IncludeNested: true,
|
||||
})
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 6, len(docsForExport))
|
||||
})
|
||||
t.Run("get derived objects, object type have missing relations - return only object and its type", func(t *testing.T) {
|
||||
// given
|
||||
storeFixture := objectstore.NewStoreFixture(t)
|
||||
objectTypeKey := "customObjectType"
|
||||
objectTypeUniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeObjectType, objectTypeKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
storeFixture.AddObjects(t, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String("id"),
|
||||
bundle.RelationKeyType: pbtypes.String(objectTypeKey),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: pbtypes.String(objectTypeKey),
|
||||
bundle.RelationKeyUniqueKey: pbtypes.String(objectTypeUniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_objectType)),
|
||||
bundle.RelationKeyRecommendedRelations: pbtypes.StringList([]string{addr.MissingObject}),
|
||||
},
|
||||
})
|
||||
|
||||
objectGetter := mock_cache.NewMockObjectGetter(t)
|
||||
|
||||
smartBlockTest := smarttest.New("id")
|
||||
smartBlockObjectType := smarttest.New(objectTypeKey)
|
||||
|
||||
objectGetter.EXPECT().GetObject(context.Background(), "id").Return(smartBlockTest, nil)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), objectTypeKey).Return(smartBlockObjectType, nil)
|
||||
|
||||
e := &export{
|
||||
objectStore: storeFixture,
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
@ -29,7 +28,6 @@ import (
|
|||
"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/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
|
@ -59,16 +57,13 @@ type ObjectCreator struct {
|
|||
objectStore objectstore.ObjectStore
|
||||
relationSyncer *syncer.FileRelationSyncer
|
||||
syncFactory *syncer.Factory
|
||||
fileStore filestore.FileStore
|
||||
objectCreator objectcreator.Service
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func New(service BlockService,
|
||||
syncFactory *syncer.Factory,
|
||||
objectStore objectstore.ObjectStore,
|
||||
relationSyncer *syncer.FileRelationSyncer,
|
||||
fileStore filestore.FileStore,
|
||||
spaceService space.Service,
|
||||
objectCreator objectcreator.Service,
|
||||
) Service {
|
||||
|
@ -77,7 +72,6 @@ func New(service BlockService,
|
|||
syncFactory: syncFactory,
|
||||
objectStore: objectStore,
|
||||
relationSyncer: relationSyncer,
|
||||
fileStore: fileStore,
|
||||
spaceService: spaceService,
|
||||
objectCreator: objectCreator,
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestObjectCreator_Create(t *testing.T) {
|
|||
mockSpace := mock_clientspace.NewMockSpace(t)
|
||||
mockSpace.EXPECT().IsReadOnly().Return(true)
|
||||
mockService.EXPECT().Get(context.Background(), spaceID).Return(mockSpace, nil)
|
||||
service := New(blockService, nil, nil, nil, nil, mockService, objectcreator.NewCreator())
|
||||
service := New(blockService, nil, nil, nil, mockService, objectcreator.NewCreator())
|
||||
|
||||
importedSpaceId := "importedSpaceID"
|
||||
identity := "identity"
|
||||
|
|
|
@ -50,13 +50,12 @@ func NewDataObject(ctx context.Context,
|
|||
}
|
||||
|
||||
type Task struct {
|
||||
spaceID string
|
||||
sn *common.Snapshot
|
||||
oc Service
|
||||
sn *common.Snapshot
|
||||
oc Service
|
||||
}
|
||||
|
||||
func NewTask(spaceID string, sn *common.Snapshot, oc Service) *Task {
|
||||
return &Task{sn: sn, oc: oc, spaceID: spaceID}
|
||||
func NewTask(sn *common.Snapshot, oc Service) *Task {
|
||||
return &Task{sn: sn, oc: oc}
|
||||
}
|
||||
|
||||
func (t *Task) Execute(data interface{}) interface{} {
|
||||
|
|
|
@ -10,8 +10,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/common"
|
||||
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
|
||||
"github.com/anyproto/anytype-heart/core/files"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileobject"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
@ -19,9 +17,7 @@ import (
|
|||
type fileObject struct {
|
||||
treeObject *treeObject
|
||||
|
||||
blockService *block.Service
|
||||
fileService files.Service
|
||||
fileObjectService fileobject.Service
|
||||
blockService *block.Service
|
||||
}
|
||||
|
||||
func (o *fileObject) GetIDAndPayload(ctx context.Context, spaceId string, sn *common.Snapshot, timestamp time.Time, getExisting bool, origin objectorigin.ObjectOrigin) (string, treestorage.TreeStorageCreatePayload, error) {
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/common"
|
||||
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
|
||||
"github.com/anyproto/anytype-heart/core/files"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileobject"
|
||||
sb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
|
@ -26,7 +25,6 @@ type IDProvider interface {
|
|||
}
|
||||
|
||||
type Provider struct {
|
||||
objectStore objectstore.ObjectStore
|
||||
idProviderBySmartBlockType map[sb.SmartBlockType]IDProvider
|
||||
}
|
||||
|
||||
|
@ -36,20 +34,16 @@ func NewIDProvider(
|
|||
blockService *block.Service,
|
||||
fileStore filestore.FileStore,
|
||||
fileObjectService fileobject.Service,
|
||||
fileService files.Service,
|
||||
) IDProvider {
|
||||
p := &Provider{
|
||||
objectStore: objectStore,
|
||||
idProviderBySmartBlockType: make(map[sb.SmartBlockType]IDProvider, 0),
|
||||
}
|
||||
existingObject := newExistingObject(objectStore)
|
||||
treeObject := newTreeObject(existingObject, spaceService)
|
||||
derivedObject := newDerivedObject(existingObject, spaceService)
|
||||
fileObject := &fileObject{
|
||||
treeObject: treeObject,
|
||||
blockService: blockService,
|
||||
fileService: fileService,
|
||||
fileObjectService: fileObjectService,
|
||||
treeObject: treeObject,
|
||||
blockService: blockService,
|
||||
}
|
||||
oldFile := &oldFile{
|
||||
blockService: blockService,
|
||||
|
|
|
@ -14,30 +14,22 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileobject"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
oserror "github.com/anyproto/anytype-heart/util/os"
|
||||
)
|
||||
|
||||
type FileSyncer struct {
|
||||
service *block.Service
|
||||
objectStore objectstore.ObjectStore
|
||||
fileStore filestore.FileStore
|
||||
fileObjectService fileobject.Service
|
||||
}
|
||||
|
||||
func NewFileSyncer(
|
||||
service *block.Service,
|
||||
fileStore filestore.FileStore,
|
||||
fileObjectService fileobject.Service,
|
||||
objectStore objectstore.ObjectStore,
|
||||
) *FileSyncer {
|
||||
return &FileSyncer{
|
||||
service: service,
|
||||
fileStore: fileStore,
|
||||
fileObjectService: fileObjectService,
|
||||
objectStore: objectStore,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/process"
|
||||
"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"
|
||||
"github.com/anyproto/anytype-heart/core/filestorage/filesync"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
|
@ -95,12 +94,11 @@ func (i *Import) Init(a *app.App) (err error) {
|
|||
store := app.MustComponent[objectstore.ObjectStore](a)
|
||||
i.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
fileObjectService := app.MustComponent[fileobject.Service](a)
|
||||
fileService := app.MustComponent[files.Service](a)
|
||||
i.idProvider = objectid.NewIDProvider(store, spaceService, i.s, i.fileStore, fileObjectService, fileService)
|
||||
factory := syncer.New(syncer.NewFileSyncer(i.s, i.fileStore, fileObjectService, store), syncer.NewBookmarkSyncer(i.s), syncer.NewIconSyncer(i.s, fileObjectService))
|
||||
i.idProvider = objectid.NewIDProvider(store, spaceService, i.s, i.fileStore, fileObjectService)
|
||||
factory := syncer.New(syncer.NewFileSyncer(i.s, fileObjectService), syncer.NewBookmarkSyncer(i.s), syncer.NewIconSyncer(i.s, fileObjectService))
|
||||
relationSyncer := syncer.NewFileRelationSyncer(i.s, fileObjectService)
|
||||
objectCreator := app.MustComponent[objectcreator.Service](a)
|
||||
i.oc = creator.New(i.s, factory, store, relationSyncer, i.fileStore, spaceService, objectCreator)
|
||||
i.oc = creator.New(i.s, factory, store, relationSyncer, spaceService, objectCreator)
|
||||
i.fileSync = app.MustComponent[filesync.FileSync](a)
|
||||
return nil
|
||||
}
|
||||
|
@ -322,7 +320,7 @@ func (i *Import) createObjects(ctx context.Context,
|
|||
do := creator.NewDataObject(ctx, oldIDToNew, createPayloads, filesIDs, origin, req.SpaceId)
|
||||
pool := workerpool.NewPool(numWorkers)
|
||||
progress.SetProgressMessage("Create objects")
|
||||
go i.addWork(req.SpaceId, res, pool)
|
||||
go i.addWork(res, pool)
|
||||
go pool.Start(do)
|
||||
details := i.readResultFromPool(pool, req.Mode, allErrors, progress)
|
||||
return details, oldIDToNew[res.RootCollectionID]
|
||||
|
@ -436,9 +434,9 @@ func (i *Import) getObjectID(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (i *Import) addWork(spaceID string, res *common.Response, pool *workerpool.WorkerPool) {
|
||||
func (i *Import) addWork(res *common.Response, pool *workerpool.WorkerPool) {
|
||||
for _, snapshot := range res.Snapshots {
|
||||
t := creator.NewTask(spaceID, snapshot, i.oc)
|
||||
t := creator.NewTask(snapshot, i.oc)
|
||||
stop := pool.AddWork(t)
|
||||
if stop {
|
||||
break
|
||||
|
|
|
@ -41,14 +41,12 @@ type blocksRenderer struct {
|
|||
inTable bool
|
||||
listParentID string
|
||||
listNestIsNum []bool
|
||||
listNestLevel uint
|
||||
}
|
||||
|
||||
func newBlocksRenderer(baseFilepath string, allFileShortPaths []string, inTable bool) *blocksRenderer {
|
||||
return &blocksRenderer{
|
||||
baseFilepath: baseFilepath,
|
||||
allFileShortPaths: allFileShortPaths,
|
||||
listNestLevel: 0,
|
||||
inTable: inTable,
|
||||
}
|
||||
}
|
||||
|
@ -159,10 +157,8 @@ func (r *blocksRenderer) addChildID(cID string) {
|
|||
func (r *blocksRenderer) SetListState(entering bool, isNumbered bool) {
|
||||
if entering {
|
||||
r.listNestIsNum = append(r.listNestIsNum, isNumbered)
|
||||
r.listNestLevel++
|
||||
} else if len(r.listNestIsNum) > 0 {
|
||||
r.listNestIsNum = r.listNestIsNum[:len(r.listNestIsNum)-1]
|
||||
r.listNestLevel--
|
||||
}
|
||||
|
||||
if len(r.listNestIsNum) > 1 {
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"github.com/globalsign/mgo/bson"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/text"
|
||||
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
|
@ -235,3 +237,54 @@ func TestCloseTextBlock(t *testing.T) {
|
|||
assert.Equal(t, "id2", renderer.blocks[1].ChildrenIds[0])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_renderCodeBloc(t *testing.T) {
|
||||
t.Run("simple case", func(t *testing.T) {
|
||||
// given
|
||||
r := NewRenderer(newBlocksRenderer("", nil, false))
|
||||
node := ast.NewCodeBlock()
|
||||
segments := text.NewSegments()
|
||||
segments.Append(text.Segment{
|
||||
Start: 0,
|
||||
Stop: 4,
|
||||
})
|
||||
node.SetLines(segments)
|
||||
|
||||
// when
|
||||
_, err := r.renderCodeBlock(nil, []byte("test"), node, true)
|
||||
assert.Nil(t, err)
|
||||
_, err = r.renderCodeBlock(nil, []byte("test"), node, false)
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, r.blocks, 1)
|
||||
assert.Equal(t, "test", r.blocks[0].GetText().GetText())
|
||||
assert.Equal(t, r.blocks[0].GetText().GetStyle(), model.BlockContentText_Code)
|
||||
})
|
||||
t.Run("2 lines", func(t *testing.T) {
|
||||
// given
|
||||
r := NewRenderer(newBlocksRenderer("", nil, false))
|
||||
node := ast.NewCodeBlock()
|
||||
segments := text.NewSegments()
|
||||
segments.Append(text.Segment{
|
||||
Start: 0,
|
||||
Stop: 5,
|
||||
})
|
||||
segments.Append(text.Segment{
|
||||
Start: 5,
|
||||
Stop: 8,
|
||||
})
|
||||
node.SetLines(segments)
|
||||
|
||||
// when
|
||||
_, err := r.renderCodeBlock(nil, []byte("testtest"), node, true)
|
||||
assert.Nil(t, err)
|
||||
_, err = r.renderCodeBlock(nil, []byte("testtest"), node, false)
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, r.blocks, 1)
|
||||
assert.Equal(t, "testtest", r.blocks[0].GetText().GetText())
|
||||
assert.Equal(t, model.BlockContentText_Code, r.blocks[0].GetText().GetStyle())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,11 +14,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
||||
var (
|
||||
pasteCmdArgs = "pbpaste"
|
||||
copyCmdArgs = "pbcopy"
|
||||
)
|
||||
|
||||
type TestCase struct {
|
||||
Blocks []map[string]interface{} `json:"blocks"`
|
||||
HTML string `json:"html"`
|
||||
|
|
|
@ -192,11 +192,8 @@ func getCustomHTMLRules() []html2md.Rule {
|
|||
img := html2md.Rule{
|
||||
Filter: []string{"img"},
|
||||
Replacement: func(content string, selec *goquery.Selection, options *html2md.Options) *string {
|
||||
var (
|
||||
src, title string
|
||||
ok bool
|
||||
)
|
||||
if src, ok = selec.Attr("src"); !ok {
|
||||
var src, title string
|
||||
if src = extractImageSource(selec); src == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -233,6 +230,19 @@ func getCustomHTMLRules() []html2md.Rule {
|
|||
simpleText, blockquote, italic, code, bdo, div, img, table}
|
||||
}
|
||||
|
||||
func extractImageSource(selec *goquery.Selection) string {
|
||||
var (
|
||||
src string
|
||||
ok bool
|
||||
)
|
||||
if src, ok = selec.Attr("src"); !ok || src == "" {
|
||||
if src, ok = selec.Attr("data-src"); !ok || src == "" {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
func addHeaderRow(content string, numberOfCells int, numberOfRows int) string {
|
||||
numberOfColumns := numberOfCells / numberOfRows
|
||||
|
||||
|
|
|
@ -121,6 +121,9 @@ func (r *Renderer) renderCodeBlock(_ util.BufWriter,
|
|||
n ast.Node,
|
||||
entering bool) (ast.WalkStatus, error) {
|
||||
r.openTextBlockWithStyle(entering, model.BlockContentText_Code, nil)
|
||||
if entering {
|
||||
r.writeLines(source, n)
|
||||
}
|
||||
return ast.WalkContinue, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -217,8 +217,23 @@
|
|||
"blocks": [{"id":"1","Content":{"file":{"name":"http://static.com/image.png","type":2}}}]
|
||||
},
|
||||
{
|
||||
"desc": "section linm",
|
||||
"desc": "section link",
|
||||
"html": "<img class=\"logo-icon\" src=\"#description\" alt=\"\">",
|
||||
"blocks": [{"id":"1","Content":{"file":{"name":"http://test.com/test#description","type":2}}}]
|
||||
},
|
||||
{
|
||||
"desc": "image with data-src atr",
|
||||
"html": "<img class=\"logo-icon\" data-src=\"/static/image.png\" alt=\"\">",
|
||||
"blocks": [{"id":"1","Content":{"file":{"name":"http://test.com/static/image.png","type":2}}}]
|
||||
},
|
||||
{
|
||||
"desc": "image without src",
|
||||
"html": "<img class=\"logo-icon\" alt=\"\">",
|
||||
"blocks": null
|
||||
},
|
||||
{
|
||||
"desc": "image with empty src",
|
||||
"html": "<img class=\"logo-icon\" src=\"\" data-src=\"\" alt=\"\">",
|
||||
"blocks": null
|
||||
}
|
||||
]
|
|
@ -36,31 +36,6 @@ var (
|
|||
'\u205F': struct{}{}, // Medium mathemtical space.
|
||||
'\u3000': struct{}{}, // Ideographic space.
|
||||
}
|
||||
|
||||
// Whitespace line replacement character map.
|
||||
unicodeWhitespaceLineRepl = map[rune]struct{}{
|
||||
'\u0009': struct{}{}, // Character tabulation (HT.)
|
||||
'\u000A': struct{}{}, // Line feed.
|
||||
'\u0020': struct{}{}, // Space.
|
||||
'\u00A0': struct{}{}, // No-break space.
|
||||
'\u180E': struct{}{}, // Mongolian vowel separator.
|
||||
'\u2000': struct{}{}, // En quad.
|
||||
'\u2001': struct{}{}, // Em quad.
|
||||
'\u2002': struct{}{}, // En space.
|
||||
'\u2003': struct{}{}, // Em space.
|
||||
'\u2004': struct{}{}, // Three-per-em space.
|
||||
'\u2005': struct{}{}, // Four-per-em space.
|
||||
'\u2006': struct{}{}, // Six-per-em space.
|
||||
'\u2007': struct{}{}, // Figure space.
|
||||
'\u2008': struct{}{}, // Punctuation space.
|
||||
'\u2009': struct{}{}, // Thin space.
|
||||
'\u200A': struct{}{}, // Hair space.
|
||||
'\u2028': struct{}{}, // Line separator.
|
||||
'\u2029': struct{}{}, // Paragraph separator.
|
||||
'\u202F': struct{}{}, // Narrow no-break space.
|
||||
'\u205F': struct{}{}, // Medium mathemtical space.
|
||||
'\u3000': struct{}{}, // Ideographic space.
|
||||
}
|
||||
)
|
||||
|
||||
// Normalize string.
|
||||
|
|
|
@ -28,7 +28,6 @@ const (
|
|||
|
||||
type Service struct {
|
||||
blockService *block.Service
|
||||
client *client.Client
|
||||
propertyService *property.Service
|
||||
}
|
||||
|
||||
|
@ -36,7 +35,6 @@ type Service struct {
|
|||
func New(client *client.Client) *Service {
|
||||
return &Service{
|
||||
blockService: block.New(client),
|
||||
client: client,
|
||||
propertyService: property.New(client),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ func Test_handlePagePropertiesSelect(t *testing.T) {
|
|||
assert.Equal(t, options[0].Details.Fields[bundle.RelationKeyRelationOptionColor.String()], pbtypes.String("blue"))
|
||||
}
|
||||
|
||||
//Relation already exist
|
||||
// Relation already exist
|
||||
selectProperty = property.SelectItem{
|
||||
Object: "",
|
||||
ID: "id",
|
||||
|
@ -277,7 +277,7 @@ func Test_handlePagePropertiesStatus(t *testing.T) {
|
|||
assert.Equal(t, options[0].Details.Fields[bundle.RelationKeyRelationOptionColor.String()], pbtypes.String("pink"))
|
||||
}
|
||||
|
||||
//Relation already exist
|
||||
// Relation already exist
|
||||
statusProperty = property.StatusItem{
|
||||
ID: "id",
|
||||
Type: property.PropertyConfigStatus,
|
||||
|
@ -304,6 +304,40 @@ func Test_handlePagePropertiesStatus(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_handlePageProperties(t *testing.T) {
|
||||
t.Run("empty status property", func(t *testing.T) {
|
||||
c := client.NewClient()
|
||||
details := make(map[string]*types.Value, 0)
|
||||
|
||||
statusProperty := property.StatusItem{
|
||||
ID: "id",
|
||||
Type: property.PropertyConfigStatus,
|
||||
}
|
||||
properties := property.Properties{"Status": &statusProperty}
|
||||
pageTask := Task{
|
||||
propertyService: property.New(c),
|
||||
relationOptCreateMutex: &sync.Mutex{},
|
||||
relationCreateMutex: &sync.Mutex{},
|
||||
p: Page{Properties: properties},
|
||||
}
|
||||
req := &property.PropertiesStore{
|
||||
PropertyIdsToSnapshots: map[string]*model.SmartBlockSnapshotBase{},
|
||||
RelationsIdsToOptions: map[string][]*model.SmartBlockSnapshotBase{},
|
||||
}
|
||||
do := &DataObject{
|
||||
request: &api.NotionImportContext{},
|
||||
relations: req,
|
||||
}
|
||||
snapshots, _ := pageTask.handlePageProperties(do, details)
|
||||
|
||||
assert.Len(t, snapshots, 1) // 1 relation without option
|
||||
assert.Len(t, req.PropertyIdsToSnapshots, 1)
|
||||
assert.NotEmpty(t, req.PropertyIdsToSnapshots["id"])
|
||||
key := pbtypes.GetString(req.PropertyIdsToSnapshots["id"].Details, bundle.RelationKeyRelationKey.String())
|
||||
assert.NotEmpty(t, details[key])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_handlePagePropertiesNumber(t *testing.T) {
|
||||
c := client.NewClient()
|
||||
details := make(map[string]*types.Value, 0)
|
||||
|
@ -384,7 +418,7 @@ func Test_handlePagePropertiesMultiSelect(t *testing.T) {
|
|||
assert.Equal(t, options[0].Details.Fields[bundle.RelationKeyRelationOptionColor.String()], pbtypes.String("blue"))
|
||||
}
|
||||
|
||||
//Relation already exist
|
||||
// Relation already exist
|
||||
multiSelectProperty = property.MultiSelectItem{
|
||||
ID: "id",
|
||||
Type: string(property.PropertyConfigTypeMultiSelect),
|
||||
|
|
|
@ -437,7 +437,7 @@ func selectItemOptions(property *property.SelectItem, rel string, relation *prop
|
|||
}
|
||||
|
||||
func statusItemOptions(property *property.StatusItem, rel string, relation *property.PropertiesStore) *model.SmartBlockSnapshotBase {
|
||||
if property.Status.Name == "" {
|
||||
if property.Status == nil || property.Status.Name == "" {
|
||||
return nil
|
||||
}
|
||||
exist, optionID := isOptionAlreadyExist(property.Status.Name, rel, relation)
|
||||
|
|
|
@ -586,7 +586,11 @@ type Status struct {
|
|||
}
|
||||
|
||||
func (sp *StatusItem) SetDetail(key string, details map[string]*types.Value) {
|
||||
details[key] = pbtypes.StringList([]string{sp.Status.ID})
|
||||
if sp.Status != nil {
|
||||
details[key] = pbtypes.StringList([]string{sp.Status.ID})
|
||||
} else {
|
||||
details[key] = pbtypes.StringList([]string{})
|
||||
}
|
||||
}
|
||||
|
||||
func (sp *StatusItem) GetPropertyType() ConfigType {
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/restriction"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/files"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
|
@ -58,10 +57,8 @@ type service struct {
|
|||
objectStore objectstore.ObjectStore
|
||||
collectionService CollectionService
|
||||
bookmarkService bookmarkService
|
||||
app *app.App
|
||||
spaceService space.Service
|
||||
templateService TemplateService
|
||||
fileService files.Service
|
||||
}
|
||||
|
||||
func NewCreator() Service {
|
||||
|
@ -74,8 +71,6 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
s.collectionService = app.MustComponent[CollectionService](a)
|
||||
s.spaceService = app.MustComponent[space.Service](a)
|
||||
s.templateService = app.MustComponent[TemplateService](a)
|
||||
s.fileService = app.MustComponent[files.Service](a)
|
||||
s.app = a
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -104,8 +104,6 @@ func (s *service) InstallBundledObjects(
|
|||
objects = append(objects, newDetails)
|
||||
}
|
||||
}
|
||||
|
||||
s.reviseSystemObjects(space, existingObjectMap)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ type Service interface {
|
|||
}
|
||||
|
||||
type Builder struct {
|
||||
graphService Service //nolint:unused
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
objectStore objectstore.ObjectStore
|
||||
subscriptionService subscription.Service
|
||||
|
|
|
@ -2,7 +2,6 @@ package treemanager
|
|||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||
|
@ -25,9 +24,6 @@ type treeManager struct {
|
|||
spaceService space.Service
|
||||
|
||||
onDelete func(id domain.FullID) error
|
||||
|
||||
syncStarted bool
|
||||
syncerLock sync.Mutex
|
||||
}
|
||||
|
||||
func New() treemanager.TreeManager {
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package restriction
|
||||
|
||||
import (
|
||||
"github.com/samber/lo"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
@ -99,15 +103,33 @@ func (dr DataviewRestrictions) Equal(dr2 DataviewRestrictions) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *service) getDataviewRestrictions(rh RestrictionHolder) DataviewRestrictions {
|
||||
func getDataviewRestrictions(rh RestrictionHolder) DataviewRestrictions {
|
||||
if dr, ok := dataviewRestrictionsBySBType[rh.Type()]; ok {
|
||||
return dr
|
||||
}
|
||||
|
||||
uk := rh.UniqueKey()
|
||||
if uk != nil {
|
||||
return GetDataviewRestrictionsForUniqueKey(uk)
|
||||
return getDataviewRestrictionsForUniqueKey(uk)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDataviewRestrictionsForUniqueKey(uk domain.UniqueKey) DataviewRestrictions {
|
||||
switch uk.SmartblockType() {
|
||||
case smartblock.SmartBlockTypeObjectType:
|
||||
key := uk.InternalKey()
|
||||
if lo.Contains(bundle.InternalTypes, domain.TypeKey(key)) {
|
||||
return DataviewRestrictions{
|
||||
model.RestrictionsDataviewRestrictions{
|
||||
BlockId: DataviewBlockId,
|
||||
Restrictions: []model.RestrictionsDataviewRestriction{model.Restrictions_DVCreateObject},
|
||||
},
|
||||
}
|
||||
}
|
||||
case smartblock.SmartBlockTypeRelation:
|
||||
// should we handle this?
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestService_DataviewRestrictions(t *testing.T) {
|
||||
s := newFixture(t)
|
||||
s := service{}
|
||||
|
||||
t.Run("internal types have restrictions", func(t *testing.T) {
|
||||
for _, typeKey := range bundle.InternalTypes {
|
||||
|
@ -38,14 +38,12 @@ func TestService_DataviewRestrictions(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("ordinary objects don't have restrictions", func(t *testing.T) {
|
||||
objectTypeID := "derivedFrom(page)"
|
||||
restrictions := s.GetRestrictions(
|
||||
newRestrictionHolder(
|
||||
smartblock.SmartBlockTypePage,
|
||||
model.ObjectType_basic,
|
||||
nil,
|
||||
objectTypeID,
|
||||
),
|
||||
&restrictionHolder{
|
||||
sbType: smartblock.SmartBlockTypePage,
|
||||
uniqueKey: nil,
|
||||
layout: model.ObjectType_basic,
|
||||
},
|
||||
)
|
||||
assert.Equal(t, dvRestrictNo, restrictions.Dataview)
|
||||
})
|
||||
|
|
|
@ -1,61 +1,58 @@
|
|||
package restriction
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/mock_objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider/mock_typeprovider"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
Service
|
||||
objectStoreMock *mock_objectstore.MockObjectStore
|
||||
const noLayout = -1
|
||||
|
||||
type restrictionHolder struct {
|
||||
sbType smartblock.SmartBlockType
|
||||
uniqueKey domain.UniqueKey
|
||||
layout model.ObjectTypeLayout
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
objectStore := mock_objectstore.NewMockObjectStore(t)
|
||||
objectStore.EXPECT().Name().Return("objectstore")
|
||||
|
||||
sbtProvider := mock_typeprovider.NewMockSmartBlockTypeProvider(t)
|
||||
sbtProvider.EXPECT().Name().Return("sbtProvider")
|
||||
|
||||
a := &app.App{}
|
||||
a.Register(objectStore)
|
||||
a.Register(sbtProvider)
|
||||
s := New()
|
||||
err := s.Init(a)
|
||||
require.NoError(t, err)
|
||||
return &fixture{
|
||||
Service: s,
|
||||
objectStoreMock: objectStore,
|
||||
}
|
||||
func (rh *restrictionHolder) Type() smartblock.SmartBlockType {
|
||||
return rh.sbType
|
||||
}
|
||||
|
||||
func fakeDerivedID(key string) string {
|
||||
return fmt.Sprintf("derivedFrom(%s)", key)
|
||||
func (rh *restrictionHolder) Layout() (model.ObjectTypeLayout, bool) {
|
||||
return rh.layout, rh.layout != noLayout
|
||||
}
|
||||
|
||||
func (rh *restrictionHolder) UniqueKey() domain.UniqueKey {
|
||||
return rh.uniqueKey
|
||||
}
|
||||
|
||||
func givenObjectType(typeKey domain.TypeKey) RestrictionHolder {
|
||||
return newRestrictionHolder(
|
||||
smartblock.SmartBlockTypeObjectType,
|
||||
model.ObjectType_objectType,
|
||||
domain.MustUniqueKey(smartblock.SmartBlockTypeObjectType, typeKey.String()),
|
||||
fakeDerivedID(typeKey.String()),
|
||||
)
|
||||
return &restrictionHolder{
|
||||
sbType: smartblock.SmartBlockTypeObjectType,
|
||||
layout: model.ObjectType_objectType,
|
||||
uniqueKey: domain.MustUniqueKey(smartblock.SmartBlockTypeObjectType, typeKey.String()),
|
||||
}
|
||||
}
|
||||
|
||||
func givenRelation(relationKey domain.RelationKey) RestrictionHolder {
|
||||
return newRestrictionHolder(
|
||||
smartblock.SmartBlockTypeRelation,
|
||||
model.ObjectType_relation,
|
||||
domain.MustUniqueKey(smartblock.SmartBlockTypeRelation, relationKey.String()),
|
||||
fakeDerivedID(relationKey.String()),
|
||||
)
|
||||
return &restrictionHolder{
|
||||
sbType: smartblock.SmartBlockTypeRelation,
|
||||
layout: model.ObjectType_relation,
|
||||
uniqueKey: domain.MustUniqueKey(smartblock.SmartBlockTypeRelation, relationKey.String()),
|
||||
}
|
||||
}
|
||||
|
||||
func givenRestrictionHolder(sbType smartblock.SmartBlockType, typeKey domain.TypeKey) RestrictionHolder {
|
||||
layout := model.ObjectType_basic
|
||||
t, err := bundle.GetType(typeKey)
|
||||
if err == nil {
|
||||
layout = t.Layout
|
||||
}
|
||||
uk, _ := domain.NewUniqueKey(sbType, "")
|
||||
return &restrictionHolder{
|
||||
sbType: sbType,
|
||||
layout: layout,
|
||||
uniqueKey: uk,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,12 +37,6 @@ var (
|
|||
model.Restrictions_TypeChange,
|
||||
model.Restrictions_Template,
|
||||
}
|
||||
collectionRestrictions = ObjectRestrictions{
|
||||
model.Restrictions_Blocks,
|
||||
model.Restrictions_LayoutChange,
|
||||
model.Restrictions_TypeChange,
|
||||
model.Restrictions_Template,
|
||||
}
|
||||
sysTypesRestrictions = ObjectRestrictions{
|
||||
model.Restrictions_Blocks,
|
||||
model.Restrictions_LayoutChange,
|
||||
|
@ -65,8 +59,8 @@ var (
|
|||
model.ObjectType_basic: {},
|
||||
model.ObjectType_profile: {},
|
||||
model.ObjectType_todo: {},
|
||||
model.ObjectType_set: collectionRestrictions,
|
||||
model.ObjectType_collection: collectionRestrictions,
|
||||
model.ObjectType_set: objRestrictEdit,
|
||||
model.ObjectType_collection: objRestrictEdit,
|
||||
model.ObjectType_objectType: objRestrictEdit,
|
||||
model.ObjectType_relation: objRestrictEdit,
|
||||
model.ObjectType_file: objFileRestrictions,
|
||||
|
@ -189,10 +183,10 @@ func (or ObjectRestrictions) ToPB() *types.Value {
|
|||
return pbtypes.IntList(ints...)
|
||||
}
|
||||
|
||||
func (s *service) getObjectRestrictions(rh RestrictionHolder) (r ObjectRestrictions) {
|
||||
func getObjectRestrictions(rh RestrictionHolder) (r ObjectRestrictions) {
|
||||
uk := rh.UniqueKey()
|
||||
if uk != nil {
|
||||
return GetRestrictionsForUniqueKey(rh.UniqueKey())
|
||||
if uk != nil && uk.InternalKey() != "" {
|
||||
return getRestrictionsForUniqueKey(uk)
|
||||
}
|
||||
|
||||
var ok bool
|
||||
|
@ -208,7 +202,7 @@ func (s *service) getObjectRestrictions(rh RestrictionHolder) (r ObjectRestricti
|
|||
return
|
||||
}
|
||||
|
||||
func GetRestrictionsForUniqueKey(uk domain.UniqueKey) (r ObjectRestrictions) {
|
||||
func getRestrictionsForUniqueKey(uk domain.UniqueKey) (r ObjectRestrictions) {
|
||||
r = objectRestrictionsBySBType[uk.SmartblockType()]
|
||||
switch uk.SmartblockType() {
|
||||
case smartblock.SmartBlockTypeObjectType:
|
||||
|
@ -229,21 +223,3 @@ func GetRestrictionsForUniqueKey(uk domain.UniqueKey) (r ObjectRestrictions) {
|
|||
// we assume that all sb types exist in objectRestrictionsBySBType
|
||||
return r
|
||||
}
|
||||
|
||||
func GetDataviewRestrictionsForUniqueKey(uk domain.UniqueKey) DataviewRestrictions {
|
||||
switch uk.SmartblockType() {
|
||||
case smartblock.SmartBlockTypeObjectType:
|
||||
key := uk.InternalKey()
|
||||
if lo.Contains(bundle.InternalTypes, domain.TypeKey(key)) {
|
||||
return DataviewRestrictions{
|
||||
model.RestrictionsDataviewRestrictions{
|
||||
BlockId: DataviewBlockId,
|
||||
Restrictions: []model.RestrictionsDataviewRestriction{model.Restrictions_DVCreateObject},
|
||||
},
|
||||
}
|
||||
}
|
||||
case smartblock.SmartBlockTypeRelation:
|
||||
// should we handle this?
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -10,51 +10,44 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
||||
// TODO Use constructors instead for initializing restrictionHolder structures by hand. See givenObjectType and givenRelation
|
||||
func TestService_ObjectRestrictionsById(t *testing.T) {
|
||||
rest := newFixture(t)
|
||||
rs := service{}
|
||||
|
||||
assert.ErrorIs(t, rest.GetRestrictions(&restrictionHolder{
|
||||
sbType: coresb.SmartBlockTypeAnytypeProfile,
|
||||
objectTypeID: "",
|
||||
}).Object.Check(
|
||||
model.Restrictions_Blocks,
|
||||
model.Restrictions_LayoutChange,
|
||||
model.Restrictions_TypeChange,
|
||||
model.Restrictions_Delete,
|
||||
model.Restrictions_Duplicate,
|
||||
),
|
||||
ErrRestricted,
|
||||
)
|
||||
t.Run("anytype profile should have all restrictions", func(t *testing.T) {
|
||||
assert.ErrorIs(t, rs.GetRestrictions(givenRestrictionHolder(coresb.SmartBlockTypeAnytypeProfile, bundle.TypeKeyProfile)).Object.Check(
|
||||
objRestrictAll...,
|
||||
), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.ErrorIs(t, rest.GetRestrictions(&restrictionHolder{
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
layout: model.ObjectType_collection,
|
||||
objectTypeID: bundle.TypeKeyCollection.URL(),
|
||||
}).Object.Check(model.Restrictions_Blocks),
|
||||
ErrRestricted,
|
||||
)
|
||||
t.Run("sets and collections should have edit restrictions", func(t *testing.T) {
|
||||
collection := givenRestrictionHolder(coresb.SmartBlockTypePage, bundle.TypeKeyCollection)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(collection).Object.Check(objRestrictEdit...), ErrRestricted)
|
||||
set := givenRestrictionHolder(coresb.SmartBlockTypePage, bundle.TypeKeySet)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(set).Object.Check(objRestrictEdit...), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.NoError(t, rest.GetRestrictions(&restrictionHolder{
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
objectTypeID: bundle.TypeKeyPage.URL(),
|
||||
}).Object.Check(model.Restrictions_Blocks))
|
||||
t.Run("plain pages should not have any restrictions", func(t *testing.T) {
|
||||
page := givenRestrictionHolder(coresb.SmartBlockTypePage, bundle.TypeKeyPage)
|
||||
for _, restriction := range objRestrictAll {
|
||||
assert.NoError(t, rs.GetRestrictions(page).Object.Check(restriction))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("system type", func(t *testing.T) {
|
||||
assert.ErrorIs(t, rest.GetRestrictions(givenObjectType(bundle.TypeKeyObjectType)).Object.Check(
|
||||
assert.ErrorIs(t, rs.GetRestrictions(givenObjectType(bundle.TypeKeyObjectType)).Object.Check(
|
||||
model.Restrictions_Details,
|
||||
model.Restrictions_Delete,
|
||||
), ErrRestricted)
|
||||
})
|
||||
|
||||
t.Run("system type restricted creation", func(t *testing.T) {
|
||||
assert.ErrorIs(t, rest.GetRestrictions(givenObjectType(bundle.TypeKeyParticipant)).Object.Check(
|
||||
assert.ErrorIs(t, rs.GetRestrictions(givenObjectType(bundle.TypeKeyParticipant)).Object.Check(
|
||||
model.Restrictions_CreateObjectOfThisType,
|
||||
), ErrRestricted)
|
||||
})
|
||||
|
||||
t.Run("ordinary type", func(t *testing.T) {
|
||||
assert.NoError(t, rest.GetRestrictions(givenObjectType(bundle.TypeKeyDailyPlan)).Object.Check(
|
||||
assert.NoError(t, rs.GetRestrictions(givenObjectType(bundle.TypeKeyDailyPlan)).Object.Check(
|
||||
model.Restrictions_Details,
|
||||
model.Restrictions_Delete,
|
||||
model.Restrictions_CreateObjectOfThisType,
|
||||
|
@ -62,29 +55,25 @@ func TestService_ObjectRestrictionsById(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("ordinary type has basic restrictions", func(t *testing.T) {
|
||||
assert.ErrorIs(t, rest.GetRestrictions(givenObjectType(bundle.TypeKeyDailyPlan)).Object.Check(
|
||||
assert.ErrorIs(t, rs.GetRestrictions(givenObjectType(bundle.TypeKeyDailyPlan)).Object.Check(
|
||||
model.Restrictions_Blocks,
|
||||
model.Restrictions_LayoutChange,
|
||||
), ErrRestricted)
|
||||
})
|
||||
|
||||
t.Run("ordinary relation has basic restrictions", func(t *testing.T) {
|
||||
assert.ErrorIs(t, rest.GetRestrictions(givenObjectType(bundle.TypeKeyDailyPlan)).Object.Check(
|
||||
assert.ErrorIs(t, rs.GetRestrictions(givenObjectType(bundle.TypeKeyDailyPlan)).Object.Check(
|
||||
model.Restrictions_TypeChange,
|
||||
), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.ErrorIs(t, rest.GetRestrictions(&restrictionHolder{
|
||||
sbType: coresb.SmartBlockTypeBundledObjectType,
|
||||
layout: model.ObjectType_objectType,
|
||||
objectTypeID: bundle.TypeKeyObjectType.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Duplicate,
|
||||
model.Restrictions_Relations,
|
||||
), ErrRestricted)
|
||||
t.Run("bundled object types should have all restrictions", func(t *testing.T) {
|
||||
bundledType := givenRestrictionHolder(coresb.SmartBlockTypeBundledObjectType, bundle.TypeKeyObjectType)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(bundledType).Object.Check(objRestrictAll...), ErrRestricted)
|
||||
})
|
||||
|
||||
t.Run("ordinary relation", func(t *testing.T) {
|
||||
assert.NoError(t, rest.GetRestrictions(givenRelation(bundle.RelationKeyImdbRating)).Object.Check(
|
||||
assert.NoError(t, rs.GetRestrictions(givenRelation(bundle.RelationKeyImdbRating)).Object.Check(
|
||||
model.Restrictions_Delete,
|
||||
model.Restrictions_Relations,
|
||||
model.Restrictions_Details,
|
||||
|
@ -92,59 +81,39 @@ func TestService_ObjectRestrictionsById(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("system relation", func(t *testing.T) {
|
||||
assert.ErrorIs(t, rest.GetRestrictions(givenRelation(bundle.RelationKeyId)).Object.Check(
|
||||
assert.ErrorIs(t, rs.GetRestrictions(givenRelation(bundle.RelationKeyId)).Object.Check(
|
||||
model.Restrictions_Delete,
|
||||
model.Restrictions_Relations,
|
||||
model.Restrictions_Details,
|
||||
), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.ErrorIs(t, rest.GetRestrictions(&restrictionHolder{
|
||||
sbType: coresb.SmartBlockTypeBundledRelation,
|
||||
layout: model.ObjectType_relation,
|
||||
objectTypeID: bundle.TypeKeyRelation.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Duplicate,
|
||||
), ErrRestricted)
|
||||
t.Run("bundled object types should have all restrictions", func(t *testing.T) {
|
||||
bundledRelation := givenRestrictionHolder(coresb.SmartBlockTypeBundledRelation, bundle.TypeKeyRelation)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(bundledRelation).Object.Check(objRestrictAll...), ErrRestricted)
|
||||
})
|
||||
}
|
||||
|
||||
// TODO Use constructors instead for initializing restrictionHolder structures by hand. See givenObjectType and givenRelation
|
||||
func TestTemplateRestriction(t *testing.T) {
|
||||
rs := newFixture(t)
|
||||
rs := service{}
|
||||
|
||||
assert.ErrorIs(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "cannot make template from Template smartblock type",
|
||||
sbType: coresb.SmartBlockTypeTemplate,
|
||||
layout: model.ObjectType_basic,
|
||||
objectTypeID: bundle.TypeKeyTemplate.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Template,
|
||||
), ErrRestricted)
|
||||
t.Run("cannot make template from Template smartblock type", func(t *testing.T) {
|
||||
template := givenRestrictionHolder(coresb.SmartBlockTypeTemplate, bundle.TypeKeyTemplate)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(template).Object.Check(model.Restrictions_Template), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.ErrorIs(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "cannot make template from set or collection layout",
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
layout: model.ObjectType_collection,
|
||||
objectTypeID: bundle.TypeKeyCollection.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Template,
|
||||
), ErrRestricted)
|
||||
t.Run("cannot make template from set or collection layout", func(t *testing.T) {
|
||||
collection := givenRestrictionHolder(coresb.SmartBlockTypePage, bundle.TypeKeyCollection)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(collection).Object.Check(model.Restrictions_Template), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.ErrorIs(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "cannot make template from space layout",
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
layout: model.ObjectType_space,
|
||||
objectTypeID: bundle.TypeKeySpace.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Template,
|
||||
), ErrRestricted)
|
||||
t.Run("cannot make template from space layout", func(t *testing.T) {
|
||||
space := givenRestrictionHolder(coresb.SmartBlockTypePage, bundle.TypeKeySpace)
|
||||
assert.ErrorIs(t, rs.GetRestrictions(space).Object.Check(model.Restrictions_Template), ErrRestricted)
|
||||
})
|
||||
|
||||
assert.NoError(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "make template from object with objectType added to space",
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
layout: model.ObjectType_basic,
|
||||
objectTypeID: bundle.TypeKeyContact.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Template,
|
||||
))
|
||||
t.Run("make template from object with objectType added to space", func(t *testing.T) {
|
||||
book := givenRestrictionHolder(coresb.SmartBlockTypePage, bundle.TypeKeyBook)
|
||||
assert.NoError(t, rs.GetRestrictions(book).Object.Check(model.Restrictions_Template))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
package restriction
|
||||
|
||||
import (
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
||||
type RestrictionHolder interface {
|
||||
Type() smartblock.SmartBlockType
|
||||
Layout() (model.ObjectTypeLayout, bool)
|
||||
UniqueKey() domain.UniqueKey
|
||||
}
|
||||
|
||||
type restrictionHolder struct {
|
||||
sbType smartblock.SmartBlockType
|
||||
uniqueKey domain.UniqueKey
|
||||
layout model.ObjectTypeLayout
|
||||
objectTypeID string
|
||||
}
|
||||
|
||||
func newRestrictionHolder(sbType smartblock.SmartBlockType, layout model.ObjectTypeLayout, uk domain.UniqueKey, objectTypeID string) RestrictionHolder {
|
||||
return &restrictionHolder{
|
||||
sbType: sbType,
|
||||
layout: layout,
|
||||
uniqueKey: uk,
|
||||
objectTypeID: objectTypeID,
|
||||
}
|
||||
}
|
||||
|
||||
func (rh *restrictionHolder) Type() smartblock.SmartBlockType {
|
||||
return rh.sbType
|
||||
}
|
||||
|
||||
func (rh *restrictionHolder) Layout() (model.ObjectTypeLayout, bool) {
|
||||
return rh.layout, rh.layout != noLayout
|
||||
}
|
||||
|
||||
func (rh *restrictionHolder) ObjectTypeID() string {
|
||||
return rh.objectTypeID
|
||||
}
|
||||
|
||||
func (s *restrictionHolder) UniqueKey() domain.UniqueKey {
|
||||
return s.uniqueKey
|
||||
}
|
|
@ -5,21 +5,20 @@ import (
|
|||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
||||
const (
|
||||
CName = "restriction"
|
||||
noLayout = -1
|
||||
)
|
||||
const CName = "restriction"
|
||||
|
||||
var (
|
||||
ErrRestricted = errors.New("restricted")
|
||||
var ErrRestricted = errors.New("restricted")
|
||||
|
||||
log = logging.Logger("anytype-mw-restrictions")
|
||||
)
|
||||
type RestrictionHolder interface {
|
||||
Type() smartblock.SmartBlockType
|
||||
Layout() (model.ObjectTypeLayout, bool)
|
||||
UniqueKey() domain.UniqueKey
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
GetRestrictions(RestrictionHolder) Restrictions
|
||||
|
@ -27,16 +26,13 @@ type Service interface {
|
|||
app.Component
|
||||
}
|
||||
|
||||
type service struct {
|
||||
objectStore objectstore.ObjectStore
|
||||
}
|
||||
type service struct{}
|
||||
|
||||
func New() Service {
|
||||
return &service{}
|
||||
}
|
||||
|
||||
func (s *service) Init(a *app.App) (err error) {
|
||||
s.objectStore = app.MustComponent[objectstore.ObjectStore](a)
|
||||
func (s *service) Init(*app.App) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -46,13 +42,13 @@ func (s *service) Name() (name string) {
|
|||
|
||||
func (s *service) GetRestrictions(rh RestrictionHolder) (r Restrictions) {
|
||||
return Restrictions{
|
||||
Object: s.getObjectRestrictions(rh),
|
||||
Dataview: s.getDataviewRestrictions(rh),
|
||||
Object: getObjectRestrictions(rh),
|
||||
Dataview: getDataviewRestrictions(rh),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) CheckRestrictions(rh RestrictionHolder, cr ...model.RestrictionsObjectRestriction) error {
|
||||
r := s.getObjectRestrictions(rh)
|
||||
r := getObjectRestrictions(rh)
|
||||
if err := r.Check(cr...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/accountservice"
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
|
@ -21,7 +20,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/basic"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/collection"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/converter"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/file"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
|
@ -32,14 +30,12 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/restriction"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple/bookmark"
|
||||
"github.com/anyproto/anytype-heart/core/block/source"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/domain/objectorigin"
|
||||
"github.com/anyproto/anytype-heart/core/event"
|
||||
"github.com/anyproto/anytype-heart/core/files"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileobject"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileuploader"
|
||||
"github.com/anyproto/anytype-heart/core/filestorage/filesync"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
"github.com/anyproto/anytype-heart/core/syncstatus"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
|
@ -48,13 +44,11 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/database"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/util/internalflag"
|
||||
"github.com/anyproto/anytype-heart/util/linkpreview"
|
||||
"github.com/anyproto/anytype-heart/util/mutex"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/uri"
|
||||
|
@ -66,14 +60,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
CName = "block-service"
|
||||
linkObjectShare = "anytype://object/share?"
|
||||
CName = "block-service"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnexpectedBlockType = errors.New("unexpected block type")
|
||||
ErrUnknownObjectType = fmt.Errorf("unknown object type")
|
||||
ErrObjectNotFoundByOldID = fmt.Errorf("failed to find template by Source Object id")
|
||||
ErrUnexpectedBlockType = errors.New("unexpected block type")
|
||||
ErrUnknownObjectType = fmt.Errorf("unknown object type")
|
||||
)
|
||||
|
||||
var log = logging.Logger("anytype-mw-service")
|
||||
|
@ -106,10 +98,8 @@ func New() *Service {
|
|||
type Service struct {
|
||||
syncStatus syncstatus.Service
|
||||
eventSender event.Sender
|
||||
linkPreview linkpreview.LinkPreview
|
||||
process process.Service
|
||||
app *app.App
|
||||
source source.Service
|
||||
objectStore objectstore.ObjectStore
|
||||
restriction restriction.Service
|
||||
bookmark bookmarksvc.Service
|
||||
|
@ -117,14 +107,10 @@ type Service struct {
|
|||
templateService templateService
|
||||
resolver idresolver.Resolver
|
||||
spaceService space.Service
|
||||
commonAccount accountservice.Service
|
||||
fileStore filestore.FileStore
|
||||
tempDirProvider core.TempDirProvider
|
||||
layoutConverter converter.LayoutConverter
|
||||
builtinObjectService builtinObjects
|
||||
fileObjectService fileobject.Service
|
||||
|
||||
fileSync filesync.FileSync
|
||||
fileService files.Service
|
||||
fileUploaderService fileuploader.Service
|
||||
|
||||
|
@ -151,26 +137,20 @@ func (s *Service) Name() string {
|
|||
|
||||
func (s *Service) Init(a *app.App) (err error) {
|
||||
s.syncStatus = a.MustComponent(syncstatus.CName).(syncstatus.Service)
|
||||
s.linkPreview = a.MustComponent(linkpreview.CName).(linkpreview.LinkPreview)
|
||||
s.process = a.MustComponent(process.CName).(process.Service)
|
||||
s.eventSender = a.MustComponent(event.CName).(event.Sender)
|
||||
s.source = a.MustComponent(source.CName).(source.Service)
|
||||
s.objectStore = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
s.restriction = a.MustComponent(restriction.CName).(restriction.Service)
|
||||
s.bookmark = a.MustComponent("bookmark-importer").(bookmarksvc.Service)
|
||||
s.objectCreator = app.MustComponent[objectcreator.Service](a)
|
||||
s.templateService = app.MustComponent[templateService](a)
|
||||
s.spaceService = a.MustComponent(space.CName).(space.Service)
|
||||
s.commonAccount = a.MustComponent(accountservice.CName).(accountservice.Service)
|
||||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.fileSync = app.MustComponent[filesync.FileSync](a)
|
||||
s.fileService = app.MustComponent[files.Service](a)
|
||||
s.resolver = a.MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
s.fileObjectService = app.MustComponent[fileobject.Service](a)
|
||||
s.fileUploaderService = app.MustComponent[fileuploader.Service](a)
|
||||
|
||||
s.tempDirProvider = app.MustComponent[core.TempDirProvider](a)
|
||||
s.layoutConverter = app.MustComponent[converter.LayoutConverter](a)
|
||||
|
||||
s.builtinObjectService = app.MustComponent[builtinObjects](a)
|
||||
s.app = a
|
||||
|
|
|
@ -154,14 +154,7 @@ func (l *Dataview) ReorderSorts(viewID string, ids []string) error {
|
|||
}
|
||||
|
||||
func (l *Dataview) AddViewRelation(viewID string, relation *model.BlockContentDataviewRelation) error {
|
||||
view, err := l.GetView(viewID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.syncViewRelationWithRelationLinks(view)
|
||||
|
||||
view.Relations = append(view.Relations, relation)
|
||||
return nil
|
||||
return l.ReplaceViewRelation(viewID, relation.Key, relation)
|
||||
}
|
||||
|
||||
func (l *Dataview) RemoveViewRelations(viewID string, relationKeys []string) error {
|
||||
|
@ -188,7 +181,8 @@ func (l *Dataview) ReplaceViewRelation(viewID string, relationKey string, relati
|
|||
return f.Key == relationKey
|
||||
})
|
||||
if idx < 0 {
|
||||
return l.AddViewRelation(viewID, relation)
|
||||
view.Relations = append(view.Relations, relation)
|
||||
return nil
|
||||
}
|
||||
|
||||
view.Relations[idx] = relation
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
const testViewId = "viewId"
|
||||
|
||||
func makeDataviewForReorderTest(relationLinks []*model.RelationLink, relations []*model.BlockContentDataviewRelation) Block {
|
||||
func makeDataviewForViewRelationsTest(relationLinks []*model.RelationLink, relations []*model.BlockContentDataviewRelation) Block {
|
||||
return NewDataview(&model.Block{
|
||||
Content: &model.BlockContentOfDataview{
|
||||
Dataview: &model.BlockContentDataview{
|
||||
|
@ -30,7 +30,7 @@ func makeDataviewForReorderTest(relationLinks []*model.RelationLink, relations [
|
|||
|
||||
func TestReorderViewRelations(t *testing.T) {
|
||||
t.Run("reorder: add missing relation from relation links", func(t *testing.T) {
|
||||
dv := makeDataviewForReorderTest(
|
||||
dv := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
{Key: bundle.RelationKeyCreator.String(), Format: model.RelationFormat_object},
|
||||
|
@ -44,7 +44,7 @@ func TestReorderViewRelations(t *testing.T) {
|
|||
err := dv.ReorderViewRelations(testViewId, []string{bundle.RelationKeyCreator.String(), bundle.RelationKeyName.String()})
|
||||
require.NoError(t, err)
|
||||
|
||||
want := makeDataviewForReorderTest(
|
||||
want := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
{Key: bundle.RelationKeyCreator.String(), Format: model.RelationFormat_object},
|
||||
|
@ -61,7 +61,7 @@ func TestReorderViewRelations(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("reorder: remove extra relation that don't exist in relation links", func(t *testing.T) {
|
||||
dv := makeDataviewForReorderTest(
|
||||
dv := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
{Key: bundle.RelationKeyCreatedDate.String(), Format: model.RelationFormat_date},
|
||||
|
@ -76,7 +76,7 @@ func TestReorderViewRelations(t *testing.T) {
|
|||
err := dv.ReorderViewRelations(testViewId, []string{bundle.RelationKeyName.String(), bundle.RelationKeyCreator.String(), bundle.RelationKeyDescription.String()})
|
||||
require.NoError(t, err)
|
||||
|
||||
want := makeDataviewForReorderTest(
|
||||
want := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
{Key: bundle.RelationKeyCreatedDate.String(), Format: model.RelationFormat_date},
|
||||
|
@ -89,5 +89,119 @@ func TestReorderViewRelations(t *testing.T) {
|
|||
|
||||
assert.Equal(t, want, dv)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestReplaceViewRelation(t *testing.T) {
|
||||
t.Run("add new relation", func(t *testing.T) {
|
||||
dv := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
},
|
||||
[]*model.BlockContentDataviewRelation{},
|
||||
)
|
||||
|
||||
err := dv.ReplaceViewRelation(testViewId, bundle.RelationKeyDescription.String(), &model.BlockContentDataviewRelation{
|
||||
Key: bundle.RelationKeyDescription.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
want := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
},
|
||||
[]*model.BlockContentDataviewRelation{
|
||||
// Added automatically from relation links
|
||||
{
|
||||
Key: bundle.RelationKeyName.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: false,
|
||||
},
|
||||
{
|
||||
Key: bundle.RelationKeyDescription.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert.Equal(t, want, dv)
|
||||
})
|
||||
t.Run("replace existing", func(t *testing.T) {
|
||||
dv := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
},
|
||||
[]*model.BlockContentDataviewRelation{
|
||||
// Added automatically from relation links
|
||||
{
|
||||
Key: bundle.RelationKeyName.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: false,
|
||||
},
|
||||
{
|
||||
Key: bundle.RelationKeyDescription.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
err := dv.ReplaceViewRelation(testViewId, bundle.RelationKeyDescription.String(), &model.BlockContentDataviewRelation{
|
||||
Key: bundle.RelationKeyAssignee.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
want := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
},
|
||||
[]*model.BlockContentDataviewRelation{
|
||||
// Added automatically from relation links
|
||||
{
|
||||
Key: bundle.RelationKeyName.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: false,
|
||||
},
|
||||
{
|
||||
Key: bundle.RelationKeyAssignee.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
IsVisible: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert.Equal(t, want, dv)
|
||||
})
|
||||
t.Run("add relation that exist in relation links, but not in View", func(t *testing.T) {
|
||||
dv := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
},
|
||||
[]*model.BlockContentDataviewRelation{},
|
||||
)
|
||||
|
||||
err := dv.ReplaceViewRelation(testViewId, bundle.RelationKeyName.String(), &model.BlockContentDataviewRelation{
|
||||
Key: bundle.RelationKeyName.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
want := makeDataviewForViewRelationsTest(
|
||||
[]*model.RelationLink{
|
||||
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
|
||||
},
|
||||
[]*model.BlockContentDataviewRelation{
|
||||
{
|
||||
Key: bundle.RelationKeyName.String(),
|
||||
Width: DefaultViewRelationWidth,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert.Equal(t, want, dv)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
|
@ -63,7 +62,6 @@ type service struct {
|
|||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
accountService accountService
|
||||
accountKeysService accountservice.Service
|
||||
fileStore filestore.FileStore
|
||||
spaceCoreService spacecore.SpaceCoreService
|
||||
storageService storage.ClientStorage
|
||||
fileService files.Service
|
||||
|
@ -80,7 +78,6 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
s.sbtProvider = a.MustComponent(typeprovider.CName).(typeprovider.SmartBlockTypeProvider)
|
||||
s.accountService = app.MustComponent[accountService](a)
|
||||
s.accountKeysService = a.MustComponent(accountservice.CName).(accountservice.Service)
|
||||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.spaceCoreService = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
s.storageService = a.MustComponent(spacestorage.CName).(storage.ClientStorage)
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ func (s *service) newTreeSource(ctx context.Context, space Space, id string, bui
|
|||
return nil, fmt.Errorf("build tree: %w", err)
|
||||
}
|
||||
|
||||
sbt, key, err := typeprovider.GetTypeAndKeyFromRoot(ot.Header())
|
||||
sbt, _, err := typeprovider.GetTypeAndKeyFromRoot(ot.Header())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -151,11 +151,9 @@ func (s *service) newTreeSource(ctx context.Context, space Space, id string, bui
|
|||
return &source{
|
||||
ObjectTree: ot,
|
||||
id: id,
|
||||
headerKey: key,
|
||||
space: space,
|
||||
spaceID: space.Id(),
|
||||
spaceService: s.spaceCoreService,
|
||||
openedAt: time.Now(),
|
||||
smartblockType: sbt,
|
||||
accountService: s.accountService,
|
||||
accountKeysService: s.accountKeysService,
|
||||
|
@ -181,14 +179,11 @@ type source struct {
|
|||
space Space
|
||||
spaceID string
|
||||
smartblockType smartblock.SmartBlockType
|
||||
headerKey string // used for header(id) derivation together with smartblockType
|
||||
lastSnapshotId string
|
||||
changesSinceSnapshot int
|
||||
receiver ChangeReceiver
|
||||
unsubscribe func()
|
||||
metaOnly bool
|
||||
closed chan struct{}
|
||||
openedAt time.Time
|
||||
|
||||
fileService files.Service
|
||||
accountService accountService
|
||||
|
@ -211,7 +206,8 @@ func (s *source) Update(ot objecttree.ObjectTree) {
|
|||
prevSnapshot := s.lastSnapshotId
|
||||
// todo: check this one
|
||||
err := s.receiver.StateAppend(func(d state.Doc) (st *state.State, changes []*pb.ChangeContent, err error) {
|
||||
st, changes, sinceSnapshot, err := BuildState(s.spaceID, d.(*state.State), ot)
|
||||
// State will be applied later in smartblock.StateAppend
|
||||
st, changes, sinceSnapshot, err := BuildState(s.spaceID, d.(*state.State), ot, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -277,7 +273,7 @@ func (s *source) readDoc(receiver ChangeReceiver) (doc state.Doc, err error) {
|
|||
}
|
||||
|
||||
func (s *source) buildState() (doc state.Doc, err error) {
|
||||
st, _, changesAppliedSinceSnapshot, err := BuildState(s.spaceID, nil, s.ObjectTree)
|
||||
st, _, changesAppliedSinceSnapshot, err := BuildState(s.spaceID, nil, s.ObjectTree, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -295,7 +291,7 @@ func (s *source) buildState() (doc state.Doc, err error) {
|
|||
// temporary, though the applying change to this Dataview block will persist this migration, breaking backward
|
||||
// compatibility. But in many cases we expect that users update object not so often as they just view them.
|
||||
// TODO: we can skip migration for non-personal spaces
|
||||
migration := NewSubObjectsAndProfileLinksMigration(s.smartblockType, s.space, s.accountService.MyParticipantId(s.spaceID), s.accountService.PersonalSpaceID(), s.objectStore)
|
||||
migration := NewSubObjectsAndProfileLinksMigration(s.smartblockType, s.space, s.accountService.MyParticipantId(s.spaceID), s.objectStore)
|
||||
migration.Migrate(st)
|
||||
|
||||
if s.Type() == smartblock.SmartBlockTypePage || s.Type() == smartblock.SmartBlockTypeProfilePage {
|
||||
|
@ -533,7 +529,7 @@ func (s *source) Close() (err error) {
|
|||
return s.ObjectTree.Close()
|
||||
}
|
||||
|
||||
func BuildState(spaceId string, initState *state.State, ot objecttree.ReadableObjectTree) (st *state.State, appliedContent []*pb.ChangeContent, changesAppliedSinceSnapshot int, err error) {
|
||||
func BuildState(spaceId string, initState *state.State, ot objecttree.ReadableObjectTree, applyState bool) (st *state.State, appliedContent []*pb.ChangeContent, changesAppliedSinceSnapshot int, err error) {
|
||||
var (
|
||||
startId string
|
||||
lastChange *objecttree.Change
|
||||
|
@ -598,9 +594,11 @@ func BuildState(spaceId string, initState *state.State, ot objecttree.ReadableOb
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _, err = state.ApplyStateFastOne(st)
|
||||
if err != nil {
|
||||
return
|
||||
if applyState {
|
||||
_, _, err = state.ApplyStateFastOne(st)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if lastChange != nil && !st.IsTheHeaderChange() {
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
type subObjectsAndProfileLinksMigration struct {
|
||||
profileID string
|
||||
identityObjectID string
|
||||
personalSpaceId string
|
||||
sbType smartblock.SmartBlockType
|
||||
space Space
|
||||
objectStore objectstore.ObjectStore
|
||||
|
@ -35,13 +34,11 @@ func NewSubObjectsAndProfileLinksMigration(
|
|||
sbType smartblock.SmartBlockType,
|
||||
space Space,
|
||||
identityObjectID string,
|
||||
personalSpaceId string,
|
||||
objectStore objectstore.ObjectStore,
|
||||
) *subObjectsAndProfileLinksMigration {
|
||||
return &subObjectsAndProfileLinksMigration{
|
||||
space: space,
|
||||
identityObjectID: identityObjectID,
|
||||
personalSpaceId: personalSpaceId,
|
||||
sbType: sbType,
|
||||
objectStore: objectStore,
|
||||
}
|
||||
|
|
|
@ -25,17 +25,15 @@ import (
|
|||
|
||||
var log = logging.Logger("html-converter").Desugar()
|
||||
|
||||
func NewHTMLConverter(spaceID string, fileService files.Service, s *state.State, fileObjectService fileobject.Service) *HTML {
|
||||
func NewHTMLConverter(fileService files.Service, s *state.State, fileObjectService fileobject.Service) *HTML {
|
||||
return &HTML{
|
||||
s: s,
|
||||
spaceID: spaceID,
|
||||
fileService: fileService,
|
||||
fileObjectService: fileObjectService,
|
||||
}
|
||||
}
|
||||
|
||||
type HTML struct {
|
||||
spaceID string
|
||||
s *state.State
|
||||
buf *bytes.Buffer
|
||||
fileService files.Service
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestHTML_Convert(t *testing.T) {
|
|||
s := state.NewDoc("root", map[string]simple.Block{
|
||||
"root": simple.New(&model.Block{}),
|
||||
}).(*state.State)
|
||||
assert.Empty(t, NewHTMLConverter("space1", nil, s, nil).Convert())
|
||||
assert.Empty(t, NewHTMLConverter(nil, s, nil).Convert())
|
||||
})
|
||||
|
||||
t.Run("markup", func(t *testing.T) {
|
||||
|
@ -88,7 +88,7 @@ func TestHTML_Convert(t *testing.T) {
|
|||
}
|
||||
|
||||
func convertHtml(s *state.State) string {
|
||||
return NewHTMLConverter("space1", nil, s, nil).Convert()
|
||||
return NewHTMLConverter(nil, s, nil).Convert()
|
||||
}
|
||||
|
||||
func givenMarkup() *state.State {
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/go-chi/chi/v5"
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
|
@ -46,7 +45,6 @@ type Debug interface {
|
|||
}
|
||||
|
||||
type debug struct {
|
||||
block *block.Service
|
||||
store objectstore.ObjectStore
|
||||
spaceService space.Service
|
||||
resolver idresolver.Resolver
|
||||
|
@ -61,7 +59,6 @@ type Debuggable interface {
|
|||
|
||||
func (d *debug) Init(a *app.App) (err error) {
|
||||
d.store = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
d.block = a.MustComponent(block.CName).(*block.Service)
|
||||
d.spaceService = app.MustComponent[space.Service](a)
|
||||
d.resolver = app.MustComponent[idresolver.Resolver](a)
|
||||
d.statService, _ = a.Component(debugstat.CName).(debugstat.StatService)
|
||||
|
|
|
@ -72,7 +72,7 @@ func (t *treeImporter) State() (*state.State, error) {
|
|||
err error
|
||||
)
|
||||
|
||||
st, _, _, err = source.BuildState("", nil, t.objectTree)
|
||||
st, _, _, err = source.BuildState("", nil, t.objectTree, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -13,17 +13,13 @@ import (
|
|||
|
||||
type zipAclReadStorage struct {
|
||||
id string
|
||||
head string
|
||||
files map[string]*zip.File
|
||||
zr *zip.ReadCloser
|
||||
}
|
||||
|
||||
func NewZipAclReadStorage(id string, zr *zip.ReadCloser) (ls liststorage.ListStorage, err error) {
|
||||
aclStorage := &zipAclReadStorage{
|
||||
id: id,
|
||||
head: id,
|
||||
files: map[string]*zip.File{},
|
||||
zr: zr,
|
||||
}
|
||||
for _, f := range zr.Reader.File {
|
||||
if len(f.Name) > len(id) && strings.Contains(f.Name, id) {
|
||||
|
|
|
@ -10,16 +10,14 @@ import (
|
|||
)
|
||||
|
||||
type zipACLWriteStorage struct {
|
||||
id string
|
||||
head string
|
||||
zw *zip.Writer
|
||||
id string
|
||||
zw *zip.Writer
|
||||
}
|
||||
|
||||
func NewACLWriteStorage(root *consensusproto.RawRecordWithId, zw *zip.Writer) (ls liststorage.ListStorage, err error) {
|
||||
ls = &zipACLWriteStorage{
|
||||
id: root.Id,
|
||||
head: root.Id,
|
||||
zw: zw,
|
||||
id: root.Id,
|
||||
zw: zw,
|
||||
}
|
||||
err = ls.AddRawRecord(context.Background(), root)
|
||||
return
|
||||
|
|
|
@ -16,7 +16,6 @@ type zipTreeReadStorage struct {
|
|||
id string
|
||||
heads []string
|
||||
files map[string]*zip.File
|
||||
zr *zip.ReadCloser
|
||||
}
|
||||
|
||||
func NewZipTreeReadStorage(id string, zr *zip.ReadCloser) (st treestorage.TreeStorage, err error) {
|
||||
|
@ -24,7 +23,6 @@ func NewZipTreeReadStorage(id string, zr *zip.ReadCloser) (st treestorage.TreeSt
|
|||
id: id,
|
||||
heads: nil,
|
||||
files: map[string]*zip.File{},
|
||||
zr: zr,
|
||||
}
|
||||
for _, f := range zr.Reader.File {
|
||||
if len(f.Name) > len(id) && strings.Contains(f.Name, id) {
|
||||
|
|
|
@ -10,8 +10,6 @@ type FullID struct {
|
|||
SpaceID string
|
||||
}
|
||||
|
||||
type ObjectTypeKey string
|
||||
|
||||
const ParticipantPrefix = "_participant_"
|
||||
|
||||
func NewParticipantId(spaceId, identity string) string {
|
||||
|
|
|
@ -18,12 +18,6 @@ func (s *service) DebugRouter(r chi.Router) {
|
|||
r.Get("/tree/{rootID}", debug.PlaintextHandler(s.printTree))
|
||||
}
|
||||
|
||||
type fileDebugInfo struct {
|
||||
Hash string
|
||||
SyncStatus int
|
||||
IsIndexed bool
|
||||
}
|
||||
|
||||
func (s *service) printTree(w io.Writer, req *http.Request) error {
|
||||
rawID := chi.URLParam(req, "rootID")
|
||||
id, err := cid.Parse(rawID)
|
||||
|
|
|
@ -34,15 +34,6 @@ type file struct {
|
|||
node *service
|
||||
}
|
||||
|
||||
func (s *service) newFile(spaceId string, fileId domain.FileId, info *storage.FileInfo) File {
|
||||
return &file{
|
||||
spaceID: spaceId,
|
||||
fileId: fileId,
|
||||
info: info,
|
||||
node: s,
|
||||
}
|
||||
}
|
||||
|
||||
type FileMeta struct {
|
||||
Media string
|
||||
Name string
|
||||
|
|
|
@ -229,16 +229,18 @@ func (ind *indexer) injectMetadataToState(ctx context.Context, st *state.State,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ind *indexer) markFileAsNotFound(st *state.State) {
|
||||
st.SetDetailAndBundledRelation(bundle.RelationKeyFileIndexingStatus, pbtypes.Int64(int64(model.FileIndexingStatus_NotFound)))
|
||||
}
|
||||
|
||||
func (ind *indexer) buildDetails(ctx context.Context, id domain.FullFileId) (details *types.Struct, typeKey domain.TypeKey, err error) {
|
||||
file, err := ind.fileService.FileByHash(ctx, id)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if mill.IsImage(file.Info().Media) {
|
||||
|
||||
if file.Info().Mill == mill.BlobId {
|
||||
details, typeKey, err = file.Details(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
} else {
|
||||
image, err := ind.fileService.ImageByHash(ctx, id)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
@ -247,13 +249,15 @@ func (ind *indexer) buildDetails(ctx context.Context, id domain.FullFileId) (det
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
typeKey = bundle.TypeKeyImage
|
||||
} else {
|
||||
details, typeKey, err = file.Details(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite typeKey for images in case that image is uploaded as file.
|
||||
// That can be possible because some images can't be handled properly and wee fall back to
|
||||
// handling them as files
|
||||
if mill.IsImage(file.Info().Media) {
|
||||
typeKey = bundle.TypeKeyImage
|
||||
}
|
||||
|
||||
details.Fields[bundle.RelationKeyFileIndexingStatus.String()] = pbtypes.Int64(int64(model.FileIndexingStatus_Indexed))
|
||||
return details, typeKey, nil
|
||||
}
|
||||
|
|
|
@ -2,37 +2,147 @@ package fileobject
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/files/mock_files"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/mill"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/storage"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
type indexerFixture struct {
|
||||
*indexer
|
||||
fileService *mock_files.MockService
|
||||
objectStoreFixture *objectstore.StoreFixture
|
||||
}
|
||||
|
||||
func newIndexerFixture(t *testing.T) *indexerFixture {
|
||||
objectStore := objectstore.NewStoreFixture(t)
|
||||
fileService := mock_files.NewMockService(t)
|
||||
|
||||
svc := &service{
|
||||
objectStore: objectStore,
|
||||
fileService: fileService,
|
||||
}
|
||||
ind := svc.newIndexer()
|
||||
|
||||
return &indexerFixture{
|
||||
objectStoreFixture: objectStore,
|
||||
fileService: fileService,
|
||||
indexer: ind,
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexer_buildDetails(t *testing.T) {
|
||||
t.Run("with file", func(t *testing.T) {
|
||||
for _, typeKey := range []domain.TypeKey{
|
||||
bundle.TypeKeyFile,
|
||||
bundle.TypeKeyAudio,
|
||||
bundle.TypeKeyVideo,
|
||||
} {
|
||||
t.Run(fmt.Sprintf("with type %s", typeKey), func(t *testing.T) {
|
||||
fx := newIndexerFixture(t)
|
||||
id := domain.FullFileId{
|
||||
SpaceId: "space1",
|
||||
FileId: testFileId,
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
file := mock_files.NewMockFile(t)
|
||||
file.EXPECT().Info().Return(&storage.FileInfo{
|
||||
Mill: mill.BlobId,
|
||||
Media: "text",
|
||||
})
|
||||
file.EXPECT().Details(ctx).Return(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyName.String(): pbtypes.String("name"),
|
||||
},
|
||||
}, typeKey, nil)
|
||||
fx.fileService.EXPECT().FileByHash(ctx, id).Return(file, nil)
|
||||
|
||||
details, gotTypeKey, err := fx.buildDetails(ctx, id)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, typeKey, gotTypeKey)
|
||||
assert.Equal(t, "name", pbtypes.GetString(details, bundle.RelationKeyName.String()))
|
||||
assert.Equal(t, pbtypes.Int64(int64(model.FileIndexingStatus_Indexed)), details.Fields[bundle.RelationKeyFileIndexingStatus.String()])
|
||||
})
|
||||
}
|
||||
})
|
||||
t.Run("with image", func(t *testing.T) {
|
||||
fx := newIndexerFixture(t)
|
||||
id := domain.FullFileId{
|
||||
SpaceId: "space1",
|
||||
FileId: testFileId,
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
file := mock_files.NewMockFile(t)
|
||||
file.EXPECT().Info().Return(&storage.FileInfo{
|
||||
Mill: mill.ImageResizeId,
|
||||
Media: "image/jpeg",
|
||||
})
|
||||
|
||||
image := mock_files.NewMockImage(t)
|
||||
image.EXPECT().Details(ctx).Return(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyName.String(): pbtypes.String("name"),
|
||||
},
|
||||
}, nil)
|
||||
fx.fileService.EXPECT().FileByHash(ctx, id).Return(file, nil)
|
||||
fx.fileService.EXPECT().ImageByHash(ctx, id).Return(image, nil)
|
||||
|
||||
details, gotTypeKey, err := fx.buildDetails(ctx, id)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyImage, gotTypeKey)
|
||||
assert.Equal(t, "name", pbtypes.GetString(details, bundle.RelationKeyName.String()))
|
||||
assert.Equal(t, pbtypes.Int64(int64(model.FileIndexingStatus_Indexed)), details.Fields[bundle.RelationKeyFileIndexingStatus.String()])
|
||||
})
|
||||
t.Run("with image fell back to file", func(t *testing.T) {
|
||||
for _, typeKey := range []domain.TypeKey{
|
||||
bundle.TypeKeyFile,
|
||||
bundle.TypeKeyAudio,
|
||||
bundle.TypeKeyVideo,
|
||||
bundle.TypeKeyImage,
|
||||
} {
|
||||
t.Run(fmt.Sprintf("with type %s", typeKey), func(t *testing.T) {
|
||||
fx := newIndexerFixture(t)
|
||||
id := domain.FullFileId{
|
||||
SpaceId: "space1",
|
||||
FileId: testFileId,
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
file := mock_files.NewMockFile(t)
|
||||
file.EXPECT().Info().Return(&storage.FileInfo{
|
||||
Mill: mill.BlobId,
|
||||
Media: "image/jpeg",
|
||||
})
|
||||
file.EXPECT().Details(ctx).Return(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyName.String(): pbtypes.String("name"),
|
||||
},
|
||||
}, typeKey, nil)
|
||||
fx.fileService.EXPECT().FileByHash(ctx, id).Return(file, nil)
|
||||
|
||||
details, gotTypeKey, err := fx.buildDetails(ctx, id)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyImage, gotTypeKey)
|
||||
assert.Equal(t, "name", pbtypes.GetString(details, bundle.RelationKeyName.String()))
|
||||
assert.Equal(t, pbtypes.Int64(int64(model.FileIndexingStatus_Indexed)), details.Fields[bundle.RelationKeyFileIndexingStatus.String()])
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestIndexer_addFromObjectStore(t *testing.T) {
|
||||
t.Run("no records in store", func(t *testing.T) {
|
||||
fx := newIndexerFixture(t)
|
||||
|
|
|
@ -135,8 +135,7 @@ func (s *service) migrationQueueHandler(ctx context.Context, it *migrationItem)
|
|||
return persistentqueue.ActionDone, fmt.Errorf("get space: %w", err)
|
||||
}
|
||||
|
||||
// Wait object to load
|
||||
ctx = peer.CtxWithPeerId(ctx, "*")
|
||||
ctx = peer.CtxWithPeerId(ctx, peer.CtxResponsiblePeers)
|
||||
_, err = space.GetObject(ctx, it.FileObjectId)
|
||||
// Already migrated or deleted file object
|
||||
if err == nil || errors.Is(err, spacestorage.ErrTreeStorageAlreadyDeleted) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/gogo/protobuf/types"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"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"
|
||||
|
@ -34,6 +35,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/clientspace"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/peermanager"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/persistentqueue"
|
||||
)
|
||||
|
@ -103,6 +105,12 @@ func (s *service) Name() string {
|
|||
return CName
|
||||
}
|
||||
|
||||
type configProvider interface {
|
||||
IsLocalOnlyMode() bool
|
||||
}
|
||||
|
||||
var _ configProvider = (*config.Config)(nil)
|
||||
|
||||
func (s *service) Init(a *app.App) error {
|
||||
s.spaceService = app.MustComponent[space.Service](a)
|
||||
s.objectCreator = app.MustComponent[objectCreatorService](a)
|
||||
|
@ -112,6 +120,7 @@ func (s *service) Init(a *app.App) error {
|
|||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.spaceIdResolver = app.MustComponent[idresolver.Resolver](a)
|
||||
s.fileStorage = app.MustComponent[filestorage.FileStorage](a)
|
||||
cfg := app.MustComponent[configProvider](a)
|
||||
|
||||
s.indexer = s.newIndexer()
|
||||
|
||||
|
@ -120,7 +129,17 @@ func (s *service) Init(a *app.App) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("get badger: %w", err)
|
||||
}
|
||||
s.migrationQueue = persistentqueue.New(persistentqueue.NewBadgerStorage(db, []byte("queue/file_migration/"), makeMigrationItem), log.Desugar(), s.migrationQueueHandler)
|
||||
|
||||
migrationQueueCtx := context.Background()
|
||||
if cfg.IsLocalOnlyMode() {
|
||||
migrationQueueCtx = context.WithValue(migrationQueueCtx, peermanager.ContextPeerFindDeadlineKey, time.Now().Add(1*time.Minute))
|
||||
}
|
||||
s.migrationQueue = persistentqueue.New(
|
||||
persistentqueue.NewBadgerStorage(db, []byte("queue/file_migration/"), makeMigrationItem),
|
||||
log.Desugar(),
|
||||
s.migrationQueueHandler,
|
||||
persistentqueue.WithContext(migrationQueueCtx),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,20 @@ type fixture struct {
|
|||
*service
|
||||
}
|
||||
|
||||
type dummyConfig struct{}
|
||||
|
||||
func (c *dummyConfig) IsLocalOnlyMode() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *dummyConfig) Init(_ *app.App) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *dummyConfig) Name() string {
|
||||
return "dummyConfig"
|
||||
}
|
||||
|
||||
const testResolveRetryDelay = 5 * time.Millisecond
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
|
@ -70,6 +84,7 @@ func newFixture(t *testing.T) *fixture {
|
|||
|
||||
ctx := context.Background()
|
||||
a := new(app.App)
|
||||
a.Register(&dummyConfig{})
|
||||
a.Register(dataStoreProvider)
|
||||
a.Register(fileStore)
|
||||
a.Register(objectStore)
|
||||
|
|
|
@ -31,7 +31,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/crypto/symmetric/gcm"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/ipfs/helpers"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
m "github.com/anyproto/anytype-heart/pkg/lib/mill"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/mill/schema"
|
||||
|
@ -66,7 +65,6 @@ type service struct {
|
|||
fileSync filesync.FileSync
|
||||
dagService ipld.DAGService
|
||||
fileStorage filestorage.FileStorage
|
||||
objectStore objectstore.ObjectStore
|
||||
|
||||
lock sync.Mutex
|
||||
addOperationLocks map[string]*sync.Mutex
|
||||
|
@ -85,7 +83,6 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
|
||||
s.dagService = s.commonFile.DAGService()
|
||||
s.fileStorage = app.MustComponent[filestorage.FileStorage](a)
|
||||
s.objectStore = app.MustComponent[objectstore.ObjectStore](a)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -210,21 +207,6 @@ func (s *service) newExistingFileResult(lock *sync.Mutex, fileId domain.FileId)
|
|||
|
||||
}
|
||||
|
||||
func (s *service) getFileIdAndEncryptionKeysFromInfo(fileInfo *storage.FileInfo) (domain.FileId, *domain.FileEncryptionKeys, error) {
|
||||
if len(fileInfo.Targets) == 0 {
|
||||
return "", nil, fmt.Errorf("file exists but has no root")
|
||||
}
|
||||
fileId := domain.FileId(fileInfo.Targets[0])
|
||||
keys, err := s.fileStore.GetFileKeys(fileId)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("can't get encryption keys for existing file: %w", err)
|
||||
}
|
||||
return fileId, &domain.FileEncryptionKeys{
|
||||
FileId: fileId,
|
||||
EncryptionKeys: keys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// addFileRootNode has structure:
|
||||
/*
|
||||
- dir (outer)
|
||||
|
@ -337,18 +319,6 @@ func (s *service) fileInfoFromPath(ctx context.Context, spaceId string, fileId d
|
|||
return &file, nil
|
||||
}
|
||||
|
||||
func (s *service) fileContent(ctx context.Context, spaceId string, childId domain.FileContentId) (io.ReadSeeker, *storage.FileInfo, error) {
|
||||
var err error
|
||||
var file *storage.FileInfo
|
||||
var reader io.ReadSeeker
|
||||
file, err = s.fileStore.GetFileVariant(childId)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reader, err = s.getContentReader(ctx, spaceId, file)
|
||||
return reader, file, err
|
||||
}
|
||||
|
||||
func (s *service) getContentReader(ctx context.Context, spaceID string, file *storage.FileInfo) (symmetric.ReadSeekCloser, error) {
|
||||
fileCid, err := cid.Parse(file.Hash)
|
||||
if err != nil {
|
||||
|
@ -420,7 +390,7 @@ func (s *service) addFileNode(ctx context.Context, spaceID string, mill m.Mill,
|
|||
|
||||
res, err := mill.Mill(conf.Reader, conf.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("%w: %w", m.ErrProcessing, err)
|
||||
}
|
||||
|
||||
// count the result size after the applied mill
|
||||
|
@ -431,7 +401,12 @@ func (s *service) addFileNode(ctx context.Context, spaceID string, mill m.Mill,
|
|||
}
|
||||
|
||||
if variant, err := s.fileStore.GetFileVariantByChecksum(mill.ID(), variantChecksum); err == nil {
|
||||
return newExistingFileResult(variant)
|
||||
if variant.Source == conf.checksum {
|
||||
// we may have same variant checksum for different files
|
||||
// e.g. empty image exif with the same resolution
|
||||
// reuse the whole file only in case the checksum of the original file is the same
|
||||
return newExistingFileResult(variant)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = conf.Reader.Seek(0, io.SeekStart)
|
||||
|
@ -439,8 +414,7 @@ func (s *service) addFileNode(ctx context.Context, spaceID string, mill m.Mill,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// because mill result reader doesn't support seek we need to do the mill again
|
||||
res, err = mill.Mill(conf.Reader, conf.Name)
|
||||
_, err = res.File.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -495,6 +469,10 @@ func (s *service) addFileNode(ctx context.Context, spaceID string, mill m.Mill,
|
|||
fileInfo.MetaHash = metaNode.Cid().String()
|
||||
|
||||
pairNode, err := s.addFilePairNode(ctx, spaceID, fileInfo)
|
||||
err = res.File.Close()
|
||||
if err != nil {
|
||||
log.Warnf("failed to close file: %s", err)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("add file pair node: %w", err)
|
||||
}
|
||||
|
|
BIN
core/files/fileuploader/testdata/corrupted.jpg
vendored
Normal file
BIN
core/files/fileuploader/testdata/corrupted.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 KiB |
|
@ -103,7 +103,6 @@ type Uploader interface {
|
|||
SetGroupId(groupId string) Uploader
|
||||
SetCustomEncryptionKeys(keys map[string]string) Uploader
|
||||
AddOptions(options ...files.AddOption) Uploader
|
||||
AutoType(enable bool) Uploader
|
||||
AsyncUpdates(smartBlockId string) Uploader
|
||||
|
||||
Upload(ctx context.Context) (result UploadResult)
|
||||
|
@ -142,20 +141,20 @@ func (ur UploadResult) ToBlock() file.Block {
|
|||
}
|
||||
|
||||
type uploader struct {
|
||||
spaceId string
|
||||
fileObjectService fileobject.Service
|
||||
picker cache.ObjectGetter
|
||||
block file.Block
|
||||
getReader func(ctx context.Context) (*fileReader, error)
|
||||
name string
|
||||
lastModifiedDate int64
|
||||
typeDetect bool
|
||||
forceType bool
|
||||
smartBlockID string
|
||||
fileType model.BlockContentFileType
|
||||
fileStyle model.BlockContentFileStyle
|
||||
opts []files.AddOption
|
||||
groupID string
|
||||
spaceId string
|
||||
fileObjectService fileobject.Service
|
||||
picker cache.ObjectGetter
|
||||
block file.Block
|
||||
getReader func(ctx context.Context) (*fileReader, error)
|
||||
name string
|
||||
lastModifiedDate int64
|
||||
forceType bool
|
||||
forceUploadingAsFile bool
|
||||
smartBlockID string
|
||||
fileType model.BlockContentFileType
|
||||
fileStyle model.BlockContentFileStyle
|
||||
opts []files.AddOption
|
||||
groupID string
|
||||
|
||||
tempDirProvider core.TempDirProvider
|
||||
fileService files.Service
|
||||
|
@ -214,6 +213,11 @@ func (u *uploader) SetType(tp model.BlockContentFileType) Uploader {
|
|||
return u
|
||||
}
|
||||
|
||||
func (u *uploader) ForceUploadingAsFile() Uploader {
|
||||
u.forceUploadingAsFile = true
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *uploader) SetStyle(tp model.BlockContentFileStyle) Uploader {
|
||||
u.fileStyle = tp
|
||||
return u
|
||||
|
@ -356,11 +360,6 @@ func (u *uploader) setLastModifiedDate(path string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *uploader) AutoType(enable bool) Uploader {
|
||||
u.typeDetect = enable
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *uploader) AsyncUpdates(smartBlockId string) Uploader {
|
||||
u.smartBlockID = smartBlockId
|
||||
return u
|
||||
|
@ -440,10 +439,13 @@ func (u *uploader) Upload(ctx context.Context) (result UploadResult) {
|
|||
}
|
||||
|
||||
var addResult *files.AddResult
|
||||
if u.fileType == model.BlockContentFile_Image {
|
||||
if !u.forceUploadingAsFile && u.fileType == model.BlockContentFile_Image {
|
||||
addResult, err = u.fileService.ImageAdd(ctx, u.spaceId, opts...)
|
||||
if errors.Is(err, image.ErrFormat) || errors.Is(err, mill.ErrFormatSupportNotEnabled) {
|
||||
return u.SetType(model.BlockContentFile_File).Upload(ctx)
|
||||
if errors.Is(err, image.ErrFormat) ||
|
||||
errors.Is(err, mill.ErrFormatSupportNotEnabled) ||
|
||||
errors.Is(err, mill.ErrProcessing) {
|
||||
err = nil
|
||||
return u.ForceUploadingAsFile().Upload(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return UploadResult{Err: fmt.Errorf("add image to storage: %w", err)}
|
||||
|
|
|
@ -34,7 +34,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/tests/testutil"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/testMock"
|
||||
)
|
||||
|
||||
func TestUploader_Upload(t *testing.T) {
|
||||
|
@ -62,13 +61,27 @@ func TestUploader_Upload(t *testing.T) {
|
|||
assert.Equal(t, b.Model().GetFile().Name, "unnamed.jpg")
|
||||
assert.Equal(t, res.MIME, "image/jpeg")
|
||||
})
|
||||
t.Run("corrupted image: fall back to file", func(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
|
||||
fileObjectId := fx.expectCreateObject()
|
||||
|
||||
b := newBlock(model.BlockContentFile_Image)
|
||||
res := fx.Uploader.SetBlock(b).SetFile("./testdata/corrupted.jpg").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
assert.Equal(t, res.FileObjectId, fileObjectId)
|
||||
assert.Equal(t, res.Name, "corrupted.jpg")
|
||||
assert.Equal(t, b.Model().GetFile().Name, "corrupted.jpg")
|
||||
assert.Equal(t, res.MIME, "image/jpeg")
|
||||
})
|
||||
t.Run("image type detect", func(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
|
||||
fx.expectCreateObject()
|
||||
|
||||
res := fx.Uploader.AutoType(true).SetFile("./testdata/unnamed.jpg").Upload(ctx)
|
||||
res := fx.Uploader.SetFile("./testdata/unnamed.jpg").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
})
|
||||
t.Run("image to file failover", func(t *testing.T) {
|
||||
|
@ -98,7 +111,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
|
||||
fileObjectId := fx.expectCreateObject()
|
||||
|
||||
res := fx.Uploader.AutoType(true).SetUrl(serv.URL + "/unnamed.jpg").Upload(ctx)
|
||||
res := fx.Uploader.SetUrl(serv.URL + "/unnamed.jpg").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
assert.Equal(t, res.FileObjectId, fileObjectId)
|
||||
assert.Equal(t, res.Name, "unnamed.jpg")
|
||||
|
@ -120,7 +133,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
|
||||
fileObjectId := fx.expectCreateObject()
|
||||
|
||||
res := fx.Uploader.AutoType(true).SetUrl(serv.URL + "/unnamed.jpg").Upload(ctx)
|
||||
res := fx.Uploader.SetUrl(serv.URL + "/unnamed.jpg").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
assert.Equal(t, res.FileObjectId, fileObjectId)
|
||||
assert.Equal(t, res.Name, "filename")
|
||||
|
@ -141,7 +154,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
|
||||
fileObjectId := fx.expectCreateObject()
|
||||
|
||||
res := fx.Uploader.AutoType(true).SetUrl(serv.URL + "/unnamed.jpg?text=text").Upload(ctx)
|
||||
res := fx.Uploader.SetUrl(serv.URL + "/unnamed.jpg?text=text").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
assert.Equal(t, res.FileObjectId, fileObjectId)
|
||||
assert.Equal(t, res.Name, "unnamed.jpg")
|
||||
|
@ -236,19 +249,6 @@ type uplFixture struct {
|
|||
fileObjectService *mock_fileobject.MockService
|
||||
}
|
||||
|
||||
func (fx *uplFixture) newImage(fileId domain.FileId) *testMock.MockImage {
|
||||
im := testMock.NewMockImage(fx.ctrl)
|
||||
im.EXPECT().FileId().Return(fileId).AnyTimes()
|
||||
return im
|
||||
}
|
||||
|
||||
func (fx *uplFixture) newFile(fileId domain.FileId, meta *files.FileMeta) *testMock.MockFile {
|
||||
f := testMock.NewMockFile(fx.ctrl)
|
||||
f.EXPECT().FileId().Return(fileId).AnyTimes()
|
||||
f.EXPECT().Meta().Return(meta).AnyTimes()
|
||||
return f
|
||||
}
|
||||
|
||||
func (fx *uplFixture) tearDown() {
|
||||
fx.ctrl.Finish()
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ type image struct {
|
|||
func selectAndSortResizeVariants(variants []*storage.FileInfo) []*storage.FileInfo {
|
||||
onlyResizeVariants := variants[:0]
|
||||
for _, variant := range variants {
|
||||
if variant.Mill == mill.ImageResizeId {
|
||||
if variant.Mill == mill.ImageResizeId || variant.Mill == mill.BlobId {
|
||||
onlyResizeVariants = append(onlyResizeVariants, variant)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/mill"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/storage"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
@ -157,3 +159,86 @@ func testAddImageWithRichExifData(t *testing.T, fx *fixture) *AddResult {
|
|||
got.Commit()
|
||||
return got
|
||||
}
|
||||
|
||||
func TestSelectAndSortResizeVariants(t *testing.T) {
|
||||
t.Run("with resize variants", func(t *testing.T) {
|
||||
got := selectAndSortResizeVariants([]*storage.FileInfo{
|
||||
{
|
||||
Mill: mill.ImageResizeId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(200),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Mill: mill.ImageResizeId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(100),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Mill: mill.ImageExifId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(300),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Mill: mill.ImageResizeId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(300),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
want := []*storage.FileInfo{
|
||||
{
|
||||
Mill: mill.ImageResizeId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(100),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Mill: mill.ImageResizeId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(200),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Mill: mill.ImageResizeId,
|
||||
Meta: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
"width": pbtypes.Int64(300),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
})
|
||||
t.Run("with blob variant", func(t *testing.T) {
|
||||
got := selectAndSortResizeVariants([]*storage.FileInfo{
|
||||
{
|
||||
Mill: mill.BlobId,
|
||||
},
|
||||
})
|
||||
|
||||
want := []*storage.FileInfo{
|
||||
{
|
||||
Mill: mill.BlobId,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package files
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -102,6 +104,52 @@ func TestImageAddWithCustomEncryptionKeys(t *testing.T) {
|
|||
assertCustomEncryptionKeys(t, fx, got, customKeys)
|
||||
}
|
||||
|
||||
func TestImageAddReuse(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
|
||||
f, err := os.Open("../../pkg/lib/mill/testdata/image.jpeg")
|
||||
require.NoError(t, err)
|
||||
defer f.Close()
|
||||
|
||||
fileName := "myFile"
|
||||
lastModifiedDate := time.Now()
|
||||
opts := []AddOption{
|
||||
WithName(fileName),
|
||||
WithLastModifiedDate(lastModifiedDate.Unix()),
|
||||
WithReader(f),
|
||||
}
|
||||
got1, err := fx.ImageAdd(context.Background(), spaceId, opts...)
|
||||
require.NoError(t, err)
|
||||
got1.Commit()
|
||||
|
||||
f.Seek(0, 0)
|
||||
got2, err := fx.ImageAdd(context.Background(), spaceId, opts...)
|
||||
require.NoError(t, err)
|
||||
got2.Commit()
|
||||
require.True(t, got2.IsExisting)
|
||||
require.Equal(t, got1.FileId.String(), got2.FileId.String())
|
||||
require.Equal(t, got1.EncryptionKeys.EncryptionKeys, got2.EncryptionKeys.EncryptionKeys)
|
||||
|
||||
b, err := io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
b[10000] = 0x00
|
||||
// patch the original image so it will have the different source hash, but the same(empty) exif
|
||||
patchedReader := bytes.NewReader(b)
|
||||
opts = []AddOption{
|
||||
WithName(fileName),
|
||||
WithLastModifiedDate(lastModifiedDate.Unix()),
|
||||
WithReader(patchedReader),
|
||||
}
|
||||
// exif will be the same but images are different
|
||||
got3, err := fx.ImageAdd(context.Background(), spaceId, opts...)
|
||||
require.NoError(t, err)
|
||||
got3.Commit()
|
||||
fileId3 := got3.FileId.String()
|
||||
|
||||
require.NotEqual(t, got1.FileId.String(), fileId3)
|
||||
require.False(t, got3.IsExisting)
|
||||
}
|
||||
|
||||
func assertCustomEncryptionKeys(t *testing.T, fx *fixture, got *AddResult, customKeys map[string]string) {
|
||||
encKeys, err := fx.fileStore.GetFileKeys(got.FileId)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/event"
|
||||
"github.com/anyproto/anytype-heart/core/filestorage/rpcstore"
|
||||
"github.com/anyproto/anytype-heart/core/wallet"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/datastore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
)
|
||||
|
||||
|
@ -51,7 +50,6 @@ type fileStorage struct {
|
|||
cfg *config.Config
|
||||
flatfsPath string
|
||||
|
||||
provider datastore.Datastore
|
||||
rpcStore rpcstore.Service
|
||||
spaceStorage storage.ClientStorage
|
||||
eventSender event.Sender
|
||||
|
|
|
@ -69,8 +69,6 @@ type fileSync struct {
|
|||
rpcStore rpcstore.RpcStore
|
||||
loopCtx context.Context
|
||||
loopCancel context.CancelFunc
|
||||
uploadPingCh chan struct{}
|
||||
removePingCh chan struct{}
|
||||
dagService ipld.DAGService
|
||||
fileStore filestore.FileStore
|
||||
eventSender event.Sender
|
||||
|
@ -97,8 +95,6 @@ func (s *fileSync) Init(a *app.App) (err error) {
|
|||
s.dagService = app.MustComponent[fileservice.FileService](a).DAGService()
|
||||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.eventSender = app.MustComponent[event.Sender](a)
|
||||
s.removePingCh = make(chan struct{})
|
||||
s.uploadPingCh = make(chan struct{})
|
||||
db, err := s.dbProvider.LocalStorage()
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -23,12 +23,6 @@ func newFileSyncStore(db *badger.DB) (*fileSyncStore, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
func (s *fileSyncStore) updateTxn(f func(txn *badger.Txn) error) error {
|
||||
return badgerhelper.RetryOnConflict(func() error {
|
||||
return s.db.Update(f)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *fileSyncStore) setNodeUsage(usage NodeUsage) error {
|
||||
data, err := json.Marshal(usage)
|
||||
if err != nil {
|
||||
|
|
|
@ -9,10 +9,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pb"
|
||||
)
|
||||
|
||||
type limitSetter interface {
|
||||
SetLimit(limit int)
|
||||
}
|
||||
|
||||
func TestSpaceUsageUpdate(t *testing.T) {
|
||||
const limit = 1024 * 1024 * 1024
|
||||
fx := newFixture(t, limit)
|
||||
|
|
|
@ -125,7 +125,7 @@ func (m *clientManager) onTaskFinished(t *task, c *client, taskErr error) {
|
|||
}
|
||||
}
|
||||
log.Debug("finishing task task", zap.String("cid", t.cid.String()))
|
||||
t.ready <- result{cid: t.cid, err: taskErr}
|
||||
t.ready <- result{err: taskErr}
|
||||
t.release()
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue