diff --git a/src/annotations/annotation-save-logic.ts b/src/annotations/annotation-save-logic.ts index 3165e1ff0d..352f787072 100644 --- a/src/annotations/annotation-save-logic.ts +++ b/src/annotations/annotation-save-logic.ts @@ -129,7 +129,6 @@ export async function createAnnotation({ shareData = await contentSharingBG.shareAnnotation({ annotationUrl, remoteAnnotationId, - excludeFromLists: !shareOpts?.shouldShare ?? true, shareToParentPageLists: shareOpts?.shouldShare ?? false, skipPrivacyLevelUpdate: !!shareOpts?.shouldShare ?? true, }) @@ -145,7 +144,6 @@ export async function createAnnotation({ shareData = await contentSharingBG.shareAnnotation({ annotationUrl, remoteAnnotationId, - excludeFromLists: false, shareToParentPageLists: false, skipPrivacyLevelUpdate: true, }) @@ -236,7 +234,6 @@ export async function updateAnnotation({ remoteAnnotationId, annotationUrl: annotationData.localId, shareToParentPageLists: true, - excludeFromLists: false, }), !shareOpts?.skipPrivacyLevelUpdate && contentSharingBG.setAnnotationPrivacyLevel({ diff --git a/src/content-sharing/background/index.test.ts b/src/content-sharing/background/index.test.ts index 402d4f24e8..0f98b16092 100644 --- a/src/content-sharing/background/index.test.ts +++ b/src/content-sharing/background/index.test.ts @@ -701,18 +701,18 @@ export const INTEGRATION_TESTS = backgroundIntegrationTestSuite( AnnotationPrivacyLevels.SHARED, }, }) - // await helper.unshareAnnotations(setup, { - // ids: [1], - // expectedSharingStates: { - // 1: { - // sharedListIds: [], - // privateListIds: [], - // privacyLevel: - // AnnotationPrivacyLevels.PRIVATE, - // hasLink: true, - // }, - // }, - // }) + await helper.unshareAnnotations(setup, { + ids: [1], + expectedSharingStates: { + 1: { + sharedListIds: [], + privateListIds: [], + privacyLevel: + AnnotationPrivacyLevels.PRIVATE, + hasLink: true, + }, + }, + }) await helper.assertAnnotationPrivacyLevels( setup, [ @@ -774,18 +774,18 @@ export const INTEGRATION_TESTS = backgroundIntegrationTestSuite( AnnotationPrivacyLevels.SHARED_PROTECTED, }, }) - // await helper.unshareAnnotations(setup, { - // ids: [1], - // expectedSharingStates: { - // 1: { - // sharedListIds: [1, 2], - // privateListIds: [], - // privacyLevel: - // AnnotationPrivacyLevels.SHARED_PROTECTED, - // hasLink: true, - // }, - // }, - // }) + await helper.unshareAnnotations(setup, { + ids: [1], + expectedSharingStates: { + 1: { + sharedListIds: [1, 2], + privateListIds: [], + privacyLevel: + AnnotationPrivacyLevels.SHARED_PROTECTED, + hasLink: true, + }, + }, + }) await helper.assertAnnotationPrivacyLevels( setup, [ diff --git a/src/content-sharing/background/index.tests.ts b/src/content-sharing/background/index.tests.ts index 28bf4404b2..7c6e08598a 100644 --- a/src/content-sharing/background/index.tests.ts +++ b/src/content-sharing/background/index.tests.ts @@ -474,6 +474,26 @@ export class SharingTestHelper { ) } + async unshareAnnotations( + setup: BackgroundIntegrationTestSetup, + options: { + ids: number[] + expectedSharingStates: AnnotationSharingStates + }, + ) { + const { + sharingStates, + } = await setup.backgroundModules.contentSharing.unshareAnnotations({ + annotationUrls: options.ids.map( + (id) => this.annotations[id].localId, + ), + }) + this._expectAnnotationSharingStates( + sharingStates, + options.expectedSharingStates, + ) + } + async unshareAnnotation( setup: BackgroundIntegrationTestSetup, options: { id: number; expectedSharingState: AnnotationSharingState }, diff --git a/src/content-sharing/background/index.ts b/src/content-sharing/background/index.ts index 3ebd0dffc6..09f71d46b1 100644 --- a/src/content-sharing/background/index.ts +++ b/src/content-sharing/background/index.ts @@ -3,10 +3,10 @@ import type StorageManager from '@worldbrain/storex' import type { StorageOperationEvent } from '@worldbrain/storex-middleware-change-watcher/lib/types' import type { ContentSharingBackend } from '@worldbrain/memex-common/lib/content-sharing/backend' import { + makeAnnotationPrivacyLevel, getAnnotationPrivacyState, createPageLinkListTitle, getListShareUrl, - makeAnnotationPrivacyLevel, } from '@worldbrain/memex-common/lib/content-sharing/utils' import type { Analytics } from 'src/analytics/types' import { AnnotationPrivacyLevels } from '@worldbrain/memex-common/lib/annotations/types' @@ -261,9 +261,11 @@ export default class ContentSharingBackground { waitForListShareSideEffects: this.waitForListShareSideEffects, deleteListAndAllAssociatedData: this.deleteListAndAllAssociatedData, shareAnnotation: this.shareAnnotation, + shareAnnotations: this.shareAnnotations, executePendingActions: this.executePendingActions.bind(this), shareAnnotationToSomeLists: this.shareAnnotationToSomeLists, unshareAnnotationFromList: this.unshareAnnotationFromList, + unshareAnnotations: this.unshareAnnotations, ensureRemotePageId: this.ensureRemotePageId, getRemoteAnnotationLink: this.getRemoteAnnotationLink, findAnnotationPrivacyLevels: this.findAnnotationPrivacyLevels.bind( @@ -541,12 +543,9 @@ export default class ContentSharingBackground { return this.annotationSharingService.shareAnnotation(options) } - async shareAnnotations(options: { - annotationUrls: string[] - shareToParentPageLists?: boolean - setBulkShareProtected?: boolean - skipAnalytics?: boolean - }): Promise<{ sharingStates: AnnotationSharingStates }> { + shareAnnotations: ContentSharingInterface['shareAnnotations'] = async ( + options, + ) => { const remoteIds = await this.storage.getRemoteAnnotationIds({ localIds: options.annotationUrls, }) @@ -776,6 +775,50 @@ export default class ContentSharingBackground { return { sharingState } } + unshareAnnotations: ContentSharingInterface['unshareAnnotations'] = async ( + options, + ) => { + const annotPrivacyLevels = await this.storage.getPrivacyLevelsByAnnotation( + { annotations: options.annotationUrls }, + ) + const nonProtectedAnnotations = options.annotationUrls.filter( + (annotationUrl) => + ![ + AnnotationPrivacyLevels.PROTECTED, + AnnotationPrivacyLevels.SHARED_PROTECTED, + ].includes(annotPrivacyLevels[annotationUrl]?.privacyLevel), + ) + + const allMetadata = await this.storage.getRemoteAnnotationMetadata({ + localIds: nonProtectedAnnotations, + }) + await this.storage.setAnnotationsExcludedFromLists({ + localIds: Object.values(allMetadata) + .filter((metadata) => !metadata.excludeFromLists) + .map(({ localId }) => localId), + excludeFromLists: true, + }) + + await this.storage.setAnnotationPrivacyLevelBulk({ + annotations: nonProtectedAnnotations, + privacyLevel: options.setBulkShareProtected + ? AnnotationPrivacyLevels.PROTECTED + : AnnotationPrivacyLevels.PRIVATE, + }) + + if (this.options.analyticsBG) { + try { + await trackUnSharedAnnotation(this.options.analyticsBG, { + type: 'bulk', + }) + } catch (error) { + console.error(`Error tracking space create event', ${error}`) + } + } + + return { sharingStates: await this.getAnnotationSharingStates(options) } + } + unshareAnnotation: __DeprecatedContentSharingInterface['unshareAnnotation'] = async ( options, ) => { diff --git a/src/content-sharing/background/types.ts b/src/content-sharing/background/types.ts index 0c6a746fa7..4311c096a5 100644 --- a/src/content-sharing/background/types.ts +++ b/src/content-sharing/background/types.ts @@ -41,6 +41,16 @@ export interface ContentSharingInterface deleteListAndAllAssociatedData(params: { localListId: number }): Promise + shareAnnotations(options: { + annotationUrls: string[] + shareToParentPageLists?: boolean + setBulkShareProtected?: boolean + skipAnalytics?: boolean + }): Promise<{ sharingStates: AnnotationSharingStates }> + unshareAnnotations(options: { + annotationUrls: string[] + setBulkShareProtected?: boolean + }): Promise<{ sharingStates: AnnotationSharingStates }> ensureRemotePageId(normalizedPageUrl: string): Promise getRemoteAnnotationLink(params: { annotationUrl: string diff --git a/src/overview/sharing/AllNotesShareMenu.tsx b/src/overview/sharing/AllNotesShareMenu.tsx index 2cce59a3a9..f25ae4a1eb 100644 --- a/src/overview/sharing/AllNotesShareMenu.tsx +++ b/src/overview/sharing/AllNotesShareMenu.tsx @@ -55,6 +55,49 @@ export default class AllNotesShareMenu extends React.Component { this.setState({ link: getPageShareUrl({ remotePageInfoId }) }) } + private shareAllAnnotations = async () => { + try { + const { + sharingStates, + } = await this.props.contentSharingBG.shareAnnotations({ + annotationUrls: this.annotationUrls, + shareToParentPageLists: true, + }) + this.props.postBulkShareHook?.(sharingStates) + } catch (err) {} + } + + private unshareAllAnnotations = async () => { + try { + const { + sharingStates, + } = await this.props.contentSharingBG.unshareAnnotations({ + annotationUrls: this.annotationUrls, + }) + this.props.postBulkShareHook?.(sharingStates) + } catch (err) {} + } + + private handleSetShared = async () => { + await executeReactStateUITask( + this, + 'shareState', + async () => { + await this.shareAllAnnotations() + }, + ) + } + + private handleSetPrivate = async () => { + await executeReactStateUITask( + this, + 'shareState', + async () => { + await this.unshareAllAnnotations() + }, + ) + } + render() { return null // { let sharingState = await contentSharingBG.shareAnnotation({ annotationUrl, - shareToParentPageLists: - currentSharingLevel?.privacyLevel === - AnnotationPrivacyLevels.SHARED, - excludeFromLists: - currentSharingLevel?.privacyLevel !== - AnnotationPrivacyLevels.SHARED, + shareToParentPageLists: currentSharingLevel?.privacyLevel === 200, skipPrivacyLevelUpdate: true, }) @@ -169,7 +163,6 @@ class ShareAnnotationMenu extends PureComponent { await contentSharingBG.shareAnnotation({ annotationUrl, shareToParentPageLists: false, - excludeFromLists: true, skipPrivacyLevelUpdate: true, })