@atproto/bsky 0.0.155 → 0.0.157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/api/app/bsky/{unspecced/getPostThreadHiddenV2.d.ts → notification/getPreferences.d.ts} +1 -1
- package/dist/api/app/bsky/notification/getPreferences.d.ts.map +1 -0
- package/dist/api/app/bsky/notification/getPreferences.js +39 -0
- package/dist/api/app/bsky/notification/getPreferences.js.map +1 -0
- package/dist/api/app/bsky/notification/putPreferencesV2.d.ts +4 -0
- package/dist/api/app/bsky/notification/putPreferencesV2.d.ts.map +1 -0
- package/dist/api/app/bsky/notification/putPreferencesV2.js +47 -0
- package/dist/api/app/bsky/notification/putPreferencesV2.js.map +1 -0
- package/dist/api/app/bsky/notification/util.d.ts +9 -0
- package/dist/api/app/bsky/notification/util.d.ts.map +1 -0
- package/dist/api/app/bsky/notification/util.js +84 -0
- package/dist/api/app/bsky/notification/util.js.map +1 -0
- package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.d.ts +4 -0
- package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -0
- package/dist/api/app/bsky/unspecced/{getPostThreadHiddenV2.js → getPostThreadOtherV2.js} +5 -5
- package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -0
- package/dist/api/app/bsky/unspecced/getPostThreadV2.js +2 -2
- package/dist/api/app/bsky/unspecced/getPostThreadV2.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +6 -2
- package/dist/api/index.js.map +1 -1
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +3 -0
- package/dist/context.js.map +1 -1
- package/dist/data-plane/bsync/index.d.ts.map +1 -1
- package/dist/data-plane/bsync/index.js +84 -0
- package/dist/data-plane/bsync/index.js.map +1 -1
- package/dist/data-plane/server/db/database-schema.d.ts +2 -1
- package/dist/data-plane/server/db/database-schema.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.js +24 -0
- package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.js.map +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/index.js +2 -1
- package/dist/data-plane/server/db/migrations/index.js.map +1 -1
- package/dist/data-plane/server/db/tables/private-data.d.ts +13 -0
- package/dist/data-plane/server/db/tables/private-data.d.ts.map +1 -0
- package/dist/data-plane/server/db/tables/private-data.js +5 -0
- package/dist/data-plane/server/db/tables/private-data.js.map +1 -0
- package/dist/data-plane/server/routes/index.d.ts.map +1 -1
- package/dist/data-plane/server/routes/index.js +2 -0
- package/dist/data-plane/server/routes/index.js.map +1 -1
- package/dist/data-plane/server/routes/private-data.d.ts +9 -0
- package/dist/data-plane/server/routes/private-data.d.ts.map +1 -0
- package/dist/data-plane/server/routes/private-data.js +63 -0
- package/dist/data-plane/server/routes/private-data.js.map +1 -0
- package/dist/data-plane/server/util.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lexicon/index.d.ts +8 -4
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +14 -6
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +518 -100
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +277 -52
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/notification/defs.d.ts +40 -0
- package/dist/lexicon/types/app/bsky/notification/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/notification/defs.js +36 -0
- package/dist/lexicon/types/app/bsky/notification/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/notification/getPreferences.d.ts +35 -0
- package/dist/lexicon/types/app/bsky/notification/getPreferences.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/notification/getPreferences.js +7 -0
- package/dist/lexicon/types/app/bsky/notification/getPreferences.js.map +1 -0
- package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.d.ts +52 -0
- package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.js +7 -0
- package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.js.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/{getPostThreadHiddenV2.d.ts → getPostThreadOtherV2.d.ts} +7 -7
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.js +16 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -1
- package/dist/proto/bsky_connect.d.ts +10 -1
- package/dist/proto/bsky_connect.d.ts.map +1 -1
- package/dist/proto/bsky_connect.js +9 -0
- package/dist/proto/bsky_connect.js.map +1 -1
- package/dist/proto/bsky_pb.d.ts +234 -0
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +693 -5
- package/dist/proto/bsky_pb.js.map +1 -1
- package/dist/proto/bsync_pb.d.ts +10 -10
- package/dist/proto/bsync_pb.d.ts.map +1 -1
- package/dist/proto/bsync_pb.js +15 -15
- package/dist/proto/bsync_pb.js.map +1 -1
- package/dist/stash.d.ts +26 -0
- package/dist/stash.d.ts.map +1 -0
- package/dist/stash.js +56 -0
- package/dist/stash.js.map +1 -0
- package/dist/views/index.d.ts +8 -8
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +32 -32
- package/dist/views/index.js.map +1 -1
- package/dist/views/threads-v2.d.ts +11 -11
- package/dist/views/threads-v2.d.ts.map +1 -1
- package/dist/views/threads-v2.js.map +1 -1
- package/package.json +4 -4
- package/proto/bsky.proto +61 -0
- package/src/api/app/bsky/notification/getPreferences.ts +50 -0
- package/src/api/app/bsky/notification/putPreferencesV2.ts +62 -0
- package/src/api/app/bsky/notification/util.ts +123 -0
- package/src/api/app/bsky/unspecced/{getPostThreadHiddenV2.ts → getPostThreadOtherV2.ts} +5 -5
- package/src/api/app/bsky/unspecced/getPostThreadV2.ts +2 -2
- package/src/api/index.ts +6 -2
- package/src/context.ts +6 -0
- package/src/data-plane/bsync/index.ts +109 -1
- package/src/data-plane/server/db/database-schema.ts +3 -1
- package/src/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.ts +22 -0
- package/src/data-plane/server/db/migrations/index.ts +1 -0
- package/src/data-plane/server/db/tables/private-data.ts +13 -0
- package/src/data-plane/server/routes/index.ts +2 -0
- package/src/data-plane/server/routes/private-data.ts +90 -0
- package/src/index.ts +4 -0
- package/src/lexicon/index.ts +38 -14
- package/src/lexicon/lexicons.ts +281 -54
- package/src/lexicon/types/app/bsky/notification/defs.ts +76 -0
- package/src/lexicon/types/app/bsky/notification/getPreferences.ts +52 -0
- package/src/lexicon/types/app/bsky/notification/putPreferencesV2.ts +69 -0
- package/src/lexicon/types/app/bsky/unspecced/{getPostThreadHiddenV2.ts → getPostThreadOtherV2.ts} +10 -10
- package/src/lexicon/types/app/bsky/unspecced/getPostThreadV2.ts +2 -2
- package/src/proto/bsky_connect.ts +11 -0
- package/src/proto/bsky_pb.ts +669 -0
- package/src/proto/bsync_pb.ts +15 -15
- package/src/stash.ts +75 -0
- package/src/views/index.ts +46 -46
- package/src/views/threads-v2.ts +23 -23
- package/tests/stash.test.ts +156 -0
- package/tests/views/__snapshots__/thread-v2.test.ts.snap +7 -7
- package/tests/views/notifications.test.ts +221 -0
- package/tests/views/thread-v2.test.ts +93 -93
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.tsbuildinfo +1 -1
- package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.d.ts.map +0 -1
- package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.js.map +0 -1
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.d.ts.map +0 -1
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.js +0 -16
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.js.map +0 -1
package/src/proto/bsync_pb.ts
CHANGED
|
@@ -736,14 +736,14 @@ export class Operation extends Message<Operation> {
|
|
|
736
736
|
actorDid = ''
|
|
737
737
|
|
|
738
738
|
/**
|
|
739
|
-
* @generated from field: string
|
|
739
|
+
* @generated from field: string namespace = 3;
|
|
740
740
|
*/
|
|
741
|
-
|
|
741
|
+
namespace = ''
|
|
742
742
|
|
|
743
743
|
/**
|
|
744
|
-
* @generated from field: string
|
|
744
|
+
* @generated from field: string key = 4;
|
|
745
745
|
*/
|
|
746
|
-
|
|
746
|
+
key = ''
|
|
747
747
|
|
|
748
748
|
/**
|
|
749
749
|
* @generated from field: bsync.Method method = 5;
|
|
@@ -765,8 +765,8 @@ export class Operation extends Message<Operation> {
|
|
|
765
765
|
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
766
766
|
{ no: 1, name: 'id', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
767
767
|
{ no: 2, name: 'actor_did', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
768
|
-
{ no: 3, name: '
|
|
769
|
-
{ no: 4, name: '
|
|
768
|
+
{ no: 3, name: 'namespace', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
769
|
+
{ no: 4, name: 'key', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
770
770
|
{ no: 5, name: 'method', kind: 'enum', T: proto3.getEnumType(Method) },
|
|
771
771
|
{ no: 6, name: 'payload', kind: 'scalar', T: 12 /* ScalarType.BYTES */ },
|
|
772
772
|
])
|
|
@@ -805,19 +805,19 @@ export class Operation extends Message<Operation> {
|
|
|
805
805
|
*/
|
|
806
806
|
export class PutOperationRequest extends Message<PutOperationRequest> {
|
|
807
807
|
/**
|
|
808
|
-
* @generated from field: string
|
|
808
|
+
* @generated from field: string actor_did = 1;
|
|
809
809
|
*/
|
|
810
|
-
|
|
810
|
+
actorDid = ''
|
|
811
811
|
|
|
812
812
|
/**
|
|
813
|
-
* @generated from field: string
|
|
813
|
+
* @generated from field: string namespace = 2;
|
|
814
814
|
*/
|
|
815
|
-
|
|
815
|
+
namespace = ''
|
|
816
816
|
|
|
817
817
|
/**
|
|
818
|
-
* @generated from field: string
|
|
818
|
+
* @generated from field: string key = 3;
|
|
819
819
|
*/
|
|
820
|
-
|
|
820
|
+
key = ''
|
|
821
821
|
|
|
822
822
|
/**
|
|
823
823
|
* @generated from field: bsync.Method method = 4;
|
|
@@ -837,9 +837,9 @@ export class PutOperationRequest extends Message<PutOperationRequest> {
|
|
|
837
837
|
static readonly runtime: typeof proto3 = proto3
|
|
838
838
|
static readonly typeName = 'bsync.PutOperationRequest'
|
|
839
839
|
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
840
|
-
{ no: 1, name: '
|
|
841
|
-
{ no: 2, name: '
|
|
842
|
-
{ no: 3, name: '
|
|
840
|
+
{ no: 1, name: 'actor_did', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
841
|
+
{ no: 2, name: 'namespace', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
842
|
+
{ no: 3, name: 'key', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
843
843
|
{ no: 4, name: 'method', kind: 'enum', T: proto3.getEnumType(Method) },
|
|
844
844
|
{ no: 5, name: 'payload', kind: 'scalar', T: 12 /* ScalarType.BYTES */ },
|
|
845
845
|
])
|
package/src/stash.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { LexValue, stringifyLex } from '@atproto/lexicon'
|
|
2
|
+
import { BsyncClient } from './bsync'
|
|
3
|
+
import { lexicons } from './lexicon/lexicons'
|
|
4
|
+
import { Method } from './proto/bsync_pb'
|
|
5
|
+
|
|
6
|
+
export const createStashClient = (bsyncClient: BsyncClient): StashClient => {
|
|
7
|
+
return new StashClient(bsyncClient)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// An abstraction over the BsyncClient, that uses the bsync `PutOperation` RPC
|
|
11
|
+
// to store private data, which can be indexed by the dataplane and queried by the appview.
|
|
12
|
+
export class StashClient {
|
|
13
|
+
constructor(private readonly bsyncClient: BsyncClient) {}
|
|
14
|
+
|
|
15
|
+
create(input: CreateInput) {
|
|
16
|
+
this.validateLexicon(input.namespace, input.payload)
|
|
17
|
+
return this.putOperation(Method.CREATE, input)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
update(input: UpdateInput) {
|
|
21
|
+
this.validateLexicon(input.namespace, input.payload)
|
|
22
|
+
return this.putOperation(Method.UPDATE, input)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
delete(input: DeleteInput) {
|
|
26
|
+
return this.putOperation(Method.DELETE, { ...input, payload: undefined })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private validateLexicon(namespace: string, payload: LexValue) {
|
|
30
|
+
const result = lexicons.validate(namespace, payload)
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
throw result.error
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private async putOperation(method: Method, input: PutOperationInput) {
|
|
37
|
+
const { actorDid, namespace, key, payload } = input
|
|
38
|
+
await this.bsyncClient.putOperation({
|
|
39
|
+
actorDid,
|
|
40
|
+
namespace,
|
|
41
|
+
key,
|
|
42
|
+
method,
|
|
43
|
+
payload: payload
|
|
44
|
+
? Buffer.from(
|
|
45
|
+
stringifyLex({
|
|
46
|
+
$type: namespace,
|
|
47
|
+
...payload,
|
|
48
|
+
}),
|
|
49
|
+
)
|
|
50
|
+
: undefined,
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
type PutOperationInput = {
|
|
56
|
+
actorDid: string
|
|
57
|
+
namespace: string
|
|
58
|
+
key: string
|
|
59
|
+
payload: LexValue | undefined
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type CreateInput = {
|
|
63
|
+
actorDid: string
|
|
64
|
+
namespace: string
|
|
65
|
+
key: string
|
|
66
|
+
payload: LexValue
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
type UpdateInput = CreateInput
|
|
70
|
+
|
|
71
|
+
type DeleteInput = {
|
|
72
|
+
actorDid: string
|
|
73
|
+
namespace: string
|
|
74
|
+
key: string
|
|
75
|
+
}
|
package/src/views/index.ts
CHANGED
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
isRecord as isLabelerRecord,
|
|
60
60
|
} from '../lexicon/types/app/bsky/labeler/service'
|
|
61
61
|
import { RecordDeleted as NotificationRecordDeleted } from '../lexicon/types/app/bsky/notification/defs'
|
|
62
|
-
import {
|
|
62
|
+
import { ThreadItem as ThreadOtherItem } from '../lexicon/types/app/bsky/unspecced/getPostThreadOtherV2'
|
|
63
63
|
import {
|
|
64
64
|
QueryParams as GetPostThreadV2QueryParams,
|
|
65
65
|
ThreadItem,
|
|
@@ -75,13 +75,13 @@ import {
|
|
|
75
75
|
uriToDid as creatorFromUri,
|
|
76
76
|
} from '../util/uris'
|
|
77
77
|
import {
|
|
78
|
-
ThreadHiddenAnchorPostNode,
|
|
79
|
-
ThreadHiddenItemValuePost,
|
|
80
|
-
ThreadHiddenPostNode,
|
|
81
78
|
ThreadItemValueBlocked,
|
|
82
79
|
ThreadItemValueNoUnauthenticated,
|
|
83
80
|
ThreadItemValueNotFound,
|
|
84
81
|
ThreadItemValuePost,
|
|
82
|
+
ThreadOtherAnchorPostNode,
|
|
83
|
+
ThreadOtherItemValuePost,
|
|
84
|
+
ThreadOtherPostNode,
|
|
85
85
|
ThreadTree,
|
|
86
86
|
ThreadTreeVisible,
|
|
87
87
|
sortTrimFlattenThreadTree,
|
|
@@ -1161,7 +1161,7 @@ export class Views {
|
|
|
1161
1161
|
prioritizeFollowedUsers: boolean
|
|
1162
1162
|
sort: GetPostThreadV2QueryParams['sort']
|
|
1163
1163
|
},
|
|
1164
|
-
): {
|
|
1164
|
+
): { hasOtherReplies: boolean; thread: ThreadItem[] } {
|
|
1165
1165
|
const { anchor: anchorUri, uris } = skeleton
|
|
1166
1166
|
|
|
1167
1167
|
// Not found.
|
|
@@ -1169,7 +1169,7 @@ export class Views {
|
|
|
1169
1169
|
const post = state.posts?.get(anchorUri)
|
|
1170
1170
|
if (!post || !postView) {
|
|
1171
1171
|
return {
|
|
1172
|
-
|
|
1172
|
+
hasOtherReplies: false,
|
|
1173
1173
|
thread: [
|
|
1174
1174
|
this.threadV2ItemNotFound({
|
|
1175
1175
|
uri: anchorUri,
|
|
@@ -1182,7 +1182,7 @@ export class Views {
|
|
|
1182
1182
|
// Blocked (only 1p for anchor).
|
|
1183
1183
|
if (this.viewerBlockExists(postView.author.did, state)) {
|
|
1184
1184
|
return {
|
|
1185
|
-
|
|
1185
|
+
hasOtherReplies: false,
|
|
1186
1186
|
thread: [
|
|
1187
1187
|
this.threadV2ItemBlocked({
|
|
1188
1188
|
uri: anchorUri,
|
|
@@ -1229,7 +1229,7 @@ export class Views {
|
|
|
1229
1229
|
|
|
1230
1230
|
const anchorDepth = 0 // The depth of the anchor post is always 0.
|
|
1231
1231
|
let anchorTree: ThreadTree
|
|
1232
|
-
let
|
|
1232
|
+
let hasOtherReplies = false
|
|
1233
1233
|
|
|
1234
1234
|
if (this.noUnauthenticatedPost(state, postView)) {
|
|
1235
1235
|
anchorTree = {
|
|
@@ -1241,7 +1241,7 @@ export class Views {
|
|
|
1241
1241
|
parent,
|
|
1242
1242
|
}
|
|
1243
1243
|
} else {
|
|
1244
|
-
const { replies,
|
|
1244
|
+
const { replies, hasOtherReplies: hasOtherRepliesShadow } =
|
|
1245
1245
|
!anchorViolatesThreadGate
|
|
1246
1246
|
? this.threadV2Replies(
|
|
1247
1247
|
{
|
|
@@ -1257,8 +1257,8 @@ export class Views {
|
|
|
1257
1257
|
},
|
|
1258
1258
|
state,
|
|
1259
1259
|
)
|
|
1260
|
-
: { replies: undefined,
|
|
1261
|
-
|
|
1260
|
+
: { replies: undefined, hasOtherReplies: false }
|
|
1261
|
+
hasOtherReplies = hasOtherRepliesShadow
|
|
1262
1262
|
|
|
1263
1263
|
anchorTree = {
|
|
1264
1264
|
type: 'post',
|
|
@@ -1287,7 +1287,7 @@ export class Views {
|
|
|
1287
1287
|
})
|
|
1288
1288
|
|
|
1289
1289
|
return {
|
|
1290
|
-
|
|
1290
|
+
hasOtherReplies,
|
|
1291
1291
|
thread,
|
|
1292
1292
|
}
|
|
1293
1293
|
}
|
|
@@ -1432,14 +1432,14 @@ export class Views {
|
|
|
1432
1432
|
prioritizeFollowedUsers: boolean
|
|
1433
1433
|
},
|
|
1434
1434
|
state: HydrationState,
|
|
1435
|
-
): { replies: ThreadTreeVisible[] | undefined;
|
|
1435
|
+
): { replies: ThreadTreeVisible[] | undefined; hasOtherReplies: boolean } {
|
|
1436
1436
|
// Reached the `below` limit.
|
|
1437
1437
|
if (depth > below) {
|
|
1438
|
-
return { replies: undefined,
|
|
1438
|
+
return { replies: undefined, hasOtherReplies: false }
|
|
1439
1439
|
}
|
|
1440
1440
|
|
|
1441
1441
|
const childrenUris = childrenByParentUri[parentUri] ?? []
|
|
1442
|
-
let
|
|
1442
|
+
let hasOtherReplies = false
|
|
1443
1443
|
const replies = mapDefined(childrenUris, (uri) => {
|
|
1444
1444
|
const replyInclusion = this.checkThreadV2ReplyInclusion({
|
|
1445
1445
|
uri,
|
|
@@ -1452,14 +1452,14 @@ export class Views {
|
|
|
1452
1452
|
const { authorDid, post, postView } = replyInclusion
|
|
1453
1453
|
|
|
1454
1454
|
// Hidden.
|
|
1455
|
-
const {
|
|
1455
|
+
const { isOther } = this.isOtherThreadPost(
|
|
1456
1456
|
{ post, postView, prioritizeFollowedUsers, rootUri, uri },
|
|
1457
1457
|
state,
|
|
1458
1458
|
)
|
|
1459
|
-
if (
|
|
1459
|
+
if (isOther) {
|
|
1460
1460
|
// Only care about anchor replies
|
|
1461
1461
|
if (depth === 1) {
|
|
1462
|
-
|
|
1462
|
+
hasOtherReplies = true
|
|
1463
1463
|
}
|
|
1464
1464
|
return undefined
|
|
1465
1465
|
}
|
|
@@ -1504,7 +1504,7 @@ export class Views {
|
|
|
1504
1504
|
|
|
1505
1505
|
return {
|
|
1506
1506
|
replies,
|
|
1507
|
-
|
|
1507
|
+
hasOtherReplies,
|
|
1508
1508
|
}
|
|
1509
1509
|
}
|
|
1510
1510
|
|
|
@@ -1537,8 +1537,8 @@ export class Views {
|
|
|
1537
1537
|
moreParents: moreParents ?? false,
|
|
1538
1538
|
moreReplies,
|
|
1539
1539
|
opThread: isOPThread,
|
|
1540
|
-
hiddenByThreadgate: false, // Hidden posts are handled by
|
|
1541
|
-
mutedByViewer: false, // Hidden posts are handled by
|
|
1540
|
+
hiddenByThreadgate: false, // Hidden posts are handled by threadOtherV2
|
|
1541
|
+
mutedByViewer: false, // Hidden posts are handled by threadOtherV2
|
|
1542
1542
|
},
|
|
1543
1543
|
}
|
|
1544
1544
|
}
|
|
@@ -1599,7 +1599,7 @@ export class Views {
|
|
|
1599
1599
|
}
|
|
1600
1600
|
}
|
|
1601
1601
|
|
|
1602
|
-
|
|
1602
|
+
threadOtherV2(
|
|
1603
1603
|
skeleton: { anchor: string; uris: string[] },
|
|
1604
1604
|
state: HydrationState,
|
|
1605
1605
|
{
|
|
@@ -1611,7 +1611,7 @@ export class Views {
|
|
|
1611
1611
|
branchingFactor: number
|
|
1612
1612
|
prioritizeFollowedUsers: boolean
|
|
1613
1613
|
},
|
|
1614
|
-
):
|
|
1614
|
+
): ThreadOtherItem[] {
|
|
1615
1615
|
const { anchor: anchorUri, uris } = skeleton
|
|
1616
1616
|
|
|
1617
1617
|
// Not found.
|
|
@@ -1634,10 +1634,10 @@ export class Views {
|
|
|
1634
1634
|
const rootUri = getRootUri(anchorUri, post)
|
|
1635
1635
|
const opDid = uriToDid(rootUri)
|
|
1636
1636
|
|
|
1637
|
-
const anchorTree:
|
|
1637
|
+
const anchorTree: ThreadOtherAnchorPostNode = {
|
|
1638
1638
|
type: 'hiddenAnchor',
|
|
1639
|
-
item: this.
|
|
1640
|
-
replies: this.
|
|
1639
|
+
item: this.threadOtherV2ItemPostAnchor({ depth: 0, uri: anchorUri }),
|
|
1640
|
+
replies: this.threadOtherV2Replies(
|
|
1641
1641
|
{
|
|
1642
1642
|
parentUri: anchorUri,
|
|
1643
1643
|
rootUri,
|
|
@@ -1660,7 +1660,7 @@ export class Views {
|
|
|
1660
1660
|
})
|
|
1661
1661
|
}
|
|
1662
1662
|
|
|
1663
|
-
private
|
|
1663
|
+
private threadOtherV2Replies(
|
|
1664
1664
|
{
|
|
1665
1665
|
parentUri,
|
|
1666
1666
|
rootUri,
|
|
@@ -1677,7 +1677,7 @@ export class Views {
|
|
|
1677
1677
|
prioritizeFollowedUsers: boolean
|
|
1678
1678
|
},
|
|
1679
1679
|
state: HydrationState,
|
|
1680
|
-
):
|
|
1680
|
+
): ThreadOtherPostNode[] | undefined {
|
|
1681
1681
|
// Reached the `below` limit.
|
|
1682
1682
|
if (depth > below) {
|
|
1683
1683
|
return undefined
|
|
@@ -1695,13 +1695,13 @@ export class Views {
|
|
|
1695
1695
|
}
|
|
1696
1696
|
const { post, postView } = replyInclusion
|
|
1697
1697
|
|
|
1698
|
-
//
|
|
1699
|
-
const {
|
|
1700
|
-
this.
|
|
1698
|
+
// Other posts to pull out
|
|
1699
|
+
const { isOther, hiddenByThreadgate, mutedByViewer } =
|
|
1700
|
+
this.isOtherThreadPost(
|
|
1701
1701
|
{ post, postView, rootUri, prioritizeFollowedUsers, uri },
|
|
1702
1702
|
state,
|
|
1703
1703
|
)
|
|
1704
|
-
if (
|
|
1704
|
+
if (isOther) {
|
|
1705
1705
|
// Only show hidden anchor replies, not all hidden.
|
|
1706
1706
|
if (depth > 1) {
|
|
1707
1707
|
return undefined
|
|
@@ -1712,7 +1712,7 @@ export class Views {
|
|
|
1712
1712
|
}
|
|
1713
1713
|
|
|
1714
1714
|
// Recurse down.
|
|
1715
|
-
const replies = this.
|
|
1715
|
+
const replies = this.threadOtherV2Replies(
|
|
1716
1716
|
{
|
|
1717
1717
|
parentUri: uri,
|
|
1718
1718
|
rootUri,
|
|
@@ -1724,7 +1724,7 @@ export class Views {
|
|
|
1724
1724
|
state,
|
|
1725
1725
|
)
|
|
1726
1726
|
|
|
1727
|
-
const item = this.
|
|
1727
|
+
const item = this.threadOtherV2ItemPost({
|
|
1728
1728
|
depth,
|
|
1729
1729
|
hiddenByThreadgate,
|
|
1730
1730
|
mutedByViewer,
|
|
@@ -1732,7 +1732,7 @@ export class Views {
|
|
|
1732
1732
|
uri,
|
|
1733
1733
|
})
|
|
1734
1734
|
|
|
1735
|
-
const tree:
|
|
1735
|
+
const tree: ThreadOtherPostNode = {
|
|
1736
1736
|
type: 'hiddenPost',
|
|
1737
1737
|
item: item,
|
|
1738
1738
|
tags: post.tags,
|
|
@@ -1743,13 +1743,13 @@ export class Views {
|
|
|
1743
1743
|
})
|
|
1744
1744
|
}
|
|
1745
1745
|
|
|
1746
|
-
private
|
|
1746
|
+
private threadOtherV2ItemPostAnchor({
|
|
1747
1747
|
depth,
|
|
1748
1748
|
uri,
|
|
1749
1749
|
}: {
|
|
1750
1750
|
depth: number
|
|
1751
1751
|
uri: string
|
|
1752
|
-
}):
|
|
1752
|
+
}): ThreadOtherAnchorPostNode['item'] {
|
|
1753
1753
|
return {
|
|
1754
1754
|
uri,
|
|
1755
1755
|
depth,
|
|
@@ -1759,7 +1759,7 @@ export class Views {
|
|
|
1759
1759
|
}
|
|
1760
1760
|
}
|
|
1761
1761
|
|
|
1762
|
-
private
|
|
1762
|
+
private threadOtherV2ItemPost({
|
|
1763
1763
|
depth,
|
|
1764
1764
|
hiddenByThreadgate,
|
|
1765
1765
|
mutedByViewer,
|
|
@@ -1771,8 +1771,8 @@ export class Views {
|
|
|
1771
1771
|
mutedByViewer: boolean
|
|
1772
1772
|
postView: PostView
|
|
1773
1773
|
uri: string
|
|
1774
|
-
}):
|
|
1775
|
-
const base = this.
|
|
1774
|
+
}): ThreadOtherItemValuePost {
|
|
1775
|
+
const base = this.threadOtherV2ItemPostAnchor({ depth, uri })
|
|
1776
1776
|
return {
|
|
1777
1777
|
...base,
|
|
1778
1778
|
value: {
|
|
@@ -1780,9 +1780,9 @@ export class Views {
|
|
|
1780
1780
|
post: postView,
|
|
1781
1781
|
hiddenByThreadgate,
|
|
1782
1782
|
mutedByViewer,
|
|
1783
|
-
moreParents: false, //
|
|
1784
|
-
moreReplies: 0, //
|
|
1785
|
-
opThread: false, //
|
|
1783
|
+
moreParents: false, // "Other" replies don't have parents.
|
|
1784
|
+
moreReplies: 0, // "Other" replies don't have replies hydrated.
|
|
1785
|
+
opThread: false, // "Other" replies don't contain OP threads.
|
|
1786
1786
|
},
|
|
1787
1787
|
}
|
|
1788
1788
|
}
|
|
@@ -1834,7 +1834,7 @@ export class Views {
|
|
|
1834
1834
|
return { authorDid, post, postView }
|
|
1835
1835
|
}
|
|
1836
1836
|
|
|
1837
|
-
private
|
|
1837
|
+
private isOtherThreadPost(
|
|
1838
1838
|
{
|
|
1839
1839
|
post,
|
|
1840
1840
|
postView,
|
|
@@ -1850,7 +1850,7 @@ export class Views {
|
|
|
1850
1850
|
},
|
|
1851
1851
|
state: HydrationState,
|
|
1852
1852
|
): {
|
|
1853
|
-
|
|
1853
|
+
isOther: boolean
|
|
1854
1854
|
hiddenByTag: boolean
|
|
1855
1855
|
hiddenByThreadgate: boolean
|
|
1856
1856
|
mutedByViewer: boolean
|
|
@@ -1873,7 +1873,7 @@ export class Views {
|
|
|
1873
1873
|
const mutedByViewer = this.viewerMuteExists(authorDid, state)
|
|
1874
1874
|
|
|
1875
1875
|
return {
|
|
1876
|
-
|
|
1876
|
+
isOther: hiddenByTag || hiddenByThreadgate || mutedByViewer,
|
|
1877
1877
|
hiddenByTag,
|
|
1878
1878
|
hiddenByThreadgate,
|
|
1879
1879
|
mutedByViewer,
|
package/src/views/threads-v2.ts
CHANGED
|
@@ -7,18 +7,18 @@ import {
|
|
|
7
7
|
ThreadItemNotFound,
|
|
8
8
|
ThreadItemPost,
|
|
9
9
|
} from '../lexicon/types/app/bsky/unspecced/defs'
|
|
10
|
-
import {
|
|
10
|
+
import { ThreadItem as ThreadOtherItem } from '../lexicon/types/app/bsky/unspecced/getPostThreadOtherV2'
|
|
11
11
|
import {
|
|
12
12
|
QueryParams as GetPostThreadV2QueryParams,
|
|
13
13
|
ThreadItem,
|
|
14
14
|
} from '../lexicon/types/app/bsky/unspecced/getPostThreadV2'
|
|
15
15
|
import { $Typed } from '../lexicon/util'
|
|
16
16
|
|
|
17
|
-
type
|
|
17
|
+
type ThreadMaybeOtherPostNode = ThreadPostNode | ThreadOtherPostNode
|
|
18
18
|
type ThreadNodeWithReplies =
|
|
19
19
|
| ThreadPostNode
|
|
20
|
-
|
|
|
21
|
-
|
|
|
20
|
+
| ThreadOtherPostNode
|
|
21
|
+
| ThreadOtherAnchorPostNode
|
|
22
22
|
|
|
23
23
|
type ThreadItemValue<T extends ThreadItem['value']> = Omit<
|
|
24
24
|
ThreadItem,
|
|
@@ -63,37 +63,37 @@ type ThreadPostNode = {
|
|
|
63
63
|
replies: ThreadTree[] | undefined
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
type
|
|
67
|
-
|
|
66
|
+
type ThreadOtherItemValue<T extends ThreadOtherItem['value']> = Omit<
|
|
67
|
+
ThreadOtherItem,
|
|
68
68
|
'value'
|
|
69
69
|
> & {
|
|
70
70
|
value: T
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export type
|
|
73
|
+
export type ThreadOtherItemValuePost = ThreadOtherItemValue<
|
|
74
74
|
$Typed<ThreadItemPost>
|
|
75
75
|
>
|
|
76
76
|
|
|
77
77
|
// This is an intermediary type that doesn't map to the views.
|
|
78
78
|
// It is useful to differentiate between the anchor post and the replies for the hidden case,
|
|
79
79
|
// while also differentiating between hidden and visible cases.
|
|
80
|
-
export type
|
|
80
|
+
export type ThreadOtherAnchorPostNode = {
|
|
81
81
|
type: 'hiddenAnchor'
|
|
82
|
-
item: Omit<
|
|
83
|
-
replies:
|
|
82
|
+
item: Omit<ThreadOtherItem, 'value'> & { value: undefined }
|
|
83
|
+
replies: ThreadOtherPostNode[] | undefined
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
export type
|
|
86
|
+
export type ThreadOtherPostNode = {
|
|
87
87
|
type: 'hiddenPost'
|
|
88
|
-
item:
|
|
88
|
+
item: ThreadOtherItemValuePost
|
|
89
89
|
tags: Set<string>
|
|
90
|
-
replies:
|
|
90
|
+
replies: ThreadOtherPostNode[] | undefined
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
const isNodeWithReplies = (node: ThreadTree): node is ThreadNodeWithReplies =>
|
|
94
94
|
'replies' in node && node.replies !== undefined
|
|
95
95
|
|
|
96
|
-
const isPostNode = (node: ThreadTree): node is
|
|
96
|
+
const isPostNode = (node: ThreadTree): node is ThreadMaybeOtherPostNode =>
|
|
97
97
|
node.type === 'post' || node.type === 'hiddenPost'
|
|
98
98
|
|
|
99
99
|
export type ThreadTreeVisible =
|
|
@@ -102,9 +102,9 @@ export type ThreadTreeVisible =
|
|
|
102
102
|
| ThreadNotFoundNode
|
|
103
103
|
| ThreadPostNode
|
|
104
104
|
|
|
105
|
-
export type
|
|
105
|
+
export type ThreadTreeOther = ThreadOtherAnchorPostNode | ThreadOtherPostNode
|
|
106
106
|
|
|
107
|
-
export type ThreadTree = ThreadTreeVisible |
|
|
107
|
+
export type ThreadTree = ThreadTreeVisible | ThreadTreeOther
|
|
108
108
|
|
|
109
109
|
/** This function mutates the tree parameter. */
|
|
110
110
|
export function sortTrimFlattenThreadTree(
|
|
@@ -146,8 +146,8 @@ function sortTrimThreadTree(
|
|
|
146
146
|
if (!isPostNode(bn)) {
|
|
147
147
|
return -1
|
|
148
148
|
}
|
|
149
|
-
const aNode:
|
|
150
|
-
const bNode:
|
|
149
|
+
const aNode: ThreadMaybeOtherPostNode = an
|
|
150
|
+
const bNode: ThreadMaybeOtherPostNode = bn
|
|
151
151
|
|
|
152
152
|
// First applies bumping.
|
|
153
153
|
const bump = applyBumping(aNode, bNode, opts)
|
|
@@ -171,8 +171,8 @@ function sortTrimThreadTree(
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
function applyBumping(
|
|
174
|
-
aNode:
|
|
175
|
-
bNode:
|
|
174
|
+
aNode: ThreadMaybeOtherPostNode,
|
|
175
|
+
bNode: ThreadMaybeOtherPostNode,
|
|
176
176
|
opts: SortTrimFlattenOptions,
|
|
177
177
|
): number | null {
|
|
178
178
|
if (!isPostNode(aNode)) {
|
|
@@ -191,7 +191,7 @@ function applyBumping(
|
|
|
191
191
|
} = opts
|
|
192
192
|
|
|
193
193
|
type BumpDirection = 'up' | 'down'
|
|
194
|
-
type BumpPredicateFn = (i:
|
|
194
|
+
type BumpPredicateFn = (i: ThreadMaybeOtherPostNode) => boolean
|
|
195
195
|
|
|
196
196
|
const maybeBump = (
|
|
197
197
|
bump: BumpDirection,
|
|
@@ -276,8 +276,8 @@ function applyBumping(
|
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
function applySorting(
|
|
279
|
-
aNode:
|
|
280
|
-
bNode:
|
|
279
|
+
aNode: ThreadMaybeOtherPostNode,
|
|
280
|
+
bNode: ThreadMaybeOtherPostNode,
|
|
281
281
|
opts: SortTrimFlattenOptions,
|
|
282
282
|
): number {
|
|
283
283
|
const a = aNode.item.value
|