This commit is contained in:
WardPearce
2024-03-08 01:11:35 +13:00
parent b65f1e54cd
commit 0d196280c5
25 changed files with 4042 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
+31
View File
@@ -0,0 +1,31 @@
/** @type { import("eslint").Linter.Config } */
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte']
},
env: {
browser: true,
es2017: true,
node: true
},
overrides: [
{
files: ['*.svelte'],
parser: 'svelte-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
]
};
+10
View File
@@ -0,0 +1,10 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
+1
View File
@@ -0,0 +1 @@
engine-strict=true
+4
View File
@@ -0,0 +1,4 @@
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
+8
View File
@@ -0,0 +1,8 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}
+38
View File
@@ -0,0 +1,38 @@
# create-svelte
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
# create a new project in my-app
npm create svelte@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
+3560
View File
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
{
"name": "materialious",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/eslint": "^8.56.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^5.0.3"
},
"type": "module",
"dependencies": {
"beercss": "^3.5.1",
"svelte-persisted-store": "^0.9.1"
}
}
+14
View File
@@ -0,0 +1,14 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export { };
+12
View File
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
import { get } from 'svelte/store';
import { invidiousInstance } from '../../store';
import type { Video } from './model';
function buildPath(path: string): string {
return `${get(invidiousInstance)}/api/v1/${path}`;
}
export async function getTrending(): Promise<Video[]> {
const resp = await fetch(buildPath('trending'));
return await resp.json();
}
+34
View File
@@ -0,0 +1,34 @@
export interface Image {
url: string;
width: number;
height: number;
}
export interface Thumbnail {
quality: string;
url: string;
width: number;
height: number;
}
export interface Video {
type: "video";
title: string;
videoId: string;
author: string;
authorId: string;
authorUrl: string;
authorVerified: boolean;
videoThumbnails: Thumbnail[];
description: string;
descriptionHtml: string;
viewCount: number;
viewCountText: string;
lengthSeconds: number;
published: number;
publishedText: string;
premiereTimestamp: number;
liveNow: boolean;
premium: boolean;
isUpcoming: boolean;
}
+19
View File
@@ -0,0 +1,19 @@
<svg height="100%" version="1.0" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"
><g
><path
d="m247.17 455.95c-19.792-0.78921-38.719-4.2564-57.154-10.47-60.968-20.55-108.68-68.579-127-127.86-7.8955-25.538-10.062-53.943-6.2586-82.067 3.7105-27.439 13.603-53.515 29.342-77.344 12.069-18.273 29.138-36.277 47.228-49.816 36.891-27.61 85.944-42.49 132.38-40.157 25.88 1.3001 49.939 6.765 73.106 16.606 8.1948 3.481 20.024 9.6845 27.696 14.525 14.15 8.9272 22.367 15.498 34.482 27.573 13.254 13.211 22.128 24.276 30.398 37.906 7.2081 11.879 14.099 27.15 18.229 40.397 1.5996 5.1305 4.442 16.456 5.6852 22.653 2.3908 11.917 2.6998 15.722 2.7049 33.312 6e-3 18.515-0.46256 24.413-2.9166 36.758-9.3274 46.92-35.58 88.167-74.872 117.64-22.814 17.112-50.027 29.535-78.547 35.858-16.714 3.7059-35.421 5.2453-54.498 4.4846zm-35.1-78.786c-5.3e-4 -0.52647-0.0741-2.0564-0.16311-3.3999l-0.16178-2.4427-4.7018-0.26271c-4.0477-0.22614-4.7968-0.33363-5.3847-0.77253-2.0235-1.5108-1.4679-6.0695 2.2494-18.457 0.8637-2.8781 3.3371-11.321 5.4966-18.762 2.1594-7.4409 5.2002-17.836 6.7573-23.101 1.5571-5.2648 4.1948-14.282 5.8615-20.038 1.6667-5.7562 3.6145-12.4 4.3284-14.764 0.71391-2.3641 3.2583-11.037 5.6542-19.272 4.9475-17.007 8.1626-27.723 8.9438-29.811 0.51852-1.3858 0.54785-1.4139 0.99761-0.95317 0.25486 0.26106 3.8462 7.3667 7.9807 15.79 4.1345 8.4236 13.089 26.573 19.898 40.331 17.188 34.73 37.849 76.578 43.261 87.622l4.5356 9.257 11.359-0.0895c6.2475-0.0492 11.615-0.19623 11.929-0.32672 0.5614-0.23385 0.54167-0.2959-1.3723-4.3176-1.068-2.2442-8.1436-16.601-15.724-31.904-48.687-98.293-61.22-123.86-67.889-138.48-4.7022-10.309-6.9031-14.807-7.7139-15.762-0.82931-0.97742-1.6319-1.0638-2.3704-0.25525-1.1993 1.313-4.1046 10.063-9.3869 28.27-2.0569 7.0899-6.5372 22.425-9.9562 34.077-6.6396 22.629-8.5182 29.037-14.33 48.883-2.0354 6.9495-4.7977 16.369-6.1385 20.931-1.3408 4.5628-4.033 13.81-5.9826 20.549-4.304 14.877-6.136 20.889-7.3886 24.25-2.1371 5.7334-2.5723 6.3292-4.9216 6.7384-0.88855 0.15472-2.4102 0.28196-3.3815 0.28275-2.1993 3e-3 -3.5494 0.36339-4.0558 1.0863-0.42176 0.60215-0.56421 4.8802-0.18251 5.4812 0.20573 0.32388 2.4672 0.37414 23.34 0.51873l8.6151 0.0597-7e-4 -0.95723zm36.751-205.59c4.3282-0.92335 8.4607-4.943 9.4374-9.1796 0.36569-1.5862 0.32543-4.9758-0.077-6.4799-0.85108-3.1813-3.2688-6.291-6.039-7.7675-3.8111-2.0313-9.456-2.0295-13.272 5e-3 -5.9828 3.1888-8.1556 11.089-4.7878 17.408 2.6995 5.0648 8.3611 7.3754 14.738 6.015z"
fill="var(--inverse-primary)"
stroke-width=".025526"
/></g
><g transform="matrix(.069892 0 0 -.069892 44.236 474.48)"
><path
d="m2787 4669c-124-65-123-255 3-319 86-44 196-16 247 62 58 87 26 211-67 258-51 26-132 26-183-1z"
fill="var(--inverse-surface)"
stroke="var(--inverse-surface)"
stroke-width="4.25"
/><path
d="m2882 4108c-12-16-63-166-102-303-30-104-101-350-165-565-20-69-58-199-85-290-26-91-64-221-85-290-20-69-58-199-85-290-26-91-64-221-85-290-20-69-57-195-81-280-59-207-93-299-115-310-10-6-35-10-56-10-73 0-84-8-81-54l3-41 228-3 228-2-3 47-3 48-73 3c-66 3-74 5-84 27-13 28 0 104 37 225 13 41 47 156 75 255s66 230 85 290c18 61 56 191 85 290 28 99 66 230 85 290 18 61 56 191 85 290 85 297 123 419 131 429 5 5 17-11 28-35 10-24 192-393 403-819s447-902 523-1058l139-282h168c92 0 168 4 168 8s-75 158-166 342c-588 1183-969 1958-1033 2100-29 63-69 151-89 195-44 95-58 110-80 83z"
fill="var(--inverse-surface)"
/></g
></svg
>

After

Width:  |  Height:  |  Size: 3.3 KiB

+12
View File
@@ -0,0 +1,12 @@
<div>
<progress class="circle large"></progress>
</div>
<style>
div {
display: flex;
align-items: center;
justify-content: center;
height: 40vh;
}
</style>
+53
View File
@@ -0,0 +1,53 @@
<script lang="ts">
import type { Video } from './Api/model';
export let video: Video;
function videoLength(lengthSeconds: number): string {
const hours = Math.floor(lengthSeconds / 3600);
const minutes = Math.floor((lengthSeconds % 3600) / 60);
const seconds = lengthSeconds % 60;
return `${hours}:${minutes}:${seconds}`;
}
</script>
<article class="no-padding transparent">
<a
class="wave"
style="width: 100%; height: 155px; overflow: hidden;"
href={`/watch/${video.videoId}`}
><img
class="responsive"
style="object-fit: crop;"
src={video.videoThumbnails[3].url}
alt="Thumbnail for video"
/>
{#if !video.liveNow}
<div class="absolute right bottom small-margin black white-text small-text">
&nbsp;{videoLength(video.lengthSeconds)}&nbsp;
</div>
{:else}
<div
class="absolute right bottom small-margin red white-text small-text"
style="padding: 0 1em;"
>
LIVE
</div>
{/if}
</a>
<div class="small-padding">
<nav>
<div class="max truncate">
<div class="bold">{video.author}</div>
<div>{video.viewCountText} • {video.publishedText}</div>
</div>
<button class="circle transparent" data-ui="#menu-1"
><i>more_vert</i><menu class="left no-wrap" id="menu-1" data-ui="#menu-1"
><a>Save to paylist</a>
<a>Download</a></menu
></button
>
</nav>
</div>
</article>
+1
View File
@@ -0,0 +1 @@
export const ssr = false;
+107
View File
@@ -0,0 +1,107 @@
<script lang="ts">
import Logo from '$lib/Logo.svelte';
import 'beercss';
import 'material-dynamic-colors';
const pages = [
{
icon: 'home',
href: '/home',
name: 'Home'
},
{
icon: 'whatshot',
href: '/trending',
name: 'Trending'
},
{
icon: 'subscriptions',
href: '/subscriptions',
name: 'Subscriptions'
},
{
icon: 'video_library',
href: '/playlists',
name: 'Playlists'
},
{
icon: 'history',
href: '/history',
name: 'history'
}
];
</script>
<nav class="left m l small">
<header></header>
{#each pages as page}
<a href={page.href}
><i>{page.icon}</i>
<div>{page.name}</div>
</a>
{/each}
</nav>
<nav class="top">
<button class="circle large transparent s m l small-margin" data-ui="#dialog-expanded"
><i>menu</i></button
>
<Logo />
<h6 class="m l">Materialious</h6>
<div class="max"></div>
<div class="max field round suffix prefix small no-margin m l white black-text">
<i class="front">search</i><input type="text" placeholder="Search..." />
</div>
<div class="max"></div>
<button class="circle large transparent" data-ui="#dialog-notifications"
><i>notifications</i></button
>
<button class="circle large transparent" data-ui="#dialog-settings"><i>settings</i></button>
<button class="circle large transparent"><i>login</i></button>
</nav>
<dialog class="right" id="dialog-settings">
<nav>
<h5 class="max">Settings</h5>
<button class="circle transparent" data-ui="#dialog-settings"><i>close</i></button>
</nav>
<p>Customize Materialious</p>
</dialog>
<dialog class="right" id="dialog-notifications">
<nav>
<h5 class="max">Notifications</h5>
<button class="circle transparent" data-ui="#dialog-notifications"><i>close</i></button>
</nav>
<p>No new notifications here</p>
</dialog>
<dialog class="left small" id="dialog-expanded">
<header class="fixed">
<nav>
<button class="transparent circle large" data-ui="#dialog-expanded"><i>menu</i></button>
<div style="width: 20%;">
<Logo />
</div>
<h6>Materialious</h6>
</nav>
</header>
{#each pages as page}
<a class="row round" data-ui="#dialog-expanded" href={page.href}
><i>{page.icon}</i>
<div>{page.name}</div></a
>
{/each}
</dialog>
<main class="responsive max">
<slot />
</main>
<style>
nav.left a {
font-size: 0.8em;
}
</style>
+28
View File
@@ -0,0 +1,28 @@
<script lang="ts">
import { getTrending } from '$lib/Api';
import type { Video } from '$lib/Api/model';
import PageLoading from '$lib/PageLoading.svelte';
import Thumbnail from '$lib/Thumbnail.svelte';
import { onMount } from 'svelte';
let trending: Video[];
onMount(async () => {
trending = await getTrending();
});
</script>
{#if trending}
<div class="page right active">
<div class="space"></div>
<div class="grid">
{#each trending as video}
<div class="s12 m6 l2">
<Thumbnail {video} />
</div>
{/each}
</div>
</div>
{:else}
<PageLoading />
{/if}
@@ -0,0 +1,3 @@
<script lang="ts">
export let videoId: string;
</script>
+3
View File
@@ -0,0 +1,3 @@
import { persisted } from 'svelte-persisted-store';
export const invidiousInstance = persisted('invidiousInstance', import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE);
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+18
View File
@@ -0,0 +1,18 @@
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter()
}
};
export default config;
+18
View File
@@ -0,0 +1,18 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}
+6
View File
@@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()],
});