JBrowse 2 · Circular Genome View examples

Put the session in the URL

encodeSession and decodeSession, for a sharable link.

A decoded session goes in session, not defaultSession, which validates against a shape you wrote. The hash fragment never reaches the server, so a long session cannot fail with HTTP 414. Only the session travels: the receiving page supplies its own assembly and tracks.

View source — 92 lines
import { useState } from 'react'

import { useCreateOnceAsync } from '@jbrowse/core/util/hooks'
import {
  JBrowseCircularGenomeView,
  createViewState,
  decodeSession,
  encodeSession,
} from '@jbrowse/react-circular-genome-view2'

const assembly = {
  name: 'volvox',
  sequence: {
    adapter: {
      type: 'TwoBitAdapter',
      uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
    },
  },
}

const tracks = [
  {
    type: 'VariantTrack',
    trackId: 'volvox_sv_test',
    name: 'volvox structural variant test',
    category: ['VCF'],
    assemblyNames: ['volvox'],
    adapter: {
      type: 'VcfTabixAdapter',
      uri: 'https://jbrowse.org/code/jb2/main/test_data/volvox/volvox.dup.vcf.gz',
    },
  },
]

function readSessionParam() {
  return (
    new URLSearchParams(window.location.hash.slice(1)).get('session') ??
    undefined
  )
}

function writeSessionParam(value: string) {
  const params = new URLSearchParams(window.location.hash.slice(1))
  params.set('session', value)
  window.history.replaceState(null, '', `#${params.toString()}`)
}

async function build() {
  const param = readSessionParam()
  let session: Awaited<ReturnType<typeof decodeSession>> | undefined
  let status = ''
  if (param) {
    try {
      session = await decodeSession(param)
      status = `restored "${session.name}" from the URL`
    } catch (e) {
      console.error(e)
      status = `could not restore the session in the URL: ${e}`
    }
  }
  return { state: await createViewState({ assembly, tracks, session }), status }
}

export default function SessionInUrl() {
  const built = useCreateOnceAsync(build)
  const [saved, setSaved] = useState('')
  const state = built?.state
  const status = saved || built?.status

  return state ? (
    <div>
      <div style={{ padding: 8, fontSize: 13, background: '#8881' }}>
        <button
          type="button"
          onClick={() => {
            void (async () => {
              const encoded = await encodeSession(state)
              writeSessionParam(encoded)
              setSaved(
                `saved to the URL (${encoded.length} chars) — copy the address bar, or reload to restore it`,
              )
            })()
          }}
        >
          Save this view to the URL
        </button>{' '}
        {status || 'show a track or rotate the view, then save'}
      </div>
      <JBrowseCircularGenomeView viewState={state} />
    </div>
  ) : null
}