diff --git a/external/@worldbrain/memex-common b/external/@worldbrain/memex-common index c00948203c..efd98d8d35 160000 --- a/external/@worldbrain/memex-common +++ b/external/@worldbrain/memex-common @@ -1 +1 @@ -Subproject commit c00948203c01779f887b1ab8a5e80c1925785b18 +Subproject commit efd98d8d355515a5e0b3eed9e4491a5a94ca20d2 diff --git a/src/annotations/components/AnnotationCreate.tsx b/src/annotations/components/AnnotationCreate.tsx index 69a48b27d1..8e7266307f 100644 --- a/src/annotations/components/AnnotationCreate.tsx +++ b/src/annotations/components/AnnotationCreate.tsx @@ -69,6 +69,7 @@ export interface AnnotationCreateGeneralProps { getRootElement: () => HTMLElement updateSpacesSearchSuggestions?: (query: string) => void spaceSearchSuggestions?: SpaceSearchSuggestion[] + openImageInPreview: (imageSource: string) => Promise } export interface Props @@ -522,6 +523,7 @@ export class AnnotationCreate extends React.Component this.props.addNewSpaceViaWikiLinksNewNote } defaultMinimized={this.props.defaultMinimized} + openImageInPreview={this.props.openImageInPreview} /> {this.props.comment.length > 0 && diff --git a/src/annotations/components/AnnotationEdit.tsx b/src/annotations/components/AnnotationEdit.tsx index a26372ca7b..a450a94acb 100644 --- a/src/annotations/components/AnnotationEdit.tsx +++ b/src/annotations/components/AnnotationEdit.tsx @@ -54,6 +54,7 @@ export interface AnnotationEditGeneralProps { slimEditorActions?: boolean isEditMode?: boolean searchTerms?: string[] + openImageInPreview: (imageSource: string) => Promise } export interface Props @@ -214,6 +215,7 @@ class AnnotationEdit extends React.Component { this.props.addNewSpaceViaWikiLinks } searchTerms={this.props.searchTerms} + openImageInPreview={this.props.openImageInPreview} /> ) diff --git a/src/annotations/components/AnnotationEditable.tsx b/src/annotations/components/AnnotationEditable.tsx index 9ca4c2a388..e1560fbe16 100644 --- a/src/annotations/components/AnnotationEditable.tsx +++ b/src/annotations/components/AnnotationEditable.tsx @@ -150,6 +150,7 @@ export interface AnnotationProps { shiftSelectItem?: () => void searchTerms?: string[] syncSettingsBG: RemoteSyncSettingsInterface + openImageInPreview: (imageSource: string) => Promise } export interface AnnotationEditableEventProps { @@ -553,6 +554,7 @@ export default class AnnotationEditable extends React.Component { ) } searchTerms={this.props.searchTerms} + openImageInPreview={this.props.openImageInPreview} /> @@ -854,6 +856,7 @@ export default class AnnotationEditable extends React.Component { ) } searchTerms={this.props.searchTerms} + openImageInPreview={this.props.openImageInPreview} /> ) diff --git a/src/dashboard-refactor/index.tsx b/src/dashboard-refactor/index.tsx index 73f62d4b7f..dd578968dd 100644 --- a/src/dashboard-refactor/index.tsx +++ b/src/dashboard-refactor/index.tsx @@ -70,6 +70,7 @@ import { TooltipBox } from '@worldbrain/memex-common/lib/common-ui/components/to import KeyboardShortcuts from '@worldbrain/memex-common/lib/common-ui/components/keyboard-shortcuts' import { UpdateNotifBanner } from 'src/common-ui/containers/UpdateNotifBanner' import { HighlightColor } from '@worldbrain/memex-common/lib/common-ui/components/highlightColorPicker/types' +import ImagePreviewModal from '@worldbrain/memex-common/lib/common-ui/image-preview-modal' export type Props = DashboardDependencies & { getRootElement: () => HTMLElement @@ -267,6 +268,8 @@ export class DashboardContainer extends StatefulUIElement< : undefined, imageSupport: this.props.imageSupportBG, getRootElement: this.props.getRootElement, + openImageInPreview: (imageSource: string) => + this.processEvent('openImageInPreview', imageSource), } } @@ -937,6 +940,9 @@ export class DashboardContainer extends StatefulUIElement< ) : [] } + openImageInPreview={(imageSource: string) => + this.processEvent('openImageInPreview', imageSource) + } spacePickerBGProps={{ authBG: this.props.authBG, spacesBG: this.props.listsBG, @@ -1447,6 +1453,8 @@ export class DashboardContainer extends StatefulUIElement< ...opts, }) }, + openImageInPreview: () => (imageSource: string) => + this.processEvent('openImageInPreview', imageSource), onGoToHighlightClick: (noteId) => () => this.processEvent('goToHighlightInNewTab', { noteId }), onListPickerBarBtnClick: (noteId) => () => @@ -2080,6 +2088,15 @@ export class DashboardContainer extends StatefulUIElement< /> {this.renderModals()} + {this.state.imageSourceForPreview?.length > 0 ? ( + + this.processEvent('openImageInPreview', null) + } + getRootElement={this.props.getRootElement} + /> + ) : null} { focusLockUntilMouseStart: false, selectableBlocks: [], focusedBlockId: -1, + imageSourceForPreview: null, } } @@ -848,6 +849,14 @@ export class DashboardLogic extends UILogic { }) } + openImageInPreview: EventHandler<'openImageInPreview'> = async ({ + event, + }) => { + this.emitMutation({ + imageSourceForPreview: { $set: event }, + }) + } + checkSharingAccess: EventHandler<'checkSharingAccess'> = async ({ previousState, }) => { diff --git a/src/dashboard-refactor/search-results/components/list-details.tsx b/src/dashboard-refactor/search-results/components/list-details.tsx index 4f33b4cc20..cf501e025d 100644 --- a/src/dashboard-refactor/search-results/components/list-details.tsx +++ b/src/dashboard-refactor/search-results/components/list-details.tsx @@ -33,6 +33,7 @@ export interface Props { clearInbox?: () => void imageSupport: ImageSupportInterface<'caller'> getRootElement: () => HTMLElement + openImageInPreview: (imageSource: string) => Promise } interface State { @@ -200,6 +201,7 @@ export default class ListDetails extends PureComponent { }) }} defaultMinimized + openImageInPreview={this.props.openImageInPreview} /> ) } diff --git a/src/dashboard-refactor/search-results/index.tsx b/src/dashboard-refactor/search-results/index.tsx index 91c44fcfea..1619a581b8 100644 --- a/src/dashboard-refactor/search-results/index.tsx +++ b/src/dashboard-refactor/search-results/index.tsx @@ -168,6 +168,7 @@ export type Props = RootState & spaceSearchSuggestions?: SpaceSearchSuggestion[] shiftSelectItems: (itemId: string, type: 'notes' | 'pages') => void focusLockUntilMouseStart: boolean + openImageInPreview: (imageSource: string) => Promise } export interface State { @@ -397,6 +398,7 @@ export default class SearchResultsContainer extends React.Component< ? new Date(noteData.displayTime) : undefined } + openImageInPreview={this.props.openImageInPreview} searchTerms={this.state.searchTerms} syncSettingsBG={this.props.syncSettingsBG} bulkSelectAnnotation={() => { @@ -540,6 +542,7 @@ export default class SearchResultsContainer extends React.Component< onBodyChange: (content) => interactionProps.onBodyChange(content), setEditing: interactionProps.onEditBtnClick, + openImageInPreview: interactionProps.openImageInPreview, }} annotationFooterDependencies={{ onCopyPasterDefaultExecute: diff --git a/src/dashboard-refactor/search-results/types.ts b/src/dashboard-refactor/search-results/types.ts index 88f0632a8f..aa565c82c8 100644 --- a/src/dashboard-refactor/search-results/types.ts +++ b/src/dashboard-refactor/search-results/types.ts @@ -83,6 +83,7 @@ export type NoteInteractionProps = Omit< onCommentChange: (content: string) => void onBodyChange: (content: string) => void onCopyPasterDefaultExecute: () => void + openImageInPreview: (imageSource: string) => Promise } // NOTE: Derived type - edit the original diff --git a/src/dashboard-refactor/types.ts b/src/dashboard-refactor/types.ts index c76d272a4a..8c22cdae06 100644 --- a/src/dashboard-refactor/types.ts +++ b/src/dashboard-refactor/types.ts @@ -80,6 +80,7 @@ export interface RootState { spaceSearchSuggestions: SpaceSearchSuggestion[] selectableBlocks: SelectableBlock[] focusedBlockId: number | null + imageSourceForPreview: string } export type Events = UIEvent< @@ -195,6 +196,7 @@ export type DashboardModalsEvents = UIEvent<{ setDeletingPageArgs: PageEventArgs & { instaDelete: boolean } setDeletingNoteArgs: NoteDataEventArgs checkSharingAccess: null + openImageInPreview: string setSpaceSidebarWidth: { width: string } setDisableMouseLeave: { disable: boolean } selectAllCurrentItems: null diff --git a/src/in-page-ui/tooltip/content_script/interactions.ts b/src/in-page-ui/tooltip/content_script/interactions.ts index 5a78fef482..ffa5836fdc 100644 --- a/src/in-page-ui/tooltip/content_script/interactions.ts +++ b/src/in-page-ui/tooltip/content_script/interactions.ts @@ -182,6 +182,7 @@ export const insertTooltip = async (params: TooltipInsertDependencies) => { addNewSpaceViaWikiLinks: async (spaceName: string) => { // Placeholder function, replace with actual implementation }, + openImageInPreview: async (src: string) => null, }, { annotationsBG: params.annotationsBG, diff --git a/src/sidebar/annotations-sidebar/components/AnnotationsSidebar.tsx b/src/sidebar/annotations-sidebar/components/AnnotationsSidebar.tsx index fee7232936..94e77ec92d 100644 --- a/src/sidebar/annotations-sidebar/components/AnnotationsSidebar.tsx +++ b/src/sidebar/annotations-sidebar/components/AnnotationsSidebar.tsx @@ -171,7 +171,7 @@ export interface AnnotationsSidebarProps extends SidebarContainerState { renderContextMenuForList: (listData: UnifiedList) => JSX.Element renderEditMenuForList: (listData: UnifiedList) => JSX.Element renderPageLinkMenuForList: () => JSX.Element - + openImageInPreview: (imageSource: string) => Promise setActiveTab: (tab: SidebarTab) => void setActiveAITab: (tab: SidebarAITab) => React.MouseEventHandler setActiveSuggestionsTab: (tab: SuggestionsTab) => React.MouseEventHandler @@ -753,6 +753,7 @@ export class AnnotationsSidebar extends React.Component< onCancel={() => { this.setState({ autoFocusCreateForm: false }) }} + openImageInPreview={this.props.openImageInPreview} ref={this.annotationCreateRef} getYoutubePlayer={this.props.getYoutubePlayer} autoFocus={this.state.autoFocusCreateForm} @@ -1050,6 +1051,7 @@ export class AnnotationsSidebar extends React.Component< isShared syncSettingsBG={this.props.syncSettingsBG} getRootElement={this.props.getRootElement} + openImageInPreview={this.props.openImageInPreview} isBulkShareProtected onSpacePickerToggle={() => { this.props.setSpacePickerAnnotationInstance( @@ -1191,6 +1193,9 @@ export class AnnotationsSidebar extends React.Component< createdWhen: annotation.createdWhen, reference: sharedAnnotationRef, }} + openImageInPreview={ + this.props.openImageInPreview + } getYoutubePlayer={ this.props.getYoutubePlayer } @@ -2006,6 +2011,7 @@ export class AnnotationsSidebar extends React.Component< createNewNoteFromAISummary={ this.props.createNewNoteFromAISummary } + openImageInPreview={this.props.openImageInPreview} getYoutubePlayer={this.props.getYoutubePlayer} sidebarEvents={this.props.events} aiChatStateExternal={{ diff --git a/src/sidebar/annotations-sidebar/containers/AnnotationsSidebarContainer.tsx b/src/sidebar/annotations-sidebar/containers/AnnotationsSidebarContainer.tsx index 4c735e193e..3c865a1ba6 100644 --- a/src/sidebar/annotations-sidebar/containers/AnnotationsSidebarContainer.tsx +++ b/src/sidebar/annotations-sidebar/containers/AnnotationsSidebarContainer.tsx @@ -54,6 +54,7 @@ import { generateAnnotationCardInstanceId } from './utils' import type { AnnotationCardInstanceLocation } from '../types' import type { YoutubeService } from '@worldbrain/memex-common/lib/services/youtube' import { getBlockContentYoutubePlayerId } from '@worldbrain/memex-common/lib/common-ui/components/block-content' +import ImagePreviewModal from '@worldbrain/memex-common/lib/common-ui/image-preview-modal' import type { YoutubePlayer } from '@worldbrain/memex-common/lib/services/youtube/types' import { AICounterIndicator } from 'src/util/subscriptions/AICountIndicator' import SpaceContextMenu from 'src/custom-lists/ui/space-context-menu' @@ -418,6 +419,8 @@ export class AnnotationsSidebarContainer< imageSupport: this.props.imageSupport, getRootElement: this.props.getRootElement, copyLoadingState: annotationCardInstance?.copyLoadingState, + openImageInPreview: (imageSource: string) => + this.processEvent('openImageInPreview', imageSource), } } @@ -504,6 +507,8 @@ export class AnnotationsSidebarContainer< }) }, defaultMinimized: false, + openImageInPreview: (imageSource: string) => + this.processEvent('openImageInPreview', imageSource), } } @@ -1174,6 +1179,12 @@ export class AnnotationsSidebarContainer< unifiedAnnotationId, }) } + openImageInPreview={(imageSource: string) => + this.processEvent( + 'openImageInPreview', + imageSource, + ) + } getHighlightColorSettings={() => this.processEvent( 'getHighlightColorSettings', @@ -1865,6 +1876,15 @@ export class AnnotationsSidebarContainer< {this.renderModals()} + {this.state.imageSourceForPreview?.length > 0 ? ( + + this.processEvent('openImageInPreview', null) + } + getRootElement={this.props.getRootElement} + /> + ) : null} ) } diff --git a/src/sidebar/annotations-sidebar/containers/logic.ts b/src/sidebar/annotations-sidebar/containers/logic.ts index 9c99c1ea7d..3aa49669da 100644 --- a/src/sidebar/annotations-sidebar/containers/logic.ts +++ b/src/sidebar/annotations-sidebar/containers/logic.ts @@ -375,6 +375,7 @@ export class SidebarContainerLogic extends UILogic< existingSourcesOption: 'pristine', localFoldersList: [], bulkSelectionState: [], + imageSourceForPreview: null, } } @@ -1334,6 +1335,14 @@ export class SidebarContainerLogic extends UILogic< // } } + openImageInPreview: EventHandler<'openImageInPreview'> = async ({ + event, + }) => { + this.emitMutation({ + imageSourceForPreview: { $set: event }, + }) + } + setPopoutsActive: EventHandler<'setPopoutsActive'> = async ({ event }) => { this.emitMutation({ popoutsActive: { $set: event }, diff --git a/src/sidebar/annotations-sidebar/containers/types.ts b/src/sidebar/annotations-sidebar/containers/types.ts index 8a2686a240..bd43b3d5bd 100644 --- a/src/sidebar/annotations-sidebar/containers/types.ts +++ b/src/sidebar/annotations-sidebar/containers/types.ts @@ -152,6 +152,7 @@ export interface SidebarContainerState extends AnnotationConversationsState { remoteAnnotationsLoadState: TaskState foreignSelectedListLoadState: TaskState selectedTextAIPreview: string + imageSourceForPreview: string queryMode: string isTrial: boolean signupDate: number @@ -354,6 +355,7 @@ interface SidebarEvents { adjustSidebarWidth: { newWidth: string; isWidthLocked?: boolean } adjustRighPositionBasedOnRibbonPosition: { position: number } setPopoutsActive: boolean + openImageInPreview: string checkIfKeyValid: { apiKey: string } saveAIPrompt: { prompt: string } removeAISuggestion: { suggestion: string }