Konubinix' opinionated web of thoughts

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": []
}