forked from nostr/nostrweb
view: separate view logic from template code
moved code that creates the view dom elements into its own module. deliberately not in ui.ts as view.ts is imported early and has almost no dependecies except for nostr-tools and ./utils
parent
5039b3dece
commit
da3c1b02b2
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
import {nip19} from 'nostr-tools';
|
||||||
|
import {elem} from './utils/dom';
|
||||||
|
|
||||||
|
export type DOMMap = {
|
||||||
|
[id: string]: HTMLElement
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ViewTemplateOptions = {
|
||||||
|
type: 'feed'
|
||||||
|
} | {
|
||||||
|
type: 'note';
|
||||||
|
id: string;
|
||||||
|
} | {
|
||||||
|
type: 'profile';
|
||||||
|
id: string;
|
||||||
|
} | {
|
||||||
|
type: 'event';
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const renderViewTemplate = (options: ViewTemplateOptions) => {
|
||||||
|
const content = elem('div', {className: 'content'});
|
||||||
|
const dom: DOMMap = {};
|
||||||
|
switch (options.type) {
|
||||||
|
case 'profile':
|
||||||
|
const pubkey = options.id;
|
||||||
|
const detail = elem('p', {data: {'profileDetails': pubkey}});
|
||||||
|
dom[`detail-${pubkey}`] = detail;
|
||||||
|
const header = elem('header', {className: 'hero'}, [
|
||||||
|
elem('small', {}, nip19.npubEncode(pubkey)),
|
||||||
|
elem('h1', {}, pubkey),
|
||||||
|
detail,
|
||||||
|
elem('footer', {}, [
|
||||||
|
elem('span', {data:{following: pubkey}})
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
dom[pubkey] = header;
|
||||||
|
content.append(header);
|
||||||
|
document.title = pubkey;
|
||||||
|
break;
|
||||||
|
case 'note':
|
||||||
|
break;
|
||||||
|
case 'feed':
|
||||||
|
break;
|
||||||
|
case 'event':
|
||||||
|
const id = options.id;
|
||||||
|
const eventHeader = elem('header', {className: 'hero'}, [
|
||||||
|
elem('h1', {}, id),
|
||||||
|
]);
|
||||||
|
dom[id] = eventHeader;
|
||||||
|
content.append(eventHeader);
|
||||||
|
document.title = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const view = elem('section', {className: 'view'}, [content]);
|
||||||
|
return {content, dom, view};
|
||||||
|
};
|
72
src/view.ts
72
src/view.ts
|
@ -1,26 +1,8 @@
|
||||||
import {nip19} from 'nostr-tools';
|
import {DOMMap, renderViewTemplate, ViewTemplateOptions} from './template';
|
||||||
import {elem} from './utils/dom';
|
|
||||||
|
|
||||||
type ViewOptions = {
|
|
||||||
type: 'feed'
|
|
||||||
} | {
|
|
||||||
type: 'note';
|
|
||||||
id: string;
|
|
||||||
} | {
|
|
||||||
type: 'profile';
|
|
||||||
id: string;
|
|
||||||
} | {
|
|
||||||
type: 'event';
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type DOMMap = {
|
|
||||||
[id: string]: HTMLElement
|
|
||||||
};
|
|
||||||
|
|
||||||
type Container = {
|
type Container = {
|
||||||
id: string;
|
id: string;
|
||||||
options: ViewOptions,
|
options: ViewTemplateOptions,
|
||||||
view: HTMLElement;
|
view: HTMLElement;
|
||||||
content: HTMLDivElement;
|
content: HTMLDivElement;
|
||||||
dom: DOMMap;
|
dom: DOMMap;
|
||||||
|
@ -53,62 +35,28 @@ export const setViewElem = (id: string, node: HTMLElement) => {
|
||||||
|
|
||||||
const mainContainer = document.querySelector('main') as HTMLElement;
|
const mainContainer = document.querySelector('main') as HTMLElement;
|
||||||
|
|
||||||
const renderView = (options: ViewOptions) => {
|
|
||||||
const content = elem('div', {className: 'content'});
|
|
||||||
const dom: DOMMap = {};
|
|
||||||
switch (options.type) {
|
|
||||||
case 'profile':
|
|
||||||
const pubkey = options.id;
|
|
||||||
const detail = elem('p', {data: {'profileDetails': pubkey}});
|
|
||||||
dom[`detail-${pubkey}`] = detail;
|
|
||||||
const header = elem('header', {className: 'hero'}, [
|
|
||||||
elem('small', {}, nip19.npubEncode(pubkey)),
|
|
||||||
elem('h1', {}, pubkey),
|
|
||||||
detail,
|
|
||||||
elem('footer', {}, [
|
|
||||||
elem('span', {data:{following: pubkey}})
|
|
||||||
])
|
|
||||||
]);
|
|
||||||
dom[pubkey] = header;
|
|
||||||
content.append(header);
|
|
||||||
document.title = pubkey;
|
|
||||||
break;
|
|
||||||
case 'note':
|
|
||||||
break;
|
|
||||||
case 'feed':
|
|
||||||
break;
|
|
||||||
case 'event':
|
|
||||||
const id = options.id;
|
|
||||||
const eventHeader = elem('header', {className: 'hero'}, [
|
|
||||||
elem('h1', {}, id),
|
|
||||||
]);
|
|
||||||
dom[id] = eventHeader;
|
|
||||||
content.append(eventHeader);
|
|
||||||
document.title = id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const view = elem('section', {className: 'view'}, [content]);
|
|
||||||
return {content, dom, view};
|
|
||||||
};
|
|
||||||
|
|
||||||
const createContainer = (
|
const createContainer = (
|
||||||
route: string,
|
route: string,
|
||||||
options: ViewOptions,
|
options: ViewTemplateOptions,
|
||||||
) => {
|
) => {
|
||||||
const {content, dom, view} = renderView(options);
|
const {content, dom, view} = renderViewTemplate(options);
|
||||||
const container = {id: route, options, view, content, dom};
|
const container = {id: route, options, view, content, dom};
|
||||||
mainContainer.append(view);
|
mainContainer.append(view);
|
||||||
containers.push(container);
|
containers.push(container);
|
||||||
return container;
|
return container;
|
||||||
};
|
};
|
||||||
|
|
||||||
type GetViewOptions = () => ViewOptions;
|
type GetViewOptions = () => ViewTemplateOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get options for current view
|
||||||
|
* @returns {id: 'feed' | 'profile' | 'note' | 'event', id?: string}
|
||||||
|
*/
|
||||||
export const getViewOptions: GetViewOptions = () => containers[activeContainerIndex]?.options || {type: 'feed'};
|
export const getViewOptions: GetViewOptions = () => containers[activeContainerIndex]?.options || {type: 'feed'};
|
||||||
|
|
||||||
export const view = (
|
export const view = (
|
||||||
route: string,
|
route: string,
|
||||||
options: ViewOptions,
|
options: ViewTemplateOptions,
|
||||||
) => {
|
) => {
|
||||||
const active = containers[activeContainerIndex];
|
const active = containers[activeContainerIndex];
|
||||||
const nextContainer = containers.find(c => c.id === route) || createContainer(route, options);
|
const nextContainer = containers.find(c => c.id === route) || createContainer(route, options);
|
||||||
|
|
Loading…
Reference in New Issue