Skip to content

Commit

Permalink
Create autosave files for launcher panel entries
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Oct 12, 2021
1 parent a933d9f commit 204743a
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 42 deletions.
57 changes: 53 additions & 4 deletions products/jbrowse-desktop/public/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,16 @@ const defaultSessionName = `jbrowse_session.json`
const userData = app.getPath('userData')
const recentSessionsPath = path.join(userData, 'recent_sessions.json')
const quickstartDir = path.join(userData, 'quickstart')
const autosaveDir = path.join(userData, 'autosaved')

function getQuickstartPath(sessionName: string, ext = 'json') {
return path.join(quickstartDir, `${encodeURIComponent(sessionName)}.${ext}`)
}

function getAutosavePath(sessionName: string, ext = 'json') {
return path.join(autosaveDir, `${encodeURIComponent(sessionName)}.${ext}`)
}

if (!fs.existsSync(recentSessionsPath)) {
fs.writeFileSync(recentSessionsPath, stringify([]), 'utf8')
}
Expand All @@ -64,6 +69,10 @@ if (!fs.existsSync(quickstartDir)) {
fs.mkdirSync(quickstartDir, { recursive: true })
}

if (!fs.existsSync(autosaveDir)) {
fs.mkdirSync(autosaveDir, { recursive: true })
}

interface SessionSnap {
defaultSession: {
name: string
Expand Down Expand Up @@ -268,9 +277,20 @@ ipcMain.handle('quit', () => {
app.quit()
})

ipcMain.handle('listSessions', async () => {
return JSON.parse(await readFile(recentSessionsPath, 'utf8'))
})
ipcMain.handle(
'listSessions',
async (_event: unknown, showAutosaves: boolean) => {
const sessions = JSON.parse(await readFile(recentSessionsPath, 'utf8')) as {
path: string
}[]

if (!showAutosaves) {
return sessions.filter(f => !f.path.startsWith(autosaveDir))
} else {
return sessions
}
},
)

ipcMain.handle('loadExternalConfig', (_event: unknown, sessionPath) => {
return readFile(sessionPath, 'utf8')
Expand Down Expand Up @@ -341,6 +361,36 @@ ipcMain.handle(
})
},
)

// creates an initial entry in autosave folder
ipcMain.handle(
'createInitialAutosaveFile',
async (_event: unknown, snap: SessionSnap) => {
const rows = JSON.parse(fs.readFileSync(recentSessionsPath, 'utf8')) as [
{ path: string; updated: number },
]
const idx = rows.findIndex(r => r.path === path)
const path = getAutosavePath(`${+Date.now()}`)
const entry = {
path,
updated: +Date.now(),
name: snap.defaultSession?.name,
}
if (idx === -1) {
rows.unshift(entry)
} else {
rows[idx] = entry
}
await Promise.all([
writeFile(recentSessionsPath, stringify(rows)),
writeFile(path, stringify(snap)),
])

return path
},
)

// snapshots page and saves to path
ipcMain.handle(
'saveSession',
async (_event: unknown, path: string, snap: SessionSnap) => {
Expand Down Expand Up @@ -368,7 +418,6 @@ ipcMain.handle(
},
)


ipcMain.handle('promptOpenFile', async (_event: unknown) => {
const toLocalPath = path.join(app.getPath('desktop'), defaultSessionName)
const choice = await dialog.showOpenDialog({
Expand Down
2 changes: 1 addition & 1 deletion products/jbrowse-desktop/src/JBrowse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AssemblyManager } from '@jbrowse/plugin-data-management'
import { RootModel } from './rootModel'

const JBrowse = observer(
({ pluginManager }: { pluginManager: PluginManager; }) => {
({ pluginManager }: { pluginManager: PluginManager }) => {
const { rootModel } = pluginManager

return rootModel ? (
Expand Down
12 changes: 5 additions & 7 deletions products/jbrowse-desktop/src/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { CssBaseline, ThemeProvider, makeStyles } from '@material-ui/core'
import { createJBrowseTheme } from '@jbrowse/core/ui'
import { StringParam, useQueryParam } from 'use-query-params'
import { ipcRenderer } from 'electron'
import { createPluginManager } from './StartScreen/util'
import { loadPluginManager } from './StartScreen/util'

import JBrowse from './JBrowse'
import StartScreen from './StartScreen'
Expand Down Expand Up @@ -77,10 +77,10 @@ const Loader = observer(() => {
// @ts-ignore
pm.rootModel?.setOpenNewSessionCallback(async () => {
const path = await ipcRenderer.invoke('promptOpenFile')
const data = await ipcRenderer.invoke('loadSession', path)
const pm = await createPluginManager(data)
handleSetPluginManager(pm)
handleSetPluginManager(await loadPluginManager(path))
})

// @ts-ignore
setPluginManager(pm)
setError(undefined)
setSnapshotError('')
Expand All @@ -93,9 +93,7 @@ const Loader = observer(() => {
;(async () => {
if (config) {
try {
const data = await ipcRenderer.invoke('loadSession', config)
const pm = await createPluginManager(data)
handleSetPluginManager(pm)
handleSetPluginManager(await loadPluginManager(config))
} catch (e) {
handleError(e)
}
Expand Down
18 changes: 11 additions & 7 deletions products/jbrowse-desktop/src/StartScreen/LauncherPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState } from 'react'
import { Button, Typography, makeStyles } from '@material-ui/core'
import PluginManager from '@jbrowse/core/PluginManager'
import { ipcRenderer } from 'electron'
import QuickstartPanel from './QuickstartPanel'
import OpenSequenceDialog from '../OpenSequenceDialog'
import { createPluginManager } from './util'
import { loadPluginManager } from './util'

const useStyles = makeStyles(theme => ({
form: {
Expand Down Expand Up @@ -50,13 +51,16 @@ export default function StartScreenOptionsPanel({
if (conf) {
// note this can throw before dialog closes, but this is handled
// by the dialog itself
const pm = await createPluginManager({
assemblies: [conf],
defaultSession: {
name: 'New Session ' + new Date().toLocaleString('en-US'),
const path = await ipcRenderer.invoke(
'createInitialAutosaveFile',
{
assemblies: [conf],
defaultSession: {
name: 'New Session ' + new Date().toLocaleString('en-US'),
},
},
})
setPluginManager(pm)
)
setPluginManager(await loadPluginManager(path))
}
setSequenceDialogOpen(false)
}}
Expand Down
13 changes: 8 additions & 5 deletions products/jbrowse-desktop/src/StartScreen/QuickstartPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { ipcRenderer } from 'electron'
import deepmerge from 'deepmerge'

// locals
import { createPluginManager } from './util'
import { loadPluginManager } from './util'

const useStyles = makeStyles(theme => ({
button: {
Expand All @@ -43,7 +43,7 @@ const useStyles = makeStyles(theme => ({
},
}))

function PreloadedDatasetSelector({
function QuickstartPanel({
setPluginManager,
}: {
setPluginManager: (arg0: PluginManager) => void
Expand Down Expand Up @@ -111,8 +111,11 @@ function PreloadedDatasetSelector({
config.defaultSession.name = `New session ${new Date().toLocaleString(
'en-US',
)}`
const pm = await createPluginManager(config)
setPluginManager(pm)
const path = await ipcRenderer.invoke(
'createInitialAutosaveFile',
config,
)
setPluginManager(await loadPluginManager(path))
}}
variant="contained"
color="primary"
Expand Down Expand Up @@ -211,4 +214,4 @@ function PreloadedDatasetSelector({
)
}

export default PreloadedDatasetSelector
export default QuickstartPanel
38 changes: 26 additions & 12 deletions products/jbrowse-desktop/src/StartScreen/RecentSessionsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useState, useEffect, useMemo } from 'react'
import {
Checkbox,
CircularProgress,
FormControl,
FormControlLabel,
Grid,
IconButton,
Link,
Expand Down Expand Up @@ -29,7 +31,7 @@ import PlaylistAddIcon from '@material-ui/icons/PlaylistAdd'
// locals
import RenameSessionDialog from './dialogs/RenameSessionDialog'
import DeleteSessionDialog from './dialogs/DeleteSessionDialog'
import { useLocalStorage, createPluginManager } from './util'
import { useLocalStorage, loadPluginManager } from './util'
import SessionCard from './SessionCard'

const useStyles = makeStyles(theme => ({
Expand Down Expand Up @@ -99,12 +101,7 @@ function RecentSessionsList({
className={classes.pointer}
onClick={async () => {
try {
const data = await ipcRenderer.invoke(
'loadSession',
params.row.path,
)
const pm = await createPluginManager(data)
setPluginManager(pm)
setPluginManager(await loadPluginManager(params.row.path))
} catch (e) {
console.error(e)
setError(e)
Expand Down Expand Up @@ -197,9 +194,7 @@ function RecentSessionsCards({
sessionData={session}
onClick={async () => {
try {
const pm = await createPluginManager(
await ipcRenderer.invoke('loadSession', session.path),
)
const pm = await loadPluginManager(session.path)
setPluginManager(pm)
} catch (e) {
console.error(e)
Expand Down Expand Up @@ -242,6 +237,10 @@ export default function RecentSessionPanel({
const [updateSessionsList, setUpdateSessionsList] = useState(0)
const [selectedSessions, setSelectedSessions] = useState<RecentSessions>()
const [sessionsToDelete, setSessionsToDelete] = useState<RecentSessions>()
const [showAutosaves, setShowAutosaves] = useLocalStorage(
'showAutosaves',
'false',
)

const sortedSessions = useMemo(
() => sessions?.sort((a, b) => b.updated - a.updated),
Expand All @@ -251,14 +250,17 @@ export default function RecentSessionPanel({
useEffect(() => {
;(async () => {
try {
const sessions = await ipcRenderer.invoke('listSessions')
const sessions = await ipcRenderer.invoke(
'listSessions',
showAutosaves === 'true',
)
setSessions(sessions)
} catch (e) {
console.error(e)
setError(e)
}
})()
}, [setError, updateSessionsList])
}, [setError, updateSessionsList, showAutosaves])

if (!sessions) {
return (
Expand Down Expand Up @@ -338,6 +340,18 @@ export default function RecentSessionPanel({
</ToggleButtonGroup>
</FormControl>

<FormControlLabel
control={
<Checkbox
checked={showAutosaves === 'true'}
onChange={() =>
setShowAutosaves(showAutosaves === 'true' ? 'false' : 'true')
}
/>
}
label="Show autosaves"
/>

{sortedSessions.length ? (
displayMode === 'grid' ? (
<RecentSessionsCards
Expand Down
13 changes: 11 additions & 2 deletions products/jbrowse-desktop/src/StartScreen/util.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PluginManager from '@jbrowse/core/PluginManager'
import PluginLoader from '@jbrowse/core/PluginLoader'
import { readConfObject } from '@jbrowse/core/configuration'
import deepmerge from 'deepmerge'
import { ipcRenderer } from 'electron'

import JBrowseRootModelFactory from '../rootModel'
import corePlugins from '../corePlugins'
Expand Down Expand Up @@ -50,6 +51,14 @@ const defaultInternetAccounts = [
},
]

export async function loadPluginManager(filePath: string) {
const snap = await ipcRenderer.invoke('loadSession', filePath)
const pm = await createPluginManager(snap)
// @ts-ignore
pm.rootModel?.setSessionPath(filePath)
return pm
}

export async function createPluginManager(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
configSnapshot: any,
Expand Down Expand Up @@ -79,9 +88,9 @@ export async function createPluginManager(

const ids = jbrowse.internetAccounts.map(o => o.internetAccountId)

// remove duplicates while mixing in default internet accounts
jbrowse.internetAccounts = jbrowse.internetAccounts.filter(
({ internetAccountId }, index) =>
!ids.includes(internetAccountId, index + 1),
(arg, index) => !ids.includes(arg.internetAccountId, index + 1),
)

const rootModel = JBrowseRootModel.create(
Expand Down
15 changes: 11 additions & 4 deletions products/jbrowse-desktop/src/rootModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ export default function rootModelFactory(pluginManager: PluginManager) {
.volatile(() => ({
error: undefined as unknown,
textSearchManager: new TextSearchManager(pluginManager),
openNewSessionCallback: () => { console.error('openNewSessionCallback unimplemented') }
openNewSessionCallback: () => {
console.error('openNewSessionCallback unimplemented')
},
}))
.actions(self => ({
async saveSession(val: unknown) {
Expand Down Expand Up @@ -237,7 +239,7 @@ export default function rootModelFactory(pluginManager: PluginManager) {
onClick: async () => {
try {
await self.openNewSessionCallback()
} catch(e) {
} catch (e) {
console.error(e)
self.session?.notify(`${e}`, 'error')
}
Expand Down Expand Up @@ -392,8 +394,13 @@ export default function rootModelFactory(pluginManager: PluginManager) {
}

const url = window.location.href.split('?')[0]
const name = self.session?.name || ''
window.location.href = `${url}?config=${encodeURIComponent(name)}`
if (!self.sessionPath) {
self.session?.notify('You must save your session first')
} else {
window.location.href = `${url}?config=${encodeURIComponent(
self.sessionPath,
)}`
}
},
/**
* Add a top-level menu
Expand Down

0 comments on commit 204743a

Please sign in to comment.