(even) better gif loader, scss support

This commit is contained in:
Pablo Ferreiro 2022-01-07 00:13:51 +01:00
parent ca926c4dfb
commit 5888e2cdfb
No known key found for this signature in database
GPG key ID: 41FBCE65B779FA24
16 changed files with 267 additions and 45 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
node_modules
/.env /.env
/.vscode /.vscode
/vendor /vendor

View file

@ -1,6 +1,13 @@
# TikTok alternative Frontend # TikTok alternative Frontend
Use Tiktok using an alternative frontend, inspired by Nitter. Use Tiktok using an alternative frontend, inspired by Nitter.
## Features
* Privacy: All requests made to TikTok are server-side, so you will never connect to TikTok servers
* See user's feed
* See trending
* See tags
* Create a following list, which you can later use to see all the feeds from those users
## Installation ## Installation
Clone the repository and fetch the requiered external packages with: Clone the repository and fetch the requiered external packages with:
```bash ```bash
@ -17,7 +24,7 @@ php -S localhost:8080
Move the .env.example file to .env and modify it. Move the .env.example file to .env and modify it.
### Apache ### Apache
If you are using Apache you don't have to do anything more You don't have to do anything more
### Nginx ### Nginx
Add the following to your config (you can modify the tiktok-viewer part if you have or not a subdir): Add the following to your config (you can modify the tiktok-viewer part if you have or not a subdir):
@ -41,9 +48,11 @@ location /tiktok-viewer/.env {
## TODO ## TODO
* Allow searching for just one video using the ID * Allow searching for just one video using the ID
* Add a NoJS version / Make the whole program without required JS
## Credits ## Credits
* [TikTok-API-PHP](https://github.com/ssovit/TikTok-API-PHP) * [TikTok-API-PHP](https://github.com/ssovit/TikTok-API-PHP)
* [steampixel/simple-php-router](https://github.com/steampixel/simple-php-router) * [steampixel/simple-php-router](https://github.com/steampixel/simple-php-router)
* [PHP dotenv](https://github.com/vlucas/phpdotenv) * [PHP dotenv](https://github.com/vlucas/phpdotenv)
* [Bulma](https://github.com/jgthms/bulma) * [Bulma](https://github.com/jgthms/bulma)
* [Bulmaswatch](https://github.com/jenil/bulmaswatch)

View file

@ -14,8 +14,8 @@ class Misc {
static public function api(): \Sovit\TikTok\Api { static public function api(): \Sovit\TikTok\Api {
$options = []; $options = [];
// Proxy config // Proxy config
if (in_array(Settings::$proxy, $_COOKIE)) { if (in_array(Settings::PROXY, $_COOKIE)) {
foreach (Settings::$proxy as $proxy_element) { foreach (Settings::PROXY as $proxy_element) {
$options[$proxy_element] = $_COOKIE[$proxy_element]; $options[$proxy_element] = $_COOKIE[$proxy_element];
} }
} }

View file

@ -2,7 +2,7 @@
namespace Helpers; namespace Helpers;
class Settings { class Settings {
static public $proxy = ['proxy-host', 'proxy-port', 'proxy-username', 'proxy-password']; const PROXY = ['proxy-host', 'proxy-port', 'proxy-username', 'proxy-password'];
static public function get(string $name): string { static public function get(string $name): string {
if (isset($_COOKIE[$name]) && !empty($_COOKIE[$name])) { if (isset($_COOKIE[$name]) && !empty($_COOKIE[$name])) {

View file

@ -7,12 +7,12 @@ use Steampixel\Route;
Route::add("/settings", function () { Route::add("/settings", function () {
$latte = Misc::latte(); $latte = Misc::latte();
$latte->render(Misc::getView('settings'), ["proxy_elements" => Settings::$proxy, "following" => Following::get()]); $latte->render(Misc::getView('settings'), ["proxy_elements" => Settings::PROXY, "following" => Following::get()]);
}); });
Route::add("/settings/proxy", function () { Route::add("/settings/proxy", function () {
if (in_array(Settings::$proxy, $_POST)) { if (in_array(Settings::PROXY, $_POST)) {
foreach (Settings::$proxy as $proxy_element) { foreach (Settings::PROXY as $proxy_element) {
Settings::set($proxy_element, $_POST[$proxy_element]); Settings::set($proxy_element, $_POST[$proxy_element]);
} }
} }
@ -23,17 +23,25 @@ Route::add("/settings/proxy", function () {
Route::add("/settings/following", function () { Route::add("/settings/following", function () {
$following = Following::get(); $following = Following::get();
if (!isset($_POST['mode']) || empty($_POST['mode'])) {
die('You need to send a mode');
}
if (isset($_POST['add'])) { switch ($_POST['mode']) {
case 'add':
// Add following // Add following
array_push($following, $_POST['account']); array_push($following, $_POST['account']);
} elseif (isset($_POST['remove'])) { break;
case 'remove':
// Remove following
$index = array_search($_POST['account'], $following); $index = array_search($_POST['account'], $following);
if ($index !== false) { if ($index !== false) {
unset($following[$index]); unset($following[$index]);
} }
} else { break;
return 'You need to send a mode!'; default:
// Invalid
die('Invalid mode');
} }
// Build string // Build string

View file

@ -4,7 +4,6 @@ const audio = document.getElementById('audio')
const audio_title = document.getElementById('audio_title') const audio_title = document.getElementById('audio_title')
const modal = document.getElementById('modal') const modal = document.getElementById('modal')
const download_button = document.getElementById('download_button') const download_button = document.getElementById('download_button')
const gifs = document.getElementsByClassName("img-background")
// -- HELPERS -- // // -- HELPERS -- //
const getHash = () => window.location.hash.substring(1) const getHash = () => window.location.hash.substring(1)
@ -102,9 +101,24 @@ const hashChange = () => {
} }
} }
const swapImages = e => { const swapImages = (e, mode) => {
if (!e.target.src) { let img = null
e.target.src = e.target.dataset.src let gif = null
if (mode === 'gif') {
const a = e.target
img = a.children[0]
gif = a.children[1]
} else if (mode === 'img') {
gif = e.target
img = e.target.parentElement.children[0]
}
if (img && gif) {
if (!gif.src) {
gif.src = gif.dataset.src
}
img.classList.toggle('hidden')
gif.classList.toggle('hidden')
} }
} }
@ -115,7 +129,11 @@ document.getElementById('next-button').addEventListener('click', () => moveVideo
window.addEventListener('hashchange', hashChange, false) window.addEventListener('hashchange', hashChange, false)
// Image hover // Image hover
for (let i = 0; i < gifs.length; i++) { const images = document.getElementsByClassName("clickable-img")
gifs[i].addEventListener('mouseenter', swapImages, false) for (let i = 0; i < images.length; i++) {
images[i].addEventListener('mouseenter', e => swapImages(e, 'gif'), false)
images[i].addEventListener('mouseout', e => swapImages(e, 'img'), false)
} }
hashChange() hashChange()

1
styles/bulma.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
styles/bulma.min.css.map Normal file

File diff suppressed because one or more lines are too long

View file

@ -8,19 +8,12 @@ figure {
display: inline-block; display: inline-block;
} }
.img-background { .hidden {
display: none;
}
/* Make gifs take all available space */
.clickable-img img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
figure .img-background {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 99;
}
figure:hover .img-background {
display: inline;
}

11
styles/scss/README.md Normal file
View file

@ -0,0 +1,11 @@
This facilities making the bulma.min.css file, install all dependencies using:
```
yarn install
```
And then use:
```
yarn bulma
```
This compiles bulma.scss to a css file and helps lowering the size of the css that will be sent to the user.

36
styles/scss/bulma.scss vendored Normal file
View file

@ -0,0 +1,36 @@
@charset "utf-8";
@import "./node_modules/bulmaswatch/superhero/_variables.scss";
// Utilities
@import "./node_modules/bulma/sass/utilities/_all.sass";
// Base
@import "./node_modules/bulma/sass/base/_all.sass";
// Elements
@import "./node_modules/bulma/sass/elements/button.sass";
@import "./node_modules/bulma/sass/elements/container.sass";
@import "./node_modules/bulma/sass/elements/other.sass";
@import "./node_modules/bulma/sass/elements/tag.sass";
@import "./node_modules/bulma/sass/elements/title.sass";
// Form
@import "./node_modules/bulma/sass/form/shared.sass";
@import "./node_modules/bulma/sass/form/checkbox_radio.sass";
@import "./node_modules/bulma/sass/form/tools.sass";
// Components
@import "./node_modules/bulma/sass/components/modal.sass";
@import "./node_modules/bulma/sass/components/navbar.sass";
// Grids
@import "./node_modules/bulma/sass/grid/columns.sass";
// Helpers
@import "./node_modules/bulma/sass/helpers/_all.sass";
// Layout
@import "./node_modules/bulma/sass/layout/_all.sass";
@import "./node_modules/bulmaswatch/superhero/_overrides.scss";

12
styles/scss/package.json Normal file
View file

@ -0,0 +1,12 @@
{
"name": "tiktok-alt-frontend-scss",
"private": true,
"scripts": {
"bulma": "sass --style=compressed bulma.scss ../bulma.min.css"
},
"dependencies": {
"bulma": "^0.9.3",
"bulmaswatch": "^0.8.1",
"sass": "^1.46.0"
}
}

134
styles/scss/yarn.lock Normal file
View file

@ -0,0 +1,134 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
bulma@^0.9.3:
version "0.9.3"
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.9.3.tgz#ddccb7436ebe3e21bf47afe01d3c43a296b70243"
integrity sha512-0d7GNW1PY4ud8TWxdNcP6Cc8Bu7MxcntD/RRLGWuiw/s0a9P+XlH/6QoOIrmbj6o8WWJzJYhytiu9nFjTszk1g==
bulmaswatch@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/bulmaswatch/-/bulmaswatch-0.8.1.tgz#3b9cf899dfa2430b9d5178362a45e79f005b0b5b"
integrity sha512-7HGm5v9If6gzxbTht4/oVS0dhySp6g/JyTrxmpSXHXgDQXivvxiuVmcJOZo3PFv9GAOn4om7SK36I2V8W81sgw==
"chokidar@>=3.0.0 <4.0.0":
version "3.5.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
immutable@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23"
integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
picomatch@^2.0.4, picomatch@^2.2.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
sass@^1.46.0:
version "1.46.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.46.0.tgz#923117049525236026a7ede69715580eb0fac751"
integrity sha512-Z4BYTgioAOlMmo4LU3Ky2txR8KR0GRPLXxO38kklaYxgo7qMTgy+mpNN4eKsrXDTFlwS5vdruvazG4cihxHRVQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
"source-map-js@>=0.6.2 <2.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"

View file

@ -2,8 +2,8 @@
<section class="section"> <section class="section">
<div class="columns is-multiline is-vcentered"> <div class="columns is-multiline is-vcentered">
{foreach $feed->items as $item} {foreach $feed->items as $item}
<div class="column is-one-quarter clickable-img"> <div class="column is-one-quarter">
<a id="{$item->id}" href="#{$item->id}" <a class="clickable-img" id="{$item->id}" href="#{$item->id}"
data-video_url="{path('stream?url=' . urlencode($item->video->playAddr))}" data-video_url="{path('stream?url=' . urlencode($item->video->playAddr))}"
data-video_download="{path('stream?url=' . urlencode($item->video->playAddr) . '&download=1')}" data-video_download="{path('stream?url=' . urlencode($item->video->playAddr) . '&download=1')}"
data-desc="{$item->desc}" data-desc="{$item->desc}"
@ -11,10 +11,8 @@
data-video_height="{$item->video->height}" data-video_height="{$item->video->height}"
data-music_title="{$item->music->title}" data-music_title="{$item->music->title}"
data-music_url="{path('stream?url=' . urlencode($item->music->playUrl))}"> data-music_url="{path('stream?url=' . urlencode($item->music->playUrl))}">
<figure> <img loading="lazy" src="{path('stream?url=' . urlencode($item->video->originCover))}" />
<img class="img-main" loading="lazy" src="{path('stream?url=' . urlencode($item->video->originCover))}" /> <img class="hidden" loading="lazy" data-src="{path('stream?url=' . urlencode($item->video->dynamicCover))}" />
<img class="img-background" loading="lazy" data-src="{path('stream?url=' . urlencode($item->video->dynamicCover))}" />
</figure>
</a> </a>
</div> </div>
{/foreach} {/foreach}

View file

@ -2,6 +2,6 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/bulmaswatch/superhero/bulmaswatch.min.css"> <link rel="stylesheet" href="{assets('bulma.min.css', 'styles')}">
<title>{$title} - Tiktok Alt-Frontend</title> <title>{$title} - Tiktok Alt-Frontend</title>
</head> </head>

View file

@ -9,10 +9,10 @@
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<label class="radio"> <label class="radio">
<input type="radio" name="add">Add <input type="radio" name="mode" value="add">Add
</label> </label>
<label class="radio"> <label class="radio">
<input type="radio" name="remove">Remove <input type="radio" name="mode" value="remove">Remove
</label> </label>
</div> </div>
</div> </div>