Files
speckle-server/packages/server/modules/comments/services/data.ts
T
Dimitrie Stefanescu 7b037352df Dim/fe2/view changes (#1608)
* Fixed an issue with curves doubling up on geometry and also not being selectable after the last filtering changes. Added the options to make lines transparent. Added lines to diffing

* Points now are diff-able and support proper visual diff-ing. Visual diff filters are now chosen internally by the Differ. Fixed an issue with LineBatch and transparency

* Implemented PLAIN visual diff mode, where all objects keep their original materil, but opacity is manipulated via the diff time. Added API member function to switch between the PLAIN and COLORED visual diff modes

* feat(fe2): diffs wip

* Diffing fixes for instances and blocks. Things seem to be working fine, but there are some caveats. Additionally, some older issues were fixed and diffing now works better on all the rest of the streams

* feat(fe2): de-dupes diff results

* feat(fe2): wip diffs

* feat(fe2): diff transparency goes from 0 to 1

* feat(fe2): diff results display work

* feat(fe2): diff results display work

* feat(fe2): diff panel work

* feat(fe2): diff work: various display changes, coloring toggle, selection logic, selection object display wip

* feat(fe2): diff work: cleaned up old/new version, fixed minor bug in viewer diff time when swapping color mode

* feat(fe2): diff work: implements custom selection logic and selection display for modified objects (they come in pairs now)

* feat(fe2): diff minor fix in selected object display

* feat(fe2): wip; trying to fix diff order to be consistent (ordered by date)

* feat(fe2): wip, broken state right now

* feat(fe2): fixes scrollbars in viewer

* feat(fe2): fixes slider sync with diff time

* feat(fe2): WIP syncs of diffs (threads, refreshes, etc.)

* feat(fe2): diffing polish

* speckle shared fix

* speckle shared fix

* more bugfixes

* linter fixess

* more CI fixes

* fix viewerState serialization

* more linting fixess

* template fixes

* moving tailwind classes to theme package

* migrated away from diffString + simplified postSetup

* moved diff new/old version resolution to use state.resources

* cleanup

* updating url threadId & diff command correctly

* minor improvements to diff state

---------

Co-authored-by: AlexandruPopovici <alexandrupopoviciioan@gmail.com>
Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
2023-06-08 11:26:19 +03:00

176 lines
4.9 KiB
TypeScript

import { CommentRecord } from '@/modules/comments/helpers/types'
import { LegacyCommentViewerData } from '@/modules/core/graph/generated/graphql'
import {
getViewerResourcesForComments,
viewerResourcesToString
} from '@/modules/core/services/commit/viewerResources'
import { Nullable, SpeckleViewer } from '@speckle/shared'
import { has, get, intersection, isObjectLike } from 'lodash'
type SerializedViewerState = SpeckleViewer.ViewerState.SerializedViewerState
export type LegacyData = Partial<LegacyCommentViewerData>
export type DataStruct = {
version: number
state: SerializedViewerState
}
export function inputToDataStruct(
inputSerializedViewerState: unknown
): Nullable<DataStruct> {
const state = SpeckleViewer.ViewerState.isSerializedViewerState(
inputSerializedViewerState
)
? inputSerializedViewerState
: null
if (!state) return null
return {
version: SpeckleViewer.ViewerState.SERIALIZED_VIEWER_STATE_VERSION,
state
}
}
export function isDataStruct(data: unknown): data is DataStruct {
if (!data) return false
if (!has(data, 'version')) return false
const stateRaw = get(data, 'state')
return SpeckleViewer.ViewerState.isSerializedViewerState(stateRaw)
}
export function formatSerializedViewerState(state: SerializedViewerState) {
return SpeckleViewer.ViewerState.formatSerializedViewerState(state)
}
export function isLegacyData(data: unknown): data is LegacyData {
if (!data) return false
const keys: Array<keyof LegacyData> = [
'camPos',
'filters',
'location',
'sectionBox',
'selection'
]
if (!isObjectLike(data)) return false
const valKeys = Object.keys(data as Record<string, unknown>)
if (intersection(valKeys, keys).length !== keys.length) return false
return true
}
export function convertStateToLegacyData(state: SerializedViewerState): LegacyData {
const camPos = state.ui.camera.position
const camTarget = state.ui.camera.target
const zoom = state.ui.camera.zoom
const isOrtho = state.ui.camera.isOrthoProjection
const selection = state.ui.selection
const selectionLocation = selection || camTarget
const ret: LegacyData = {
camPos: [
camPos[0] || 0,
camPos[1] || 0,
camPos[2] || 0,
camTarget[0] || 0,
camTarget[1] || 0,
camTarget[2] || 0,
zoom || 1,
isOrtho ? 1 : 0
],
filters: {
passMin: state.viewer.metadata.filteringState?.passMin || null,
passMax: state.viewer.metadata.filteringState?.passMax || null,
hiddenIds: state.ui.filters.hiddenObjectIds.slice(),
isolatedIds: state.ui.filters.isolatedObjectIds.slice(),
sectionBox: state.ui.sectionBox,
propertyInfoKey: state.ui.filters.propertyFilter.key
},
location: {
x: selectionLocation[0] || 0,
y: selectionLocation[1] || 0,
z: selectionLocation[2] || 0
},
sectionBox: state.ui.sectionBox,
selection: null
}
return ret
}
export async function convertLegacyDataToState(
data: LegacyData,
comment: CommentRecord
): Promise<SerializedViewerState> {
const resources = await getViewerResourcesForComments(comment.streamId, [comment.id])
const sectionBox = data.filters?.sectionBox || data.sectionBox
const ret: SerializedViewerState = {
projectId: comment.streamId,
sessionId: 'legacy-sessionId',
viewer: {
metadata: {
filteringState: {
passMax: data.filters?.passMax,
passMin: data.filters?.passMin
}
}
},
resources: {
request: {
resourceIdString: viewerResourcesToString(resources),
threadFilters: {
includeArchived: false,
loadedVersionsOnly: false
}
}
},
ui: {
threads: {
openThread: {
threadId: null,
isTyping: false,
newThreadEditor: true
}
},
spotlightUserSessionId: null,
explodeFactor: 0,
filters: {
isolatedObjectIds: data.filters?.isolatedIds || [],
hiddenObjectIds: data.filters?.hiddenIds || [],
selectedObjectIds: [],
propertyFilter: {
key: data.filters?.propertyInfoKey || null,
isApplied: true
}
},
camera: {
position: [data.camPos?.[0] || 0, data.camPos?.[1] || 0, data.camPos?.[2] || 0],
target: [data.camPos?.[3] || 0, data.camPos?.[4] || 0, data.camPos?.[5] || 0],
isOrthoProjection: !!data.camPos?.[4],
zoom: data.camPos?.[5] || 1
},
sectionBox: sectionBox
? {
min: (sectionBox.min as number[]) || [0, 0, 0],
max: (sectionBox.max as number[]) || [0, 0, 0]
}
: null,
lightConfig: {},
selection: data.location
? [
data.location.x as number,
data.location.y as number,
data.location.z as number
]
: null,
diff: {
command: null,
mode: 1,
time: 0.5
}
}
}
return ret
}