import type { SlInput } from '@shoelace-style/shoelace' import type { EntityID } from '@wovin/core' import type { Accessor, Component } from 'solid-js' import type { Provider } from '../../data/VMs/ProviderVM' import { urlFromHumanInput } from '@wovin/utils/browser' import { Logger } from 'besonders-logger' import classNames from 'classnames' import { Collapse } from 'solid-collapse' import { createMemo, createSignal, For, Show } from 'solid-js' import { useAgent } from '../../data/agent/AgentState' import { DefaultAgentBanner } from '../../data/agent/utils-agent' import { chooseFilesystemFolder, isFileSystemAPIavailable } from '../../data/filesystem-utils' import { useLocalStorage } from '../../data/utils-data' import { getVM, getVMs } from '../../data/VMs/MappedVMbase' import { ProviderVM } from '../../data/VMs/ProviderVM' import { DEMO_PROVIDER } from '../../ipfs/storage' import { useCurrentThread, useProviderIDs } from '../../ui/reactive' import { FlexBetween, Iconify } from '../mini-components' const { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG) // eslint-disable-line unused-imports/no-unused-vars export const StorageSettings: Component<{}> = () => { DEBUG('Creating ') // HACK used to render twice and sideEffects should only happen once if possible const thread = useCurrentThread() const [apiKey, setApiKey] = createSignal('') const [submitted, setSubmitted] = createSignal(false) const storageProviderIDs = useProviderIDs() const storageProviders = getVMs(ProviderVM, storageProviderIDs) // const hasPersistProvider = createMemo(() => hasProviderWithCap(storageProviders, 'persist')) const hasDemoProvider = createMemo(() => storageProviders.some(({ type, url }) => type === 'ucan-store-proxy' && url?.includes(DEMO_PROVIDER)), ) const agent = useAgent() const [infoMinimized, setInfoMinimized] = useLocalStorage('note3.settings.storage.info-minimized', false) return (
{/* */} {/* */}
setInfoMinimized(!infoMinimized())} > Info
{ /* Upload Download */ }

Storage Providers can offer different capabilities:

  • Access & Retrieval (IPFS)
  • Storing data (IFPS)
  • Storing state pointers (IPNS)
Find out about the different options here {' '} (from self-hosting to paid services)
Your storage provider(s)
new ObjectBuilder({ 'wovin/provider/type': 'ucan-store-proxy' })} />

If you just want to try, {' '} { e.preventDefault() const demoGW = storageProviders.find(({ type, url }) => type === 'ipfs-gateway' && url === DEMO_PROVIDER) if (demoGW) { demoGW.type = 'ucan-store-proxy' } else { ProviderVM.buildNew({ type: 'ucan-store-proxy', name: 'Note3 Demo Storage', url: DEMO_PROVIDER }).commit(thread) } }} > use our demo instance {' '} (might be offline or reset at any point)

{ /*

NFT.storage (deprecated & currently not usable)

Sign up for nft.storage & create an API key

setApiKey(e.target.value)} max-w-md />
Log in
{/* TODO setup a collapse tree here * /}
NFT.Storage UCAN:
{storageState.nftStorage.rootUcan ? JSON.stringify(storageState.nftStorage.rootUcan?.payload, undefined, 4) : 'Got API key, but not lazy-loaded yet'}
*/ }

web3.storage

(currently not usable because of {' '} infra changes {' '} we need to adapt to)

{/*
*/} { /*
Your Download Gateways {/* * /}
*/ } {/* */} {/* */}
Local Filesystem

All publications will additionally be stored in a chosen folder on your local filesystem. (fine-grained control {' '} planned )

{/* */} Choose Folder {/* */}

Selected folder: {' '} TODO

Note: in chromium < v122, {' '} you need to set some flags , otherwise permission will need to be asked for after closing all tabs.

FileSystem access is only available on chromium based browsers for now.

Check out the wovin issue about the situation.

{/*
*/} { /*
Test AppLog
*/ }
) } export const ProviderList: Component<{ ids: readonly EntityID[] // createBuilder: () => ObjectBuilder }> = (props) => { const thread = useCurrentThread() // const debouncedThread = debounceWrites(thread) let newUrlRef: SlInput let newTypeRef: SlInput const create = () => { const builder = ProviderVM.buildNew({ type: (newTypeRef.value as Provider['type']), url: urlFromHumanInput(newUrlRef.value) }) LOG(`Creating provider:`, builder) builder.commit(thread) newUrlRef.value = '' } const markDeleted = (en: EntityID) => { LOG(`Deleting provider:`, en) ProviderVM.get(en, thread).setDeleted() } return (
{(providerID) => { // const [provider, updateProvider] = withDS(debouncedThread, () => useEntityAttrs(en, ['url', 'type'] as const)) // createEffect(() => LOG(`provider logs`, query(debouncedThread, { en }).leafNodeLogs)) const provider = getVM(ProviderVM, providerID) LOG(`Provider`, providerID, provider) const onURLchange = (evt) => { LOG('onURLchange', { evt, val: evt.target.value }) provider.buildUpdate({ url: urlFromHumanInput(evt.target.value) }).commit(thread) } return (
{provider.type as string} {' '} {provider.name as string}
e.button === 0 && markDeleted(provider.en)}>
) }}
{ evt.preventDefault() create() }} > UCAN Store Proxy IPFS Gateway Add
) } export const OrderedStrings: Component<{ stringArray: Accessor, onAdd?: (string) => void }> = (props) => { return (
{(eachString: string, _nodeIdx) => { return }} props.onAdd(evt.target.value)} />
) }