@@ -12,6 +12,7 @@ import { memoizedLoading } from "../util/memo.ts"
1212import { CanvasWrapper } from "../util/canvas-wrapper.ts"
1313import { type Context , GroupSignal , mount , register , Signal } from "@kt3k/cell"
1414import type * as type from "./types.ts"
15+ import { BLOCK_SIZE } from "../util/constants.ts"
1516
1617const blockMapSource = new GroupSignal ( { uri : "" , text : "" } )
1718const fieldBlock = new Signal < FieldBlock | null > ( null )
@@ -29,25 +30,34 @@ blockMapSource.subscribe(({ uri, text }) => {
2930 )
3031} )
3132
33+ function getGridFromUri ( uri : string ) {
34+ const m = uri . match ( / b l o c k _ ( - ? \d + ) \. ( - ? \d + ) \. j s o n $ / )
35+ if ( ! m ) return { i : NaN , j : NaN }
36+ return { i : parseInt ( m [ 1 ] ) , j : parseInt ( m [ 2 ] ) }
37+ }
38+
3239function MainContainer ( { subscribe, el, query } : Context ) {
3340 subscribe ( fieldBlock , async ( fieldBlock ) => {
3441 const prev = prevFieldBlock
3542 prevFieldBlock = fieldBlock
3643 if ( fieldBlock === null ) return
3744
3845 if ( prev === null ) {
46+ const FULL_SIZE = 3200
47+ const SIDE_CANVAS_SIZE = 80
48+
3949 await fieldBlock . loadAssets ( )
4050 const canvas = fieldBlock . canvas
41- canvas . style . left = " "
42- canvas . style . top = " "
43- canvas . style . position = ""
51+ canvas . style . left = SIDE_CANVAS_SIZE + "px "
52+ canvas . style . top = SIDE_CANVAS_SIZE + "px "
53+ canvas . style . position = "absolute "
4454 canvas . classList . add ( "field-block-canvas" )
4555 el . innerHTML = ""
4656 el . appendChild ( canvas )
4757 fieldBlock . renderAll ( )
4858 mount ( "field-block-canvas" , el )
4959
50- const { i, j } = fieldBlock
60+ const { i, j } = getGridFromUri ( fieldBlock . toMap ( ) . url )
5161 const x = [
5262 [ - 1 , 0 ] ,
5363 [ 0 , - 1 ] ,
@@ -59,36 +69,99 @@ function MainContainer({ subscribe, el, query }: Context) {
5969 const l = j + dy * 200
6070 const href =
6171 new URL ( `block_${ k } .${ l } .json` , blockMapSource . get ( ) . uri ) . href
72+ let text
73+ try {
74+ text = await loadText ( href )
75+ } catch {
76+ text = await loadText (
77+ new URL ( "block_not_found.json" , blockMapSource . get ( ) . uri ) . href ,
78+ )
79+ }
80+ const blockMap = new BlockMap ( href , JSON . parse ( text ) )
81+ const fieldBlock = new FieldBlock ( blockMap , loadImage )
82+ await fieldBlock . loadAssets ( )
6283 const a = document . createElement ( "a" )
6384 a . href = href . replace ( / ^ f i l e : \/ \/ / , "vscode://file" )
6485 a . textContent = `block_${ k } .${ l } .json`
65- a . style . width = "20px"
66- a . style . height = "20px"
6786 a . classList . add (
6887 "absolute" ,
88+ "opacity-50" ,
6989 "hover:bg-neutral-700" ,
7090 "bg-neutral-800" ,
7191 "break-all" ,
7292 )
73- const FULL_SIZE = "3200px"
7493 if ( dx === - 1 ) {
94+ const imageData = fieldBlock . createImageDataForRange (
95+ BLOCK_SIZE - 5 ,
96+ 0 ,
97+ 5 ,
98+ BLOCK_SIZE ,
99+ )
100+ const canvas = document . createElement ( "canvas" )
101+ canvas . width = imageData . width
102+ canvas . height = imageData . height
103+ canvas . classList . add ( "absolute" , "top-0" , "left-0" )
104+ const ctx = canvas . getContext ( "2d" ) !
105+ ctx . putImageData ( imageData , 0 , 0 )
106+ a . appendChild ( canvas )
75107 a . style . left = "0"
76- a . style . top = "0 "
77- a . style . height = FULL_SIZE
78- a . style . marginLeft = "-20px "
108+ a . style . top = SIDE_CANVAS_SIZE + "px "
109+ a . style . height = FULL_SIZE + "px"
110+ a . style . width = SIDE_CANVAS_SIZE + "px "
79111 } else if ( dx === 1 ) {
80- a . style . left = FULL_SIZE
81- a . style . top = "0"
82- a . style . height = FULL_SIZE
112+ const imageData = fieldBlock . createImageDataForRange (
113+ 0 ,
114+ 0 ,
115+ 5 ,
116+ BLOCK_SIZE ,
117+ )
118+ const canvas = document . createElement ( "canvas" )
119+ canvas . width = imageData . width
120+ canvas . height = imageData . height
121+ canvas . classList . add ( "absolute" , "top-0" , "left-0" )
122+ const ctx = canvas . getContext ( "2d" ) !
123+ ctx . putImageData ( imageData , 0 , 0 )
124+ a . appendChild ( canvas )
125+ a . style . left = ( FULL_SIZE + SIDE_CANVAS_SIZE ) + "px"
126+ a . style . top = SIDE_CANVAS_SIZE + "px"
127+ a . style . height = FULL_SIZE + "px"
128+ a . style . width = SIDE_CANVAS_SIZE + "px"
83129 } else if ( dy === - 1 ) {
130+ const imageData = fieldBlock . createImageDataForRange (
131+ 0 ,
132+ BLOCK_SIZE - 5 ,
133+ BLOCK_SIZE ,
134+ 5 ,
135+ )
136+ const canvas = document . createElement ( "canvas" )
137+ canvas . width = imageData . width
138+ canvas . height = imageData . height
139+ canvas . classList . add ( "absolute" , "top-0" , "left-0" )
140+ const ctx = canvas . getContext ( "2d" ) !
141+ ctx . putImageData ( imageData , 0 , 0 )
142+ a . appendChild ( canvas )
84143 a . style . top = "0"
85- a . style . left = "0 "
86- a . style . width = FULL_SIZE
87- a . style . marginTop = "-20px "
144+ a . style . left = SIDE_CANVAS_SIZE + "px "
145+ a . style . width = FULL_SIZE + "px"
146+ a . style . height = SIDE_CANVAS_SIZE + "px "
88147 } else if ( dy === 1 ) {
89- a . style . top = FULL_SIZE
90- a . style . left = "0"
91- a . style . width = FULL_SIZE
148+ const imageData = fieldBlock . createImageDataForRange (
149+ 0 ,
150+ 0 ,
151+ BLOCK_SIZE ,
152+ 5 ,
153+ )
154+ const canvas = document . createElement ( "canvas" )
155+ canvas . width = imageData . width
156+ canvas . height = imageData . height
157+ canvas . classList . add ( "absolute" , "top-0" , "left-0" )
158+ const ctx = canvas . getContext ( "2d" ) !
159+ ctx . putImageData ( imageData , 0 , 0 )
160+ a . appendChild ( canvas )
161+ a . style . top = ( FULL_SIZE + SIDE_CANVAS_SIZE ) + "px"
162+ a . style . left = SIDE_CANVAS_SIZE + "px"
163+ a . style . width = FULL_SIZE + "px"
164+ a . style . height = SIDE_CANVAS_SIZE + "px"
92165 }
93166 el . appendChild ( a )
94167 }
@@ -245,23 +318,15 @@ function KeyHandler({ on }: Context) {
245318 } )
246319}
247320
321+ type ResolveImage = ( image : ImageBitmap ) => void
322+ const loadImageMap : Record < string , { resolve : ResolveImage } > = { }
248323const loadImage = memoizedLoading ( ( uri : string ) => {
249324 const { resolve, promise } = Promise . withResolvers < ImageBitmap > ( )
250325 const id = Math . random ( ) . toString ( )
251326 loadImageMap [ id ] = { resolve }
252327 vscode . postMessage ( { type : "loadImage" , uri, id } )
253328 return promise
254329} )
255-
256- type ResolveImage = ( image : ImageBitmap ) => void
257- const loadImageMap : Record < string , { resolve : ResolveImage } > = { }
258-
259- function onUpdate ( message : type . Extension . MessageUpdate ) {
260- const { uri, text } = message
261- blockMapSource . update ( { uri, text } )
262- vscode . setState ( { uri, text } )
263- }
264-
265330function onLoadImageResponse ( message : type . Extension . MessageLoadImageResponse ) {
266331 const image = new Image ( )
267332 image . src = message . text
@@ -274,6 +339,36 @@ function onLoadImageResponse(message: type.Extension.MessageLoadImageResponse) {
274339 }
275340}
276341
342+ type ResolveText = ( text : string ) => void
343+ type RejectText = ( error : Error ) => void
344+ const loadTextMap : Record <
345+ string ,
346+ { resolve : ResolveText ; reject : RejectText }
347+ > = { }
348+ const loadText = ( uri : string ) => {
349+ const { resolve, reject, promise } = Promise . withResolvers < string > ( )
350+ const id = Math . random ( ) . toString ( )
351+ loadTextMap [ id ] = { resolve, reject }
352+ vscode . postMessage ( { type : "loadText" , uri, id } )
353+ return promise
354+ }
355+ function onLoadTextResponse ( message : type . Extension . MessageLoadTextResponse ) {
356+ if ( "text" in message ) {
357+ const text = message . text
358+ loadTextMap [ message . id ] . resolve ( text )
359+ } else {
360+ const error = message . error
361+ loadTextMap [ message . id ] . reject ( new Error ( error ) )
362+ }
363+ delete loadTextMap [ message . id ]
364+ }
365+
366+ function onUpdate ( message : type . Extension . MessageUpdate ) {
367+ const { uri, text } = message
368+ blockMapSource . update ( { uri, text } )
369+ vscode . setState ( { uri, text } )
370+ }
371+
277372globalThis . addEventListener (
278373 "message" ,
279374 ( event : MessageEvent < type . Extension . Message > ) => {
@@ -285,6 +380,9 @@ globalThis.addEventListener(
285380 case "loadImageResponse" :
286381 onLoadImageResponse ( data )
287382 break
383+ case "loadTextResponse" :
384+ onLoadTextResponse ( data )
385+ break
288386 }
289387 } ,
290388)
0 commit comments