update typescript errors for vercel
This commit is contained in:
parent
e727deea19
commit
8d5b41f530
|
|
@ -130,5 +130,6 @@ The Fathom transcript shape includes:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,5 +81,6 @@ You can also manually edit the environment by:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,23 +97,29 @@ export function applyAutomergePatchesToTLStore(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const record = updatedObjects[id] || (existingRecord ? JSON.parse(JSON.stringify(existingRecord)) : defaultRecord)
|
let record = updatedObjects[id] || (existingRecord ? JSON.parse(JSON.stringify(existingRecord)) : defaultRecord)
|
||||||
|
|
||||||
// CRITICAL: Ensure typeName matches ID pattern (fixes misclassification)
|
// CRITICAL: Ensure typeName matches ID pattern (fixes misclassification)
|
||||||
// Note: obsidian_vault records are skipped above, so we don't need to handle them here
|
// Note: obsidian_vault records are skipped above, so we don't need to handle them here
|
||||||
if (typeof id === 'string') {
|
if (typeof id === 'string') {
|
||||||
|
let correctTypeName = record.typeName
|
||||||
if (id.startsWith('shape:') && record.typeName !== 'shape') {
|
if (id.startsWith('shape:') && record.typeName !== 'shape') {
|
||||||
record.typeName = 'shape'
|
correctTypeName = 'shape'
|
||||||
} else if (id.startsWith('page:') && record.typeName !== 'page') {
|
} else if (id.startsWith('page:') && record.typeName !== 'page') {
|
||||||
record.typeName = 'page'
|
correctTypeName = 'page'
|
||||||
} else if (id.startsWith('camera:') && record.typeName !== 'camera') {
|
} else if (id.startsWith('camera:') && record.typeName !== 'camera') {
|
||||||
record.typeName = 'camera'
|
correctTypeName = 'camera'
|
||||||
} else if (id.startsWith('instance:') && record.typeName !== 'instance') {
|
} else if (id.startsWith('instance:') && record.typeName !== 'instance') {
|
||||||
record.typeName = 'instance'
|
correctTypeName = 'instance'
|
||||||
} else if (id.startsWith('pointer:') && record.typeName !== 'pointer') {
|
} else if (id.startsWith('pointer:') && record.typeName !== 'pointer') {
|
||||||
record.typeName = 'pointer'
|
correctTypeName = 'pointer'
|
||||||
} else if (id.startsWith('document:') && record.typeName !== 'document') {
|
} else if (id.startsWith('document:') && record.typeName !== 'document') {
|
||||||
record.typeName = 'document'
|
correctTypeName = 'document'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new object with correct typeName if it changed
|
||||||
|
if (correctTypeName !== record.typeName) {
|
||||||
|
record = { ...record, typeName: correctTypeName }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -219,19 +219,19 @@ export class CloudflareNetworkAdapter extends NetworkAdapter {
|
||||||
// We need to handle both binary and text messages
|
// We need to handle both binary and text messages
|
||||||
if (event.data instanceof ArrayBuffer) {
|
if (event.data instanceof ArrayBuffer) {
|
||||||
console.log('🔌 CloudflareAdapter: Received binary message (Automerge protocol)')
|
console.log('🔌 CloudflareAdapter: Received binary message (Automerge protocol)')
|
||||||
// Handle binary Automerge sync messages - pass directly to Repo
|
// Handle binary Automerge sync messages - convert ArrayBuffer to Uint8Array
|
||||||
// Automerge Repo expects binary sync messages as ArrayBuffer
|
// Automerge Repo expects binary sync messages as Uint8Array
|
||||||
this.emit('message', {
|
this.emit('message', {
|
||||||
type: 'sync',
|
type: 'sync',
|
||||||
data: event.data
|
data: new Uint8Array(event.data)
|
||||||
})
|
})
|
||||||
} else if (event.data instanceof Blob) {
|
} else if (event.data instanceof Blob) {
|
||||||
// Handle Blob messages (convert to ArrayBuffer)
|
// Handle Blob messages (convert to Uint8Array)
|
||||||
event.data.arrayBuffer().then((buffer) => {
|
event.data.arrayBuffer().then((buffer) => {
|
||||||
console.log('🔌 CloudflareAdapter: Received Blob message, converted to ArrayBuffer')
|
console.log('🔌 CloudflareAdapter: Received Blob message, converted to Uint8Array')
|
||||||
this.emit('message', {
|
this.emit('message', {
|
||||||
type: 'sync',
|
type: 'sync',
|
||||||
data: buffer
|
data: new Uint8Array(buffer)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1488,7 +1488,7 @@ export function useAutomergeStoreV2({
|
||||||
for (const record of failedRecords) {
|
for (const record of failedRecords) {
|
||||||
try {
|
try {
|
||||||
// Additional cleanup for failed records - create deep copy
|
// Additional cleanup for failed records - create deep copy
|
||||||
const fixedRecord = JSON.parse(JSON.stringify(record))
|
let fixedRecord = JSON.parse(JSON.stringify(record))
|
||||||
|
|
||||||
// Fix instance records specifically
|
// Fix instance records specifically
|
||||||
if (fixedRecord.typeName === 'instance') {
|
if (fixedRecord.typeName === 'instance') {
|
||||||
|
|
|
||||||
|
|
@ -143,13 +143,13 @@ export function useAutomergeSync(config: AutomergeSyncConfig): TLStoreWithStatus
|
||||||
return {
|
return {
|
||||||
status: isLoading ? 'loading' : 'not-synced',
|
status: isLoading ? 'loading' : 'not-synced',
|
||||||
connectionStatus: 'offline',
|
connectionStatus: 'offline',
|
||||||
store: null
|
store: undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 'synced',
|
status: 'synced-remote' as const,
|
||||||
connectionStatus: 'online',
|
connectionStatus: 'online' as const,
|
||||||
store
|
store
|
||||||
}
|
}
|
||||||
}, [store, isLoading])
|
}, [store, isLoading])
|
||||||
|
|
@ -164,5 +164,5 @@ export function useAutomergeSync(config: AutomergeSyncConfig): TLStoreWithStatus
|
||||||
return {
|
return {
|
||||||
...storeWithStatus,
|
...storeWithStatus,
|
||||||
presence
|
presence
|
||||||
}
|
} as TLStoreWithStatus & { presence: typeof presence }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ export const StandardizedToolWrapper: React.FC<StandardizedToolWrapperProps> = (
|
||||||
onPointerDown={handleHeaderPointerDown}
|
onPointerDown={handleHeaderPointerDown}
|
||||||
onMouseEnter={() => setIsHoveringHeader(true)}
|
onMouseEnter={() => setIsHoveringHeader(true)}
|
||||||
onMouseLeave={() => setIsHoveringHeader(false)}
|
onMouseLeave={() => setIsHoveringHeader(false)}
|
||||||
onMouseDown={(e) => {
|
onMouseDown={(_e) => {
|
||||||
// Ensure selection happens on mouse down for immediate visual feedback
|
// Ensure selection happens on mouse down for immediate visual feedback
|
||||||
if (editor && shapeId && !isSelected) {
|
if (editor && shapeId && !isSelected) {
|
||||||
editor.setSelectedShapes([shapeId])
|
editor.setSelectedShapes([shapeId])
|
||||||
|
|
|
||||||
|
|
@ -258,5 +258,6 @@ export const LocationDashboard: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,5 +229,6 @@ export const LocationMap: React.FC<LocationMapProps> = ({
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { ShareLocation } from "./ShareLocation"
|
import { ShareLocation } from "./ShareLocation"
|
||||||
|
|
||||||
export function LocationShareDialog({ onClose }: TLUiDialogProps) {
|
export function LocationShareDialog({ onClose: _onClose }: TLUiDialogProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TldrawUiDialogHeader>
|
<TldrawUiDialogHeader>
|
||||||
|
|
|
||||||
|
|
@ -171,5 +171,6 @@ export const LocationViewer: React.FC<LocationViewerProps> = ({ shareToken }) =>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,5 +138,6 @@ export const ShareSettingsComponent: React.FC<ShareSettingsProps> = ({ onSetting
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -413,5 +413,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,21 +30,21 @@ declare global {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SpeechRecognitionResultList {
|
interface SpeechRecognitionResultList {
|
||||||
length: number
|
readonly length: number
|
||||||
item(index: number): SpeechRecognitionResult
|
item(index: number): SpeechRecognitionResult
|
||||||
[index: number]: SpeechRecognitionResult
|
[index: number]: SpeechRecognitionResult
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SpeechRecognitionResult {
|
interface SpeechRecognitionResult {
|
||||||
length: number
|
readonly length: number
|
||||||
item(index: number): SpeechRecognitionAlternative
|
item(index: number): SpeechRecognitionAlternative
|
||||||
[index: number]: SpeechRecognitionAlternative
|
[index: number]: SpeechRecognitionAlternative
|
||||||
isFinal: boolean
|
readonly isFinal: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SpeechRecognitionAlternative {
|
interface SpeechRecognitionAlternative {
|
||||||
transcript: string
|
readonly transcript: string
|
||||||
confidence: number
|
readonly confidence: number
|
||||||
}
|
}
|
||||||
|
|
||||||
var SpeechRecognition: {
|
var SpeechRecognition: {
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ export class HoloSphereService {
|
||||||
let unsubscribe: (() => void) | undefined = undefined
|
let unsubscribe: (() => void) | undefined = undefined
|
||||||
if (this.sphere.subscribe) {
|
if (this.sphere.subscribe) {
|
||||||
try {
|
try {
|
||||||
unsubscribe = this.sphere.subscribe(holon, lens, (data: any, key?: string) => {
|
const subscribeResult = this.sphere.subscribe(holon, lens, (data: any, key?: string) => {
|
||||||
subscriptionActive = true
|
subscriptionActive = true
|
||||||
console.log(`📥 Subscription callback fired for ${lens}:`, { data, key, dataType: typeof data, isObject: typeof data === 'object', isArray: Array.isArray(data) })
|
console.log(`📥 Subscription callback fired for ${lens}:`, { data, key, dataType: typeof data, isObject: typeof data === 'object', isArray: Array.isArray(data) })
|
||||||
|
|
||||||
|
|
@ -183,7 +183,18 @@ export class HoloSphereService {
|
||||||
console.log(`📥 Current collected data for ${lens}:`, Object.keys(collectedData).length, 'keys')
|
console.log(`📥 Current collected data for ${lens}:`, Object.keys(collectedData).length, 'keys')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(`✅ Subscribe called successfully for ${lens}`)
|
// Handle Promise if subscribe returns one
|
||||||
|
if (subscribeResult instanceof Promise) {
|
||||||
|
subscribeResult.then((result) => {
|
||||||
|
unsubscribe = result?.unsubscribe || undefined
|
||||||
|
console.log(`✅ Subscribe called successfully for ${lens}`)
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(`❌ Error in subscribe promise for ${lens}:`, err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
unsubscribe = subscribeResult?.unsubscribe || undefined
|
||||||
|
console.log(`✅ Subscribe called successfully for ${lens}`)
|
||||||
|
}
|
||||||
} catch (subError) {
|
} catch (subError) {
|
||||||
console.error(`❌ Error calling subscribe for ${lens}:`, subError)
|
console.error(`❌ Error calling subscribe for ${lens}:`, subError)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,10 @@ export class LocationStorageService {
|
||||||
private async ensureDirectory(path: string[]): Promise<void> {
|
private async ensureDirectory(path: string[]): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const dirPath = odd.path.directory(...path);
|
const dirPath = odd.path.directory(...path);
|
||||||
const exists = await this.fs.exists(dirPath as any);
|
const fs = this.fs as any;
|
||||||
|
const exists = await fs.exists(dirPath);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
await this.fs.mkdir(dirPath as any);
|
await fs.mkdir(dirPath);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error ensuring directory:', error);
|
console.error('Error ensuring directory:', error);
|
||||||
|
|
@ -81,10 +82,11 @@ export class LocationStorageService {
|
||||||
*/
|
*/
|
||||||
async saveLocation(location: LocationData): Promise<void> {
|
async saveLocation(location: LocationData): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const filePath = odd.path.file(...this.locationsPath, `${location.id}.json`);
|
const filePath = (odd.path as any).file(...this.locationsPath, `${location.id}.json`);
|
||||||
const content = new TextEncoder().encode(JSON.stringify(location, null, 2));
|
const content = new TextEncoder().encode(JSON.stringify(location, null, 2));
|
||||||
await this.fs.write(filePath as any, content as any);
|
const fs = this.fs as any;
|
||||||
await this.fs.publish();
|
await fs.write(filePath, content);
|
||||||
|
await fs.publish();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving location:', error);
|
console.error('Error saving location:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|
@ -96,12 +98,13 @@ export class LocationStorageService {
|
||||||
*/
|
*/
|
||||||
async getLocation(locationId: string): Promise<LocationData | null> {
|
async getLocation(locationId: string): Promise<LocationData | null> {
|
||||||
try {
|
try {
|
||||||
const filePath = odd.path.file(...this.locationsPath, `${locationId}.json`);
|
const filePath = (odd.path as any).file(...this.locationsPath, `${locationId}.json`);
|
||||||
const exists = await this.fs.exists(filePath as any);
|
const fs = this.fs as any;
|
||||||
|
const exists = await fs.exists(filePath);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const content = await this.fs.read(filePath as any);
|
const content = await fs.read(filePath);
|
||||||
const text = new TextDecoder().decode(content as Uint8Array);
|
const text = new TextDecoder().decode(content as Uint8Array);
|
||||||
return JSON.parse(text) as LocationData;
|
return JSON.parse(text) as LocationData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -116,12 +119,13 @@ export class LocationStorageService {
|
||||||
async createShare(share: LocationShare): Promise<void> {
|
async createShare(share: LocationShare): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Save share metadata in private directory
|
// Save share metadata in private directory
|
||||||
const sharePath = odd.path.file(...this.sharesPath, `${share.id}.json`);
|
const sharePath = (odd.path as any).file(...this.sharesPath, `${share.id}.json`);
|
||||||
const shareContent = new TextEncoder().encode(JSON.stringify(share, null, 2));
|
const shareContent = new TextEncoder().encode(JSON.stringify(share, null, 2));
|
||||||
await this.fs.write(sharePath as any, shareContent as any);
|
const fs = this.fs as any;
|
||||||
|
await fs.write(sharePath, shareContent);
|
||||||
|
|
||||||
// Create public reference file for share validation (only token, not full data)
|
// Create public reference file for share validation (only token, not full data)
|
||||||
const publicSharePath = odd.path.file(...this.publicSharesPath, `${share.shareToken}.json`);
|
const publicSharePath = (odd.path as any).file(...this.publicSharesPath, `${share.shareToken}.json`);
|
||||||
const publicShareRef = {
|
const publicShareRef = {
|
||||||
shareToken: share.shareToken,
|
shareToken: share.shareToken,
|
||||||
shareId: share.id,
|
shareId: share.id,
|
||||||
|
|
@ -129,9 +133,9 @@ export class LocationStorageService {
|
||||||
expiresAt: share.expiresAt,
|
expiresAt: share.expiresAt,
|
||||||
};
|
};
|
||||||
const publicContent = new TextEncoder().encode(JSON.stringify(publicShareRef, null, 2));
|
const publicContent = new TextEncoder().encode(JSON.stringify(publicShareRef, null, 2));
|
||||||
await this.fs.write(publicSharePath as any, publicContent as any);
|
await fs.write(publicSharePath, publicContent);
|
||||||
|
|
||||||
await this.fs.publish();
|
await fs.publish();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating share:', error);
|
console.error('Error creating share:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|
@ -144,24 +148,25 @@ export class LocationStorageService {
|
||||||
async getShareByToken(shareToken: string): Promise<LocationShare | null> {
|
async getShareByToken(shareToken: string): Promise<LocationShare | null> {
|
||||||
try {
|
try {
|
||||||
// First check public reference
|
// First check public reference
|
||||||
const publicSharePath = odd.path.file(...this.publicSharesPath, `${shareToken}.json`);
|
const publicSharePath = (odd.path as any).file(...this.publicSharesPath, `${shareToken}.json`);
|
||||||
const publicExists = await this.fs.exists(publicSharePath as any);
|
const fs = this.fs as any;
|
||||||
|
const publicExists = await fs.exists(publicSharePath);
|
||||||
if (!publicExists) {
|
if (!publicExists) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const publicContent = await this.fs.read(publicSharePath as any);
|
const publicContent = await fs.read(publicSharePath);
|
||||||
const publicText = new TextDecoder().decode(publicContent as Uint8Array);
|
const publicText = new TextDecoder().decode(publicContent as Uint8Array);
|
||||||
const publicRef = JSON.parse(publicText);
|
const publicRef = JSON.parse(publicText);
|
||||||
|
|
||||||
// Now get full share from private directory
|
// Now get full share from private directory
|
||||||
const sharePath = odd.path.file(...this.sharesPath, `${publicRef.shareId}.json`);
|
const sharePath = (odd.path as any).file(...this.sharesPath, `${publicRef.shareId}.json`);
|
||||||
const shareExists = await this.fs.exists(sharePath as any);
|
const shareExists = await fs.exists(sharePath);
|
||||||
if (!shareExists) {
|
if (!shareExists) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shareContent = await this.fs.read(sharePath as any);
|
const shareContent = await fs.read(sharePath);
|
||||||
const shareText = new TextDecoder().decode(shareContent as Uint8Array);
|
const shareText = new TextDecoder().decode(shareContent as Uint8Array);
|
||||||
return JSON.parse(shareText) as LocationShare;
|
return JSON.parse(shareText) as LocationShare;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -176,12 +181,13 @@ export class LocationStorageService {
|
||||||
async getAllShares(): Promise<LocationShare[]> {
|
async getAllShares(): Promise<LocationShare[]> {
|
||||||
try {
|
try {
|
||||||
const dirPath = odd.path.directory(...this.sharesPath);
|
const dirPath = odd.path.directory(...this.sharesPath);
|
||||||
const exists = await this.fs.exists(dirPath as any);
|
const fs = this.fs as any;
|
||||||
|
const exists = await fs.exists(dirPath);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const files = await this.fs.ls(dirPath as any);
|
const files = await fs.ls(dirPath);
|
||||||
const shares: LocationShare[] = [];
|
const shares: LocationShare[] = [];
|
||||||
|
|
||||||
for (const fileName of Object.keys(files)) {
|
for (const fileName of Object.keys(files)) {
|
||||||
|
|
@ -206,12 +212,13 @@ export class LocationStorageService {
|
||||||
*/
|
*/
|
||||||
private async getShareById(shareId: string): Promise<LocationShare | null> {
|
private async getShareById(shareId: string): Promise<LocationShare | null> {
|
||||||
try {
|
try {
|
||||||
const sharePath = odd.path.file(...this.sharesPath, `${shareId}.json`);
|
const sharePath = (odd.path as any).file(...this.sharesPath, `${shareId}.json`);
|
||||||
const exists = await this.fs.exists(sharePath as any);
|
const fs = this.fs as any;
|
||||||
|
const exists = await fs.exists(sharePath);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const content = await this.fs.read(sharePath as any);
|
const content = await fs.read(sharePath);
|
||||||
const text = new TextDecoder().decode(content as Uint8Array);
|
const text = new TextDecoder().decode(content as Uint8Array);
|
||||||
return JSON.parse(text) as LocationShare;
|
return JSON.parse(text) as LocationShare;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -43,5 +43,6 @@ export interface GeolocationPosition {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ export function Board() {
|
||||||
const store = {
|
const store = {
|
||||||
store: storeWithHandle.store,
|
store: storeWithHandle.store,
|
||||||
status: storeWithHandle.status,
|
status: storeWithHandle.status,
|
||||||
connectionStatus: storeWithHandle.connectionStatus,
|
...('connectionStatus' in storeWithHandle ? { connectionStatus: storeWithHandle.connectionStatus } : {}),
|
||||||
error: storeWithHandle.error
|
error: storeWithHandle.error
|
||||||
}
|
}
|
||||||
const automergeHandle = storeWithHandle.handle
|
const automergeHandle = storeWithHandle.handle
|
||||||
|
|
@ -405,11 +405,11 @@ export function Board() {
|
||||||
const isInputFocused = (target && (
|
const isInputFocused = (target && (
|
||||||
target.tagName === 'INPUT' ||
|
target.tagName === 'INPUT' ||
|
||||||
target.tagName === 'TEXTAREA' ||
|
target.tagName === 'TEXTAREA' ||
|
||||||
target.isContentEditable
|
(target instanceof HTMLElement && target.isContentEditable)
|
||||||
)) || (activeElement && (
|
)) || (activeElement && (
|
||||||
activeElement.tagName === 'INPUT' ||
|
activeElement.tagName === 'INPUT' ||
|
||||||
activeElement.tagName === 'TEXTAREA' ||
|
activeElement.tagName === 'TEXTAREA' ||
|
||||||
activeElement.isContentEditable
|
(activeElement instanceof HTMLElement && activeElement.isContentEditable)
|
||||||
));
|
));
|
||||||
|
|
||||||
// If an input is focused, let it handle Escape (don't prevent default)
|
// If an input is focused, let it handle Escape (don't prevent default)
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,6 @@ export const LocationDashboardRoute: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,6 @@ export const LocationShareCreate: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,5 +39,6 @@ export const LocationShareView: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@ interface Message {
|
||||||
// Update the ChatBox component to accept userName
|
// Update the ChatBox component to accept userName
|
||||||
export const ChatBox: React.FC<IChatBoxShape["props"]> = ({
|
export const ChatBox: React.FC<IChatBoxShape["props"]> = ({
|
||||||
roomId,
|
roomId,
|
||||||
w,
|
w: _w,
|
||||||
h,
|
h: _h,
|
||||||
userName,
|
userName,
|
||||||
}) => {
|
}) => {
|
||||||
const [messages, setMessages] = useState<Message[]>([])
|
const [messages, setMessages] = useState<Message[]>([])
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,15 @@ export class FathomTranscriptShape extends BaseBoxShapeUtil<IFathomTranscript> {
|
||||||
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
|
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const buttonStyle: React.CSSProperties = {
|
||||||
|
padding: '4px 8px',
|
||||||
|
fontSize: '10px',
|
||||||
|
border: '1px solid #ccc',
|
||||||
|
borderRadius: '4px',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
cursor: 'pointer',
|
||||||
|
}
|
||||||
|
|
||||||
// Custom header content with meeting info and toggle buttons
|
// Custom header content with meeting info and toggle buttons
|
||||||
const headerContent = (
|
const headerContent = (
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', gap: '8px' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', gap: '8px' }}>
|
||||||
|
|
|
||||||
|
|
@ -981,7 +981,7 @@ export class ObsNoteShape extends BaseBoxShapeUtil<IObsNoteShape> {
|
||||||
/**
|
/**
|
||||||
* Sanitize props to ensure all values are JSON serializable
|
* Sanitize props to ensure all values are JSON serializable
|
||||||
*/
|
*/
|
||||||
private static sanitizeProps(props: Partial<IObsNoteShape['props']>): IObsNoteShape['props'] {
|
public static sanitizeProps(props: Partial<IObsNoteShape['props']>): IObsNoteShape['props'] {
|
||||||
// Ensure tags is a proper string array
|
// Ensure tags is a proper string array
|
||||||
const tags = Array.isArray(props.tags)
|
const tags = Array.isArray(props.tags)
|
||||||
? props.tags.filter(tag => typeof tag === 'string').map(tag => String(tag))
|
? props.tags.filter(tag => typeof tag === 'string').map(tag => String(tag))
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,10 @@ export class HolonIdle extends StateNode {
|
||||||
|
|
||||||
override onExit = () => {
|
override onExit = () => {
|
||||||
this.cleanupTooltip()
|
this.cleanupTooltip()
|
||||||
|
// Clean up event listeners
|
||||||
|
if ((this as any).cleanup) {
|
||||||
|
;(this as any).cleanup()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private cleanupTooltip = () => {
|
private cleanupTooltip = () => {
|
||||||
|
|
@ -278,123 +282,6 @@ export class HolonIdle extends StateNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createHolonShape(clickX?: number, clickY?: number) {
|
|
||||||
try {
|
|
||||||
// Store current camera position to prevent it from changing
|
|
||||||
const currentCamera = this.editor.getCamera()
|
|
||||||
this.editor.stopCameraAnimation()
|
|
||||||
|
|
||||||
// Standardized size: 700x400 (matches default props to fit ID and button)
|
|
||||||
const shapeWidth = 700
|
|
||||||
const shapeHeight = 400
|
|
||||||
|
|
||||||
// Use click position if available, otherwise fall back to viewport center
|
|
||||||
let baseX: number
|
|
||||||
let baseY: number
|
|
||||||
|
|
||||||
if (clickX !== undefined && clickY !== undefined) {
|
|
||||||
// Position new Holon shape at click location (centered on click)
|
|
||||||
baseX = clickX - shapeWidth / 2 // Center the shape on click
|
|
||||||
baseY = clickY - shapeHeight / 2 // Center the shape on click
|
|
||||||
console.log('📍 HolonTool: Calculated base position from click:', { clickX, clickY, baseX, baseY, shapeWidth, shapeHeight })
|
|
||||||
} else {
|
|
||||||
// Fallback to viewport center if no click coordinates
|
|
||||||
const viewport = this.editor.getViewportPageBounds()
|
|
||||||
const centerX = viewport.x + viewport.w / 2
|
|
||||||
const centerY = viewport.y + viewport.h / 2
|
|
||||||
baseX = centerX - shapeWidth / 2 // Center the shape
|
|
||||||
baseY = centerY - shapeHeight / 2 // Center the shape
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find existing Holon shapes for naming
|
|
||||||
const allShapes = this.editor.getCurrentPageShapes()
|
|
||||||
const existingHolonShapes = allShapes.filter(s => s.type === 'Holon')
|
|
||||||
|
|
||||||
// ALWAYS use click position directly when provided - user clicked where they want it
|
|
||||||
// Skip collision detection entirely for user clicks to ensure it appears exactly where clicked
|
|
||||||
let finalX = baseX
|
|
||||||
let finalY = baseY
|
|
||||||
|
|
||||||
if (clickX !== undefined && clickY !== undefined) {
|
|
||||||
// User clicked - ALWAYS use that exact position, no collision detection
|
|
||||||
// This ensures the shape appears exactly where the user clicked
|
|
||||||
finalX = baseX
|
|
||||||
finalY = baseY
|
|
||||||
console.log('📍 Using click position directly (no collision check):', {
|
|
||||||
clickPosition: { x: clickX, y: clickY },
|
|
||||||
shapePosition: { x: finalX, y: finalY },
|
|
||||||
shapeSize: { w: shapeWidth, h: shapeHeight }
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// For fallback (no click), use collision detection
|
|
||||||
const position = findNonOverlappingPosition(
|
|
||||||
this.editor,
|
|
||||||
baseX,
|
|
||||||
baseY,
|
|
||||||
shapeWidth,
|
|
||||||
shapeHeight
|
|
||||||
)
|
|
||||||
finalX = position.x
|
|
||||||
finalY = position.y
|
|
||||||
console.log('📍 No click position - using collision detection:', { finalX, finalY })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default coordinates (can be changed by user)
|
|
||||||
const defaultLat = 40.7128 // NYC
|
|
||||||
const defaultLng = -74.0060
|
|
||||||
const defaultResolution = 7 // City level
|
|
||||||
|
|
||||||
console.log('📍 HolonTool: Final position for shape:', { finalX, finalY, wasOverlap: clickX !== undefined && clickY !== undefined && (finalX !== baseX || finalY !== baseY) })
|
|
||||||
|
|
||||||
const holonShape = this.editor.createShape({
|
|
||||||
type: 'Holon',
|
|
||||||
x: finalX,
|
|
||||||
y: finalY,
|
|
||||||
props: {
|
|
||||||
w: shapeWidth,
|
|
||||||
h: shapeHeight,
|
|
||||||
name: `Holon ${existingHolonShapes.length + 1}`,
|
|
||||||
description: '',
|
|
||||||
latitude: defaultLat,
|
|
||||||
longitude: defaultLng,
|
|
||||||
resolution: defaultResolution,
|
|
||||||
holonId: '',
|
|
||||||
isConnected: false,
|
|
||||||
isEditing: true,
|
|
||||||
selectedLens: 'general',
|
|
||||||
data: {},
|
|
||||||
connections: [],
|
|
||||||
lastUpdated: Date.now()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('✅ Created Holon shape:', holonShape.id)
|
|
||||||
|
|
||||||
// Restore camera position if it changed
|
|
||||||
const newCamera = this.editor.getCamera()
|
|
||||||
if (currentCamera.x !== newCamera.x || currentCamera.y !== newCamera.y || currentCamera.z !== newCamera.z) {
|
|
||||||
this.editor.setCamera(currentCamera, { animation: { duration: 0 } })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select the new shape
|
|
||||||
setTimeout(() => {
|
|
||||||
// Preserve camera position when selecting
|
|
||||||
const cameraBeforeSelect = this.editor.getCamera()
|
|
||||||
this.editor.stopCameraAnimation()
|
|
||||||
this.editor.setSelectedShapes([`shape:${holonShape.id}`] as any)
|
|
||||||
this.editor.setCurrentTool('select')
|
|
||||||
// Restore camera if it changed during selection
|
|
||||||
const cameraAfterSelect = this.editor.getCamera()
|
|
||||||
if (cameraBeforeSelect.x !== cameraAfterSelect.x || cameraBeforeSelect.y !== cameraAfterSelect.y || cameraBeforeSelect.z !== cameraAfterSelect.z) {
|
|
||||||
this.editor.setCamera(cameraBeforeSelect, { animation: { duration: 0 } })
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error creating Holon shape:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private addRefreshAllListener() {
|
private addRefreshAllListener() {
|
||||||
// Listen for refresh-all-holons event
|
// Listen for refresh-all-holons event
|
||||||
const handleRefreshAll = async () => {
|
const handleRefreshAll = async () => {
|
||||||
|
|
@ -439,11 +326,4 @@ export class HolonIdle extends StateNode {
|
||||||
// Store cleanup function for later use
|
// Store cleanup function for later use
|
||||||
;(this as any).cleanup = cleanup
|
;(this as any).cleanup = cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
onExit() {
|
|
||||||
// Clean up event listeners
|
|
||||||
if ((this as any).cleanup) {
|
|
||||||
;(this as any).cleanup()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,38 @@ export class ObsNoteTool extends StateNode {
|
||||||
this.addRefreshAllListener()
|
this.addRefreshAllListener()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private addRefreshAllListener() {
|
||||||
|
// Listen for refresh-all-obsnotes event
|
||||||
|
const handleRefreshAll = async () => {
|
||||||
|
const shapeUtil = new ObsNoteShape(this.editor)
|
||||||
|
shapeUtil.editor = this.editor
|
||||||
|
|
||||||
|
const result = await shapeUtil.refreshAllFromVault()
|
||||||
|
if (result.success > 0) {
|
||||||
|
alert(`✅ Refreshed ${result.success} notes from vault!${result.failed > 0 ? ` (${result.failed} failed)` : ''}`)
|
||||||
|
} else {
|
||||||
|
alert('❌ Failed to refresh any notes. Check console for details.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('refresh-all-obsnotes', handleRefreshAll)
|
||||||
|
|
||||||
|
// Clean up listener when tool is deselected
|
||||||
|
const cleanup = () => {
|
||||||
|
window.removeEventListener('refresh-all-obsnotes', handleRefreshAll)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store cleanup function for later use
|
||||||
|
;(this as any).cleanup = cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
onExit() {
|
||||||
|
// Clean up event listeners
|
||||||
|
if ((this as any).cleanup) {
|
||||||
|
;(this as any).cleanup()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ObsNoteIdle extends StateNode {
|
export class ObsNoteIdle extends StateNode {
|
||||||
|
|
@ -101,6 +133,10 @@ export class ObsNoteIdle extends StateNode {
|
||||||
|
|
||||||
override onExit = () => {
|
override onExit = () => {
|
||||||
this.cleanupTooltip()
|
this.cleanupTooltip()
|
||||||
|
// Clean up event listeners
|
||||||
|
if ((this as any).cleanup) {
|
||||||
|
;(this as any).cleanup()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private cleanupTooltip = () => {
|
private cleanupTooltip = () => {
|
||||||
|
|
@ -182,36 +218,4 @@ export class ObsNoteIdle extends StateNode {
|
||||||
console.error('❌ Error creating ObsidianBrowser shape:', error)
|
console.error('❌ Error creating ObsidianBrowser shape:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addRefreshAllListener() {
|
|
||||||
// Listen for refresh-all-obsnotes event
|
|
||||||
const handleRefreshAll = async () => {
|
|
||||||
const shapeUtil = new ObsNoteShape(this.editor)
|
|
||||||
shapeUtil.editor = this.editor
|
|
||||||
|
|
||||||
const result = await shapeUtil.refreshAllFromVault()
|
|
||||||
if (result.success > 0) {
|
|
||||||
alert(`✅ Refreshed ${result.success} notes from vault!${result.failed > 0 ? ` (${result.failed} failed)` : ''}`)
|
|
||||||
} else {
|
|
||||||
alert('❌ Failed to refresh any notes. Check console for details.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('refresh-all-obsnotes', handleRefreshAll)
|
|
||||||
|
|
||||||
// Clean up listener when tool is deselected
|
|
||||||
const cleanup = () => {
|
|
||||||
window.removeEventListener('refresh-all-obsnotes', handleRefreshAll)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store cleanup function for later use
|
|
||||||
;(this as any).cleanup = cleanup
|
|
||||||
}
|
|
||||||
|
|
||||||
onExit() {
|
|
||||||
// Clean up event listeners
|
|
||||||
if ((this as any).cleanup) {
|
|
||||||
;(this as any).cleanup()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Editor, TLShape, Box } from "@tldraw/tldraw"
|
import { Editor, TLShape, Box, TLShapeId } from "@tldraw/tldraw"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if two boxes overlap
|
* Check if two boxes overlap
|
||||||
|
|
@ -20,8 +20,9 @@ function boxesOverlap(
|
||||||
* Get the bounding box of a shape
|
* Get the bounding box of a shape
|
||||||
*/
|
*/
|
||||||
function getShapeBounds(editor: Editor, shape: TLShape | string): Box | null {
|
function getShapeBounds(editor: Editor, shape: TLShape | string): Box | null {
|
||||||
const shapeId = typeof shape === 'string' ? shape : shape.id
|
const shapeId = typeof shape === 'string' ? (shape as TLShapeId) : shape.id
|
||||||
return editor.getShapePageBounds(shapeId)
|
const bounds = editor.getShapePageBounds(shapeId)
|
||||||
|
return bounds ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -70,7 +71,7 @@ export function resolveOverlaps(editor: Editor, shapeId: string): void {
|
||||||
const newY = shapeBox.y // Keep same Y position
|
const newY = shapeBox.y // Keep same Y position
|
||||||
|
|
||||||
editor.updateShape({
|
editor.updateShape({
|
||||||
id: shapeId,
|
id: shapeId as TLShapeId,
|
||||||
type: shape.type,
|
type: shape.type,
|
||||||
x: newX,
|
x: newX,
|
||||||
y: newY,
|
y: newY,
|
||||||
|
|
@ -90,7 +91,7 @@ export function resolveOverlaps(editor: Editor, shapeId: string): void {
|
||||||
if (boxesOverlap(newShapeBox, otherBox, 20)) {
|
if (boxesOverlap(newShapeBox, otherBox, 20)) {
|
||||||
const newY2 = otherBox.y + otherBox.h + 20
|
const newY2 = otherBox.y + otherBox.h + 20
|
||||||
editor.updateShape({
|
editor.updateShape({
|
||||||
id: shapeId,
|
id: shapeId as TLShapeId,
|
||||||
type: shape.type,
|
type: shape.type,
|
||||||
x: shapeBox.x, // Keep original X
|
x: shapeBox.x, // Keep original X
|
||||||
y: newY2,
|
y: newY2,
|
||||||
|
|
|
||||||
|
|
@ -60,5 +60,6 @@ echo " npm run dev"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,7 @@ const router = AutoRouter<IRequest, [env: Environment, ctx: ExecutionContext]>({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json()
|
const data = await response.json() as { data?: any[] }
|
||||||
console.log('Fathom API success, data length:', data?.data?.length || 0)
|
console.log('Fathom API success, data length:', data?.data?.length || 0)
|
||||||
return new Response(JSON.stringify(data), {
|
return new Response(JSON.stringify(data), {
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue