Wip Ipfsdocs Lots of Thumbs With Img With Alpine
Fleeting
open
root
js main state
document.addEventListener('alpine:init', () => {
Alpine.data('app', () => (
{
[[wip_ipfsdocs_slider_alpinejs.org:gun-js-code-ex()]]
[[wip_ipfsdocs_slider_alpinejs.org:effect-ex()]]
size_index: 24, // 20
sizes: [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7.5, 8, 8.5, 9.5, 10, 10.5, 11.5, 12, 14, 16, 20, 20.5, 22, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 64.5, 72, 72.5, 80, 80.5, 96, 96.5],
async init() {
this.gun.init()
await this.get_tags()
faro_init('thumbs')
},
selection: [],
}
));
})
doc
<div
x-data="{click_date: 0, get selected() { return selection.includes(doc.cid) }, get multiselected() { return multiselection.includes(doc.cid) }}"
class="w-40 h-40"
:class="{'border-2': selected, 'bg-green-500': selected, 'bg-purple-500': multiselected}"
@contextmenu.stop.prevent="show_context_modal = true ; context_modal_doc = doc ;"
@click="
if(new Date() - click_date < 500)
{
multiselection = add_or_remove(multiselection, doc.cid)
selection = add_maybe(selection, doc.cid)
}
else
{
selection = add_or_remove(selection, doc.cid)
}
click_date = new Date()
"
>
<div class="h-5/6 p-1">
<template x-if="doc.class === 'photo'">
<div>
<img
x-data="{failed: false, inview: false}"
@error="failed = true"
:class="{'bg-red': failed,}"
class="w-full h-full object-contain border-green-500"
x-effect.src-when-in-view="if(inview){$el.src = doc.thumbnail_cid}else{$el.src = 'https://imgs.search.brave.com/dFxiYCEW58PS8jxeHTWTmQyMDG4_APgTUviyG0TQe1k/rs:fit:500:0:0/g:ce/aHR0cHM6Ly9tZWRp/YTEuZ2lwaHkuY29t/L21lZGlhL3YxLlky/bGtQVGM1TUdJM05q/RXhkWEZsZHpacGVu/QjJObW8wT1hKMGRX/NDJhM2hsYUdVNE56/aHlkWEZzTW1GMmNX/TnhibTFzYUNabGNE/MTJNVjluYVdaelgz/TmxZWEpqYUNaamRE/MW4vM29Fakk2U0lJ/SEJkUnhYSTQwL2dp/cGh5LmdpZg.jpeg'}"
x-intersect.margin.1000px="inview = true;"
x-intersect:leave="inview = false;"
/>
</div>
</template>
<template x-if="doc.class === 'video'">
<div
x-data="{
id:$id(),
controller: null,
get selected() {
return selection.includes(doc.cid)
},
get multiselected() {
return multiselection.includes(doc.cid) }
}"
class="w-full h-full"
>
<div
class="w-full h-full relative"
x-intersect:leave="if(controller) {controller.pause()}"
@controllercreated="$nextTick(() => {controller.play()})"
>
<video
x-data="{visible: false}"
class="video-js w-full h-full bg-transparent"
:id="id"
preload="none"
x-intersect.margin.1000px="visible=true;$el.poster = doc.thumbnail_cid"
x-intersect:leave="visible=false;$el.poster = 'https://imgs.search.brave.com/dFxiYCEW58PS8jxeHTWTmQyMDG4_APgTUviyG0TQe1k/rs:fit:500:0:0/g:ce/aHR0cHM6Ly9tZWRp/YTEuZ2lwaHkuY29t/L21lZGlhL3YxLlky/bGtQVGM1TUdJM05q/RXhkWEZsZHpacGVu/QjJObW8wT1hKMGRX/NDJhM2hsYUdVNE56/aHlkWEZzTW1GMmNX/TnhibTFzYUNabGNE/MTJNVjluYVdaelgz/TmxZWEpqYUNaamRE/MW4vM29Fakk2U0lJ/SEJkUnhYSTQwL2dp/cGh5LmdpZg.jpeg'"
>
<source
:src="(visible && doc) ? doc.web_cid : ''"
type="video/webm"
>
</video>
<div
class="absolute inset-0 flex items-center justify-center"
x-show="! controller"
>
<img
class="w-1/2 h-1/2"
@click.stop="
controller = videojs(id, {
controls: true,
autoplay: false,
preload: 'none',
fill: true,
//fluid: true,
})
$dispatch('controllercreated')
"
src="https://ipfs.konubinix.eu/p/bafybeidjwfa6sz3dj6qgdddnprqrdcnceet6pxggqrpctpnno32nem6qz4?filename=9TRR9bj8c.png"
/>
</div>
</div>
</div>
</template>
</div>
<div class="h-1/6 text-xs">
<template x-if="doc.metadata && doc.metadata.length > 0" x-for="metadata in doc.metadata">
<div x-text="metadata['key'] + ': ' + metadata['value']"></div>
</template>
</div>
</div>
tools
<div id="tools">
<button class="m-2 rounded bg-blue-300 p-2" @click="fetch_docs">
fetch docs
</button>
<button class="m-2 rounded bg-blue-300 p-2" @click="selection = []">
clear
</button>
<button class="m-2 rounded bg-blue-300 p-2" @click="selection = alldocs.map((doc) => doc.cid)">
select all
</button>
<div>
Channel: <input x-model="channel"/>
</div>
<hr class="m-1"></hr>
<template x-if="metadata">
<div x-data="{
cur_tag: {
key: Alpine.$persist([]).as('cur_tag_key'),
value: Alpine.$persist([]).as('cur_tag_value'),
},
}"
>
Filter:
<select x-effect="await $nextTick() ; $el.value = cur_tag.key"
@change="
cur_tag.key = $el.value
cur_tag.value = [...metadata[$el.value]].sort()[0]
">
<template x-for="key in [...Object.keys(metadata)].sort()">
<option :value="key" x-text="key"></option>
</template>
</select>
<select x-effect="await $nextTick() ; $el.value = cur_tag.value"
@change="cur_tag.value = $el.value">
<template x-for="value in [...metadata[cur_tag.key]].sort()">
<option :value="value" x-text="value"></option>
</template>
</select>
<button class="m-2 rounded bg-blue-300 p-2" x-show="selection.length !== 0" @click="await apply_tag(selection, cur_tag.key, cur_tag.value) ; await fetch_docs() ; info(`added ${cur_tag.key}: ${cur_tag.value}`)">apply</button>
<button class="m-2 rounded bg-blue-300 p-2" x-show="selection.length !== 0" @click="await remove_tag(selection, cur_tag.key, cur_tag.value) ; await fetch_docs() ; info(`removed ${cur_tag.key}: ${cur_tag.value}`)">remove</button>
<div>
<div x-text="JSON.stringify(filter_in)"></div>
<button class="m-2 rounded bg-blue-300 p-2" @click="filter_in = [] ; await fetch_docs()">clean</button>
<button class="m-2 rounded bg-blue-300 p-2" @click="filter_in = filter_in.concat([{key: cur_tag.key, value: cur_tag.value}]) ; await fetch_docs()">add</button>
</div>
</div>
</template>
<hr class="m-1"></hr>
<div>
Move
<div x-data="{value: $persist('todo')}">
<select x-ref="wanted_state" x-model="value">
<option value="todo">todo</option>
<option value="next">next</option>
<option value="done">done</option>
<option value="delete">delete</option>
</select>
<button class="m-2 rounded bg-blue-300 p-2" @click="await move_to_state(selection, value) ; await fetch_docs() ; info(`moved to ${value}`)">move</button>
</div>
</div>
<hr class="m-1"></hr>
<button :disabled="selection.length === 0" :class="{'opacity-50': selection.length === 0}" class="m-2 rounded bg-blue-300 p-2"
@click='
alert("This wont work because I would need cors access to the api")
const response = await fetch("http://192.168.2.5:5002/api/v0/add", {method: "POST", body: JSON.stringify(selection)})
window.response = response
'
>Share</button>
<hr class="m-1"></hr>
<a class="m-2 mt-4 rounded bg-blue-300 p-2" href="/slider/">slides</a>
<div x-text="message"></div>
</div>
context
<template x-if="true">
<div
class="fixed inset-0 z-30 flex items-center justify-center overflow-auto bg-white text-black bg-opacity-80"
x-show="show_context_modal"
@click="show_context_modal = false ; context_modal_doc = null ;"
x-transition:enter="motion-safe:ease-out duration-300"
x-transition:enter-start="opacity-0 scale-90"
x-transition:enter-end="opacity-100 scale-100"
>
<div x-show="context_modal_doc === null && selection.length !== 0">
<div>
<span class="bg-white rounded">Selected <span x-text="selection.length"></span> images</span>
</div>
</div>
<div x-show="context_modal_doc !== null">
<div>
<template x-if="context_modal_doc && (context_modal_doc.class === 'photo')">
<img x-data="{loaded: false, inerror: false, load_timer: null}"
class="w-full h-screen object-contain"
:class="{'border-4':!loaded, 'border-blue-900': !inerror && !loaded, 'border-red-500': error}"
:src="context_modal_doc ? context_modal_doc.web_cid : null"
@load="loaded = true
if(load_timer){
clearTimeout(load_timer)
load_timer = null
}
"
@error="inerror = true"
x-init.timeout-load-on-src-change="effect('context_modal_doc', () => {
loaded = false
inerror = false
if(load_timer){
clearTimeout(load_timer)
load_timer = null
}
load_timer = setTimeout(() => {inerror = true}, 10000)
})"
>
</template>
<template x-if="context_modal_doc && (context_modal_doc.class === 'video')">
<div
x-data="{
id: `modal-web-cid`,
controller: null,
playing: false,
ended: false,
}"
class="relative w-full h-screen"
>
<div
class="w-full h-full relative"
>
<video
x-data="{visible: false}"
class="w-full h-full object-contain"
controls
:id="id"
@pause="playing = false"
@ended="playing = false ; ended = true"
@play="playing = true"
>
<source
:src="context_modal_doc ? context_modal_doc.web_cid : ''"
type="video/webm"
>
</video>
<div
x-show="context_modal_doc && ! playing"
class="absolute inset-0 flex items-center justify-center"
>
<img
class="w-1/2 h-1/2"
@click.stop="document.getElementById(id).play(); alert('test')"
src="https://ipfs.konubinix.eu/p/bafybeidjwfa6sz3dj6qgdddnprqrdcnceet6pxggqrpctpnno32nem6qz4?filename=9TRR9bj8c.png"
/>
</div>
</div>
</div>
</template>
</div>
</div>
<div x-show="selection.length === 0 && context_modal_doc === null">
<div>
<span class="bg-white rounded">I should do something now, but what?</span>
</div>
</div>
</div>
</template>
manifest
{
"name": "ipfsdoc",
"short_name": "ipfsdoc",
"description": "ipfsdoc",
"start_url": "./index.html",
"display": "fullscreen",
"background_color": "#ffffff",
"theme_color": "#4285f4",
"icons": [
{
"src": "./icons/icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "./icons/icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"prefer_related_applications": false,
"scope": "./",
"permissions": [],
"splash_pages": null,
"categories": []
}