mirror of
https://github.com/iptv-org/iptv-org.github.io.git
synced 2025-05-11 17:40:05 -04:00
wip
This commit is contained in:
parent
b6b65a727a
commit
09f6d12085
7 changed files with 113 additions and 136 deletions
|
@ -3,7 +3,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "NODE_OPTIONS='--max-old-space-size=4096' vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
const { open } = getContext('simple-modal')
|
const { open } = getContext('simple-modal')
|
||||||
const onOpened = () => {
|
const onOpened = () => {
|
||||||
currLocation = window.location.href
|
currLocation = window.location.href
|
||||||
window.history.pushState({}, `${channel.name} • iptv-org`, `/channel?id=${channel.id}`)
|
window.history.pushState({}, `${channel.name} • iptv-org`, `/channels/${channel.id}`)
|
||||||
}
|
}
|
||||||
const onClosed = () => {
|
const onClosed = () => {
|
||||||
window.history.pushState({}, `iptv-org`, currLocation || '/')
|
window.history.pushState({}, `iptv-org`, currLocation || '/')
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
<div class="flex space-x-2 items-center">
|
<div class="flex space-x-2 items-center">
|
||||||
<a
|
<a
|
||||||
on:click|preventDefault={showChannelData}
|
on:click|preventDefault={showChannelData}
|
||||||
href="/channel?id={channel.id}"
|
href="/channels/{channel.id}"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="font-normal text-gray-600 dark:text-white hover:underline hover:text-blue-500 line-clamp-1"
|
class="font-normal text-gray-600 dark:text-white hover:underline hover:text-blue-500 line-clamp-1"
|
||||||
title={channel.name}
|
title={channel.name}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import { query, hasQuery, channels, setSearchParam } from '~/store'
|
import { query, hasQuery, channels, setSearchParam } from '~/store'
|
||||||
|
|
||||||
export let data
|
export let data
|
||||||
export let close
|
export let close = () => {}
|
||||||
|
|
||||||
let replaced_by = null
|
let replaced_by = null
|
||||||
if (data.replaced_by) {
|
if (data.replaced_by) {
|
||||||
|
@ -100,64 +100,71 @@
|
||||||
<table class="table-fixed w-full">
|
<table class="table-fixed w-full">
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each fieldset as field}
|
{#each fieldset as field}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="align-top w-[11rem]">
|
<td class="align-top w-[11rem]">
|
||||||
<div class="flex pr-4 py-1 text-sm text-gray-400 whitespace-nowrap dark:text-gray-400">
|
<div class="flex pr-4 py-1 text-sm text-gray-400 whitespace-nowrap dark:text-gray-400">
|
||||||
{field.name}
|
{field.name}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="align-top">
|
<td class="align-top">
|
||||||
<div class="flex py-1 text-sm text-gray-700 dark:text-gray-100 flex-wrap">
|
<div class="flex py-1 text-sm text-gray-700 dark:text-gray-100 flex-wrap">
|
||||||
{#if field.type === 'image'}
|
{#if field.type === 'image'}
|
||||||
<img
|
<img
|
||||||
src="{field.value}"
|
src={field.value}
|
||||||
alt="{field.name}"
|
alt={field.name}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
referrerpolicy="no-referrer"
|
referrerpolicy="no-referrer"
|
||||||
class="border rounded-sm overflow-hidden border-gray-200 bg-[#e6e6e6]"
|
class="border rounded-sm overflow-hidden border-gray-200 bg-[#e6e6e6]"
|
||||||
/>
|
/>
|
||||||
{:else if field.type === 'link'}
|
{:else if field.type === 'link'}
|
||||||
<button
|
<button
|
||||||
on:click="{() => searchBy(field.value.query)}"
|
on:click={() => searchBy(field.value.query)}
|
||||||
class="underline hover:text-blue-500"
|
class="underline hover:text-blue-500"
|
||||||
>
|
|
||||||
{field.value.label}
|
|
||||||
</button>
|
|
||||||
{:else if field.type === 'link[]'} {#each field.value as value, i} {#if i > 0}<span
|
|
||||||
>,
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
<button on:click="{() => searchBy(value.query)}" class="underline hover:text-blue-500">
|
|
||||||
{value.label}
|
|
||||||
</button>
|
|
||||||
{/each} {:else if field.type === 'external_link'}
|
|
||||||
<a
|
|
||||||
href="{field.value}"
|
|
||||||
class="underline hover:text-blue-500 inline-flex align-middle"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>{field.value}<span
|
|
||||||
class="inline-flex items-center pl-1 text-sm font-semibold text-gray-400 rounded-full"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="w-4 h-4"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
>
|
||||||
<path
|
{field.value.label}
|
||||||
stroke-linecap="round"
|
</button>
|
||||||
stroke-linejoin="round"
|
{:else if field.type === 'link[]'}
|
||||||
stroke-width="2"
|
{#each field.value as value, i}
|
||||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
{#if i > 0}<span>, </span>
|
||||||
></path>
|
{/if}
|
||||||
</svg> </span
|
<button
|
||||||
></a>
|
on:click={() => searchBy(value.query)}
|
||||||
{:else} {field.value} {/if}
|
class="underline hover:text-blue-500"
|
||||||
</div>
|
>
|
||||||
</td>
|
{value.label}
|
||||||
</tr>
|
</button>
|
||||||
|
{/each}
|
||||||
|
{:else if field.type === 'external_link'}
|
||||||
|
<a
|
||||||
|
href={field.value}
|
||||||
|
class="underline hover:text-blue-500 inline-flex align-middle"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>{field.value}<span
|
||||||
|
class="inline-flex items-center pl-1 text-sm font-semibold text-gray-400 rounded-full"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="w-4 h-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</span></a
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
{field.value}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
24
src/pages/channels/[id]/+page.server.js
Normal file
24
src/pages/channels/[id]/+page.server.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
import { fetchChannels, channels } from '~/store'
|
||||||
|
import apiChannels from '~/data/channels.json'
|
||||||
|
|
||||||
|
export async function entries() {
|
||||||
|
return apiChannels
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function load({ params }) {
|
||||||
|
const id = params.id
|
||||||
|
|
||||||
|
await fetchChannels()
|
||||||
|
|
||||||
|
const channel = get(channels).find(c => c.id === id)
|
||||||
|
let streams = []
|
||||||
|
if (channel) {
|
||||||
|
streams = channel._streams
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
channel,
|
||||||
|
streams
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,27 +4,12 @@
|
||||||
import HTMLPreview from '~/components/HTMLPreview.svelte'
|
import HTMLPreview from '~/components/HTMLPreview.svelte'
|
||||||
import EditButton from '~/components/EditButton.svelte'
|
import EditButton from '~/components/EditButton.svelte'
|
||||||
import NavBar from '~/components/NavBar.svelte'
|
import NavBar from '~/components/NavBar.svelte'
|
||||||
import { onMount } from 'svelte'
|
|
||||||
import { fetchChannels, channels } from '~/store'
|
|
||||||
import { page } from '$app/stores'
|
|
||||||
|
|
||||||
let channel
|
export let data
|
||||||
let isLoading = true
|
|
||||||
let streams = []
|
|
||||||
let guides = []
|
|
||||||
|
|
||||||
onMount(async () => {
|
let isLoading = false
|
||||||
const id = $page.url.searchParams.get('id')
|
let channel = data.channel
|
||||||
if (id && !$channels.length) {
|
let streams = data.streams
|
||||||
await fetchChannels()
|
|
||||||
}
|
|
||||||
channel = $channels.find(c => c.id === id)
|
|
||||||
if (channel) {
|
|
||||||
streams = channel._streams
|
|
||||||
guides = channel._guides
|
|
||||||
}
|
|
||||||
isLoading = false
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
71
src/store.js
71
src/store.js
|
@ -2,14 +2,6 @@ import { writable, get } from 'svelte/store'
|
||||||
import { Playlist, Link } from 'iptv-playlist-generator'
|
import { Playlist, Link } from 'iptv-playlist-generator'
|
||||||
import sj from '@freearhey/search-js'
|
import sj from '@freearhey/search-js'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import api_channels from '~/data/channels.json'
|
|
||||||
import api_regions from '~/data/regions.json'
|
|
||||||
import api_countries from '~/data/countries.json'
|
|
||||||
import api_languages from '~/data/languages.json'
|
|
||||||
import api_streams from '~/data/streams.json'
|
|
||||||
import api_subdivisions from '~/data/subdivisions.json'
|
|
||||||
import api_blocklist from '~/data/blocklist.json'
|
|
||||||
import api_categories from '~/data/categories.json'
|
|
||||||
|
|
||||||
export const query = writable('')
|
export const query = writable('')
|
||||||
export const hasQuery = writable(false)
|
export const hasQuery = writable(false)
|
||||||
|
@ -112,33 +104,8 @@ export function setPageTitle(value) {
|
||||||
async function loadAPI() {
|
async function loadAPI() {
|
||||||
const api = {}
|
const api = {}
|
||||||
|
|
||||||
api.countries = _.keyBy(
|
api.countries = await import('~/data/countries.json')
|
||||||
api_countries.map(i => {
|
.then(m => m.default)
|
||||||
i.expanded = false
|
|
||||||
return i
|
|
||||||
}),
|
|
||||||
'code'
|
|
||||||
)
|
|
||||||
|
|
||||||
api.regions = _.keyBy(api_regions, 'code')
|
|
||||||
api.subdivisions = _.keyBy(api_subdivisions, 'code')
|
|
||||||
api.languages = _.keyBy(api_languages, 'code')
|
|
||||||
api.categories = _.keyBy(api_categories, 'id')
|
|
||||||
api.streams = _.keyBy(api_streams, 'channel')
|
|
||||||
api.blocklist = _.keyBy(api_blocklist, 'channel')
|
|
||||||
api.guides = {}
|
|
||||||
|
|
||||||
api.channels = api_channels
|
|
||||||
|
|
||||||
return api
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _loadAPI() {
|
|
||||||
const api = {}
|
|
||||||
|
|
||||||
api.countries = await fetch('https://iptv-org.github.io/api/countries.json')
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data =>
|
.then(data =>
|
||||||
data.map(i => {
|
data.map(i => {
|
||||||
i.expanded = false
|
i.expanded = false
|
||||||
|
@ -148,46 +115,40 @@ async function _loadAPI() {
|
||||||
.then(data => _.keyBy(data, 'code'))
|
.then(data => _.keyBy(data, 'code'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.regions = await fetch('https://iptv-org.github.io/api/regions.json')
|
api.regions = await import('~/data/regions.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data => _.keyBy(data, 'code'))
|
.then(data => _.keyBy(data, 'code'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.subdivisions = await fetch('https://iptv-org.github.io/api/subdivisions.json')
|
api.subdivisions = await import('~/data/subdivisions.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data => _.keyBy(data, 'code'))
|
.then(data => _.keyBy(data, 'code'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.languages = await fetch('https://iptv-org.github.io/api/languages.json')
|
api.languages = await import('~/data/languages.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data => _.keyBy(data, 'code'))
|
.then(data => _.keyBy(data, 'code'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.categories = await fetch('https://iptv-org.github.io/api/categories.json')
|
api.categories = await import('~/data/categories.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data => _.keyBy(data, 'id'))
|
.then(data => _.keyBy(data, 'id'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.streams = await fetch('https://iptv-org.github.io/api/streams.json')
|
api.streams = await import('~/data/streams.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data => _.groupBy(data, 'channel'))
|
.then(data => _.groupBy(data, 'channel'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.blocklist = await fetch('https://iptv-org.github.io/api/blocklist.json')
|
api.blocklist = await import('~/data/blocklist.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.then(data => (data.length ? data : []))
|
|
||||||
.then(data => _.groupBy(data, 'channel'))
|
.then(data => _.groupBy(data, 'channel'))
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
||||||
api.guides = {}
|
api.guides = {}
|
||||||
|
|
||||||
api.channels = await fetch('https://iptv-org.github.io/api/channels.json')
|
api.channels = await import('~/data/channels.json')
|
||||||
.then(r => r.json())
|
.then(m => m.default)
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -13,7 +13,7 @@ const config = {
|
||||||
adapter: adapter({
|
adapter: adapter({
|
||||||
pages: 'docs',
|
pages: 'docs',
|
||||||
assets: 'docs',
|
assets: 'docs',
|
||||||
precompress: true
|
precompress: false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
preprocess: vitePreprocess()
|
preprocess: vitePreprocess()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue