Skip to content

Commit

Permalink
+++
Browse files Browse the repository at this point in the history
  • Loading branch information
Offirmo committed May 2, 2024
1 parent a510e7f commit 9e0b28e
Show file tree
Hide file tree
Showing 17 changed files with 123 additions and 160 deletions.
2 changes: 1 addition & 1 deletion stack--2022/4-tools/storypad/doc/demo/storypad.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

startꓽstorypad(
{
demo: storiesⵧdemo,
//demo: storiesⵧdemo,
shared: storiesⵧshared,
},
{
Expand Down
37 changes: 15 additions & 22 deletions stack--2022/4-tools/storypad/src/flux/dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,37 @@ import { Immutable } from '@offirmo-private/ts-types'

import { ImportGlob } from '../types/glob'
import { Config } from '../types/config'
import { StoryUId} from './types'
import * as InMemState from './state--in-mem'
import * as UrlState from './state--url'

/////////////////////////////////////////////////

let state: InMemState.State = null as any
let stateⵧin_mem: InMemState.State = InMemState.create()

async function init(stories_glob: Immutable<ImportGlob>, config?: Immutable<Config>): Promise<void> {
state = InMemState.create()
console.group('Flux init...')
stateⵧin_mem = InMemState.setꓽconfig(stateⵧin_mem, config)
stateⵧin_mem = await InMemState.registerꓽstoriesⵧfrom_glob(stateⵧin_mem, stories_glob)

state = InMemState.setꓽconfig(state, config)
UrlState.init()

state = await InMemState.registerꓽstoriesⵧfrom_glob(state, stories_glob)
// other states don't need an init

//state = enrich_state_from_local_storage(state)
//state = enrich_state_from_query_parameters(state)
//state = enrich_state_from_env(state)

console.log('final state =', state)
console.log('final stateⵧin_mem =', stateⵧin_mem)
console.groupEnd()
}

// explicit request on user's click
function requestꓽstory(uid: InMemState.StoryUId) {
state = InMemState.activateꓽstory(state, uid)
// TODO propagate to url state!

//throw new Error('NIMP propagate on activateꓽstory() !')
/*try {
localStorage.setItem(LS_KEYS.current_story_uid, (new URL(href)).searchParams.get(MAIN_IFRAME_QUERYPARAMS.story_uid))
}
catch {
// ignore
}*/
function requestꓽstory(uid: StoryUId) {
stateⵧin_mem = InMemState.requestꓽstory(stateⵧin_mem, uid)
UrlState.requestꓽstory(uid)
}

// DO NOT USE, only for the flux selectors
function _getꓽstateⵧin_mem(): Immutable<InMemState.State> {
assert(state, `init() must be called first!`)
return state
assert(stateⵧin_mem, `init() must be called first!`)
return stateⵧin_mem
}

/////////////////////////////////////////////////
Expand Down
17 changes: 5 additions & 12 deletions stack--2022/4-tools/storypad/src/flux/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import { Immutable } from '@offirmo-private/ts-types'
import { Config } from '../types/config'
import { _getꓽstateⵧin_mem } from './dispatcher'

import { State, FolderUId, StoryEntry, StoryUId, RenderMode } from './types'
import { FolderUId, StoryEntry, RenderMode, StoryTree } from './types'

import * as InMemStateSelectors from './state--in-mem/selectors'
import * as EnvStateSelectors from './state--env/selectors'
import * as UrlStateSelectors from './state--url/selectors'
import { RenderParams } from '../types/csf/common'
import { RenderParams } from '../types/csf'

/////////////////////////////////////////////////

// for rendering the stories tree
function getꓽtree_root(): Immutable<State['tree']> {
function getꓽtree_root(): Immutable<StoryTree> {
return _getꓽstateⵧin_mem().tree
}

Expand Down Expand Up @@ -49,8 +49,7 @@ function getꓽrender_mode(): RenderMode {
return 'full'
}

// for rendering the story
// must only return "undef" if NO stories. Else should pick the 1st one.
// must only return "undef" if NO stories
function getꓽstoryⵧcurrent(): Immutable<StoryEntry> | undefined {
const state = _getꓽstateⵧin_mem()

Expand All @@ -61,15 +60,10 @@ function getꓽstoryⵧcurrent(): Immutable<StoryEntry> | undefined {
return candidate
}

return InMemStateSelectors.getꓽstoryⵧcurrent(state)
return InMemStateSelectors.getꓽstoryⵧsuggested(state)
}


function getꓽstoryⵧexplicitely_requested‿uid(): StoryUId | undefined {
const state = _getꓽstateⵧin_mem()
return state.last_explicitly_activated_story‿uid
}

const getꓽmain_frame_url = UrlStateSelectors.getꓽmain_frame_url
const getꓽstory_frame_url = UrlStateSelectors.getꓽstory_frame_url

Expand All @@ -90,7 +84,6 @@ export {

getꓽrender_mode,
getꓽstoryⵧcurrent,
getꓽstoryⵧexplicitely_requested‿uid,
getꓽRenderParamsⵧglobal,

getꓽmain_frame_url,
Expand Down
5 changes: 5 additions & 0 deletions stack--2022/4-tools/storypad/src/flux/state--env/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

/////////////////////////////////////////////////

console.log('installing popstate listener')
addEventListener("popstate", (event) => {
console.log('Seen popstate!', event)
});

function isꓽiframe():boolean {
return window.location !== window.parent.location
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import {
ImportModule, isꓽImportModule,
} from '../../types/glob'

import {
StoryEntry, isꓽStoryEntry,
State,
} from './types'
import { StoryEntry, isꓽStoryEntry } from '../types'
import { State } from './types'
import { registerꓽstory } from './reducers'

/////////////////////////////////////////////////

const SEP = '/' // Ⳇ
const SEP = '/'

/////////////////////////////////////////////////

Expand Down
54 changes: 8 additions & 46 deletions stack--2022/4-tools/storypad/src/flux/state--in-mem/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import assert from 'tiny-invariant'
import { Immutable, RelativePath } from '@offirmo-private/ts-types'
import { FileSystemNode, createꓽfilesystem, insertꓽfile } from '@offirmo-private/data-structures'
import { createꓽfilesystem, insertꓽfile } from '@offirmo-private/data-structures'

import {
Config,
} from '../../types/config'

import {
StoryUId,
StoryEntry,
State,
StoryFolder,
} from './types'
import { Config } from '../../types/config'
import { StoryUId, StoryEntry, StoryFolder } from '../types'
import { State } from './types'

////////////////////////////////////////////////////////////////////////////////////
// init
Expand All @@ -21,9 +14,6 @@ function create(): State {
root_title: 'Stories',
decorators: [],
},
//stories_by_uid: {},
//folders_by_uid: {},
last_explicitly_activated_story‿uid: undefined,
first_encountered_story‿uid: undefined,
tree: createꓽfilesystem<StoryEntry, StoryFolder>(),
}
Expand All @@ -49,23 +39,17 @@ function registerꓽstory(state: State, story: StoryEntry, path: RelativePath):
return {
...state,
first_encountered_story‿uid: state.first_encountered_story‿uid || uid,
/*stories_by_uid: {
...state.stories_by_uid,
[uid]: {
...story,
uid,
},
},*/
}
}

/////////////////////////////////////////////////

function activateꓽstory(state: State, uid: StoryUId): State {
// TODO clarify
function requestꓽstory(state: State, uid: StoryUId): State {
//assert(getꓽstoryⵧby_uid(state, uid), `story should exist! "${uid}"`)
state = {
...state,
last_explicitly_activated_story‿uid: uid,
//last_explicitly_activated_story‿uid: uid,
}

state = folderⵧexpand(state, uid)
Expand All @@ -78,27 +62,6 @@ function activateꓽstory(state: State, uid: StoryUId): State {
// id can be story or folder, don't mind
function folderⵧexpand(state: State, uid: StoryUId): State {
console.warn('TODO folderⵧexpand')
/*
const path = id.split(SEP_FOR_IDS)
// in-place mutation SORRY TODO fix?
let folder: StoryFolder = state.folders_by_uid[ROOT_ID]! as any
do {
console.log('expanding', { path: structuredClone(path), folder })
const segment = path.shift()!
folder = folder.children[segment]! as StoryFolder
assert(folder, 'next segment is present')
if (isꓽStoryEntry(folder)) {
assert(path.length === 0, 'last segment is story')
}
else {
assert(Object.hasOwn(folder, 'isꓽexpandedⵧinitially'))
folder.isꓽexpandedⵧinitially = true
}
} while(path.length)
return state*/
return state
}

Expand All @@ -108,7 +71,6 @@ export {
create,
setꓽconfig,
registerꓽstory,
//registerꓽfolder,

activateꓽstory,
requestꓽstory,
}
17 changes: 6 additions & 11 deletions stack--2022/4-tools/storypad/src/flux/state--in-mem/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ import assert from 'tiny-invariant'
import { Immutable } from '@offirmo-private/ts-types'
import { getꓽnodeⵧby_pathⵧensure_file } from '@offirmo-private/data-structures'

import {
State,
StoryUId,
StoryEntry,
StoryFolder,
} from './types'
import { StoryUId, StoryEntry, StoryFolder } from '../types'
import { State } from './types'

/////////////////////////////////////////////////

Expand All @@ -19,12 +15,11 @@ function getꓽstoryⵧby_uid(state: Immutable<State>, uid: StoryUId): Immutable
return node.payload
}

//function getꓽstoryⵧcurrent‿uid(state: Immutable<State>): StoryUId | '[NO-KNOWN-STORIES]' {
function getꓽstoryⵧcurrent(state: Immutable<State>): Immutable<StoryEntry> | undefined {
// if no explicit story is requested,
// suggest one from the known stories
function getꓽstoryⵧsuggested(state: Immutable<State>): Immutable<StoryEntry> | undefined {
let candidate: Immutable<StoryEntry> | undefined = undefined

candidate = state.last_explicitly_activated_story‿uid ? getꓽstoryⵧby_uid(state, state.last_explicitly_activated_story‿uid) : undefined

if (!candidate) {
candidate = state.first_encountered_story‿uid ? getꓽstoryⵧby_uid(state, state.first_encountered_story‿uid) : undefined
}
Expand All @@ -36,5 +31,5 @@ function getꓽstoryⵧcurrent(state: Immutable<State>): Immutable<StoryEntry> |

export {
getꓽstoryⵧby_uid,
getꓽstoryⵧcurrent,
getꓽstoryⵧsuggested,
}
40 changes: 4 additions & 36 deletions stack--2022/4-tools/storypad/src/flux/state--in-mem/types.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,13 @@
import { FileSystemNodeⳇFolder } from '@offirmo-private/data-structures'
import { Config } from '../../types/config'
import {
Story, isꓽStory,
Meta,
} from '../../types/csf'

/////////////////////////////////////////////////

export type StoryUId = string
export type FolderUId = string

export interface StoryEntry {
uid: StoryUId // for convenience when passing the payload around

story: Story

meta: Meta | undefined
}
export function isꓽStoryEntry(x: any): x is StoryEntry {
return isꓽStory(x?.story)
}

export interface StoryFolder {
uid: FolderUId // for convenience when passing the payload around

isꓽexpandedⵧinitially: boolean
}
export function isꓽStoryFolder(x: any): x is StoryFolder {
return !isꓽStoryEntry(x) // simple for now ;)
}
import { Config } from '../../types/config'
import { StoryUId, StoryTree } from '../types'

/////////////////////////////////////////////////

export interface State {
config: Config
/*
stories_by_uid: { [k: StoryUId]: StoryEntry }
folders_by_uid: { [k: FolderUId]: StoryFolder }
*/
last_explicitly_activated_story‿uid: StoryUId | undefined

first_encountered_story‿uid: StoryUId | undefined

tree: FileSystemNodeⳇFolder<StoryEntry, StoryFolder>
tree: StoryTree
}
3 changes: 0 additions & 3 deletions stack--2022/4-tools/storypad/src/flux/state--url/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,3 @@ export const QUERYPARAMS = {

// globals=theme:dark
}

//const SEP_FOR_UID = 'Ⳇ' // :
//const ROOT_ID = '╣ROOT╠'
3 changes: 3 additions & 0 deletions stack--2022/4-tools/storypad/src/flux/state--url/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './types'
export * from './selectors'
export * from './reducers'
25 changes: 22 additions & 3 deletions stack--2022/4-tools/storypad/src/flux/state--url/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,33 @@
import assert from 'tiny-invariant'
import { Immutable } from '@offirmo-private/ts-types'

import { StoryUId } from '../types'
import { getꓽmain_frame_url } from './selectors'
import { QUERYPARAMS } from './consts.ts'

/////////////////////////////////////////////////

function activateꓽstory(): void {
throw new Error('NIMP activateꓽstory() !')
function init(): void {
console.log('URL=', window.location.href)

const url‿obj = (new URL(window.location.href))
;[...url‿obj.searchParams.keys()]
.filter(k => Object.values(QUERYPARAMS).includes(k))
.forEach(k => {
console.log(`URL param "${k}" = "${url‿obj.searchParams.get(k)}" found!`)
})
}

function requestꓽstory(uid: StoryUId): void {
const new_url = getꓽmain_frame_url(uid)

history.pushState({}, '', new_url)
}

/////////////////////////////////////////////////

export {
activateꓽstory
init,

requestꓽstory,
}
Loading

0 comments on commit 9e0b28e

Please sign in to comment.