diff --git a/app/Controllers/DiscoverController.php b/app/Controllers/DiscoverController.php
index a2d033b..c43f19b 100644
--- a/app/Controllers/DiscoverController.php
+++ b/app/Controllers/DiscoverController.php
@@ -6,7 +6,7 @@ use App\Helpers\Wrappers;
use App\Models\DiscoverTemplate;
class DiscoverController {
- static public function get() {
+ public static function get() {
$api = Wrappers::api();
$data = $api->discover();
if ($data->meta->success) {
diff --git a/app/Controllers/EmbedController.php b/app/Controllers/EmbedController.php
index 48e4b73..06c90a2 100644
--- a/app/Controllers/EmbedController.php
+++ b/app/Controllers/EmbedController.php
@@ -6,7 +6,7 @@ use App\Helpers\Wrappers;
use App\Models\VideoTemplate;
class EmbedController {
- static public function v2(int $id) {
+ public static function v2(int $id) {
$api = Wrappers::api();
$video = $api->video($id);
$video->feed();
diff --git a/app/Controllers/MusicController.php b/app/Controllers/MusicController.php
index 0ca11fe..215b3d2 100644
--- a/app/Controllers/MusicController.php
+++ b/app/Controllers/MusicController.php
@@ -7,7 +7,7 @@ use App\Helpers\Wrappers;
use App\Models\FullTemplate;
class MusicController {
- static public function get(string $music_id) {
+ public static function get(string $music_id) {
$cursor = Misc::getCursor();
$api = Wrappers::api();
diff --git a/app/Controllers/ProxyController.php b/app/Controllers/ProxyController.php
index 7a3c72e..ff72c23 100644
--- a/app/Controllers/ProxyController.php
+++ b/app/Controllers/ProxyController.php
@@ -10,7 +10,7 @@ class ProxyController {
"tiktokcdn.com", "tiktokcdn-us.com", "tiktok.com"
];
- static public function stream() {
+ public static function stream() {
self::checkUrl();
$url = $_GET['url'];
$config['user_agent'] = Misc::env("USER_AGENT", TikScraperUserAgents::DEFAULT);
@@ -18,7 +18,7 @@ class ProxyController {
$streamer->url($url);
}
- static public function download() {
+ public static function download() {
self::checkUrl();
$method = Cookies::downloader();
$downloader = new \TikScraper\Download($method);
diff --git a/app/Controllers/RedirectController.php b/app/Controllers/RedirectController.php
index 42f6d64..763084b 100644
--- a/app/Controllers/RedirectController.php
+++ b/app/Controllers/RedirectController.php
@@ -8,7 +8,7 @@ use App\Helpers\UrlBuilder;
* Used to be compatible with HTML forms
*/
class RedirectController {
- static public function search() {
+ public static function search() {
$endpoint = '/';
if (isset($_GET['type'], $_GET['term'])) {
$term = trim($_GET['term']);
@@ -49,7 +49,7 @@ class RedirectController {
header("Location: {$url}");
}
- static public function download() {
+ public static function download() {
if (!(isset($_GET['videoId'], $_GET['authorUsername'], $_GET['playAddr']))) {
ErrorHandler::showText(400, 'Request incomplete');
return;
diff --git a/app/Controllers/SettingsController.php b/app/Controllers/SettingsController.php
index 6c9f8dd..d6c1803 100644
--- a/app/Controllers/SettingsController.php
+++ b/app/Controllers/SettingsController.php
@@ -7,11 +7,11 @@ use App\Helpers\Wrappers;
use App\Models\SettingsTemplate;
class SettingsController {
- static public function index() {
+ public static function index() {
Wrappers::latte('settings', new SettingsTemplate());
}
- static public function general() {
+ public static function general() {
if (isset($_POST['theme'])) {
$theme = $_POST['theme'];
Cookies::set('theme', $theme);
@@ -19,7 +19,7 @@ class SettingsController {
self::redirect();
}
- static public function api() {
+ public static function api() {
// TODO, ADD COUNT
if (isset($_POST['api-test_endpoints'])) {
$test_endpoints = $_POST['api-test_endpoints'];
diff --git a/app/Controllers/TagController.php b/app/Controllers/TagController.php
index a59e061..e501c49 100644
--- a/app/Controllers/TagController.php
+++ b/app/Controllers/TagController.php
@@ -9,7 +9,7 @@ use App\Models\FullTemplate;
use App\Models\RSSTemplate;
class TagController {
- static public function get(string $name) {
+ public static function get(string $name) {
$cursor = Misc::getCursor();
$api = Wrappers::api();
$hashtag = $api->hashtag($name);
@@ -23,7 +23,7 @@ class TagController {
}
}
- static public function rss(string $name) {
+ public static function rss(string $name) {
$api = Wrappers::api();
$hashtag = $api->hashtag($name);
$hashtag->feed();
diff --git a/app/Controllers/TrendingController.php b/app/Controllers/TrendingController.php
index 6c85207..becc46a 100644
--- a/app/Controllers/TrendingController.php
+++ b/app/Controllers/TrendingController.php
@@ -8,7 +8,7 @@ use App\Helpers\Wrappers;
use App\Models\RSSTemplate;
class TrendingController {
- static public function get() {
+ public static function get() {
$api = Wrappers::api();
$cursor = Misc::getTtwid();
@@ -23,7 +23,7 @@ class TrendingController {
}
}
- static public function rss() {
+ public static function rss() {
$api = Wrappers::api();
$trending = $api->trending();
$trending->feed();
diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php
index 4b74dec..6cba1b6 100644
--- a/app/Controllers/UserController.php
+++ b/app/Controllers/UserController.php
@@ -10,7 +10,7 @@ use App\Models\RSSTemplate;
use App\Models\VideoTemplate;
class UserController {
- static public function get(string $username) {
+ public static function get(string $username) {
$cursor = Misc::getCursor();
$api = Wrappers::api();
$user = $api->user($username);
@@ -24,7 +24,7 @@ class UserController {
}
}
- static public function video(string $username, string $video_id) {
+ public static function video(string $username, string $video_id) {
$api = Wrappers::api();
$video = $api->video($video_id);
$video->feed();
@@ -37,7 +37,7 @@ class UserController {
}
}
- static public function rss(string $username) {
+ public static function rss(string $username) {
$api = Wrappers::api();
$user = $api->user($username);
$user->feed();
diff --git a/app/Controllers/VideoController.php b/app/Controllers/VideoController.php
index 1336c05..00540ba 100644
--- a/app/Controllers/VideoController.php
+++ b/app/Controllers/VideoController.php
@@ -2,7 +2,7 @@
namespace App\Controllers;
class VideoController {
- static public function get(string $video_id) {
+ public static function get(string $video_id) {
UserController::video('placeholder', $video_id);
}
}
diff --git a/app/Helpers/Cookies.php b/app/Helpers/Cookies.php
index a7d42ee..53c91fd 100644
--- a/app/Helpers/Cookies.php
+++ b/app/Helpers/Cookies.php
@@ -4,14 +4,14 @@ namespace App\Helpers;
use App\Constants\Themes;
class Cookies {
- static public function get(string $name, string $default_value = ''): string {
+ public static function get(string $name, string $default_value = ''): string {
if (isset($_COOKIE[$name]) && !empty($_COOKIE[$name])) {
return $_COOKIE[$name];
}
return $default_value;
}
- static public function theme(): string {
+ public static function theme(): string {
$theme = self::get('theme');
$ref = new \ReflectionClass(Themes::class);
$themes = $ref->getConstants();
@@ -21,20 +21,20 @@ class Cookies {
return 'default';
}
- static public function downloader(): string {
+ public static function downloader(): string {
$downloader = self::get('api-downloader', 'default');
return $downloader;
}
- static public function exists(string $name): bool {
+ public static function exists(string $name): bool {
return isset($_COOKIE[$name]);
}
- static public function check(string $name, string $value): bool {
+ public static function check(string $name, string $value): bool {
return self::exists($name) && $_COOKIE[$name] === $value;
}
- static public function set(string $name, string $value) {
+ public static function set(string $name, string $value) {
setcookie($name, $value, time()+60*60*24*30, '/', '', isset($_SERVER['HTTPS']), true);
}
};
diff --git a/app/Helpers/ErrorHandler.php b/app/Helpers/ErrorHandler.php
index 71eec85..e1a0170 100644
--- a/app/Helpers/ErrorHandler.php
+++ b/app/Helpers/ErrorHandler.php
@@ -5,12 +5,12 @@ use App\Models\ErrorTemplate;
use TikScraper\Models\Meta;
class ErrorHandler {
- static public function showMeta(Meta $meta) {
+ public static function showMeta(Meta $meta) {
http_response_code($meta->http_code);
Wrappers::latte('error', new ErrorTemplate($meta->http_code, $meta->tiktok_msg, $meta->tiktok_code));
}
- static public function showText(int $code, string $msg) {
+ public static function showText(int $code, string $msg) {
http_response_code($code);
Wrappers::latte('error', new ErrorTemplate($code, $msg));
}
diff --git a/app/Helpers/Misc.php b/app/Helpers/Misc.php
index 73b500a..91b7dc5 100644
--- a/app/Helpers/Misc.php
+++ b/app/Helpers/Misc.php
@@ -2,33 +2,34 @@
namespace App\Helpers;
class Misc {
- static public function getCursor(): int {
+ public static function getCursor(): int {
return isset($_GET['cursor']) && is_numeric($_GET['cursor']) ? (int) $_GET['cursor'] : 0;
}
- static public function getTtwid(): string {
+ public static function getTtwid(): string {
return isset($_GET['cursor']) ? $_GET['cursor'] : '';
}
- static public function url(string $endpoint = ''): string {
+ public static function url(string $endpoint = ''): string {
return self::env('APP_URL', '') . $endpoint;
}
- static public function env(string $key, $default_value) {
+ public static function env(string $key, $default_value) {
return $_ENV[$key] ?? $default_value;
}
/**
* Returns absolute path for view
*/
- static public function getView(string $template): string {
+ public static function getView(string $template): string {
return __DIR__ . "/../../templates/views/{$template}.latte";
}
/**
* Common method for rss feeds
*/
- static public function rss(string $title) {
+ public static function rss(string $title) {
+ header('Content-Type: application/rss+xml');
header('Content-Disposition: attachment; filename="' . $title . '.rss' . '"');
}
}
diff --git a/app/Helpers/UrlBuilder.php b/app/Helpers/UrlBuilder.php
index d7a58a8..f677902 100644
--- a/app/Helpers/UrlBuilder.php
+++ b/app/Helpers/UrlBuilder.php
@@ -2,29 +2,29 @@
namespace App\Helpers;
class UrlBuilder {
- static public function stream(string $url): string {
+ public static function stream(string $url): string {
return Misc::url('/stream?url=' . urlencode($url));
}
- static public function download(string $url, string $username, string $id, bool $watermark): string {
+ public static function download(string $url, string $username, string $id, bool $watermark): string {
$down_url = Misc::url('/download?url=' . urlencode($url) . '&id=' . $id . '&user=' . $username);
if ($watermark) $down_url .= '&watermark=1';
return $down_url;
}
- static public function user(string $username): string {
+ public static function user(string $username): string {
return Misc::url('/@' . $username);
}
- static public function tag(string $tag): string {
+ public static function tag(string $tag): string {
return Misc::url('/tag/' . $tag);
}
- static public function video_internal(string $username, string $id): string {
+ public static function video_internal(string $username, string $id): string {
return Misc::url('/@' . $username . "/video/" . $id);
}
- static public function video_external(string $username, string $id): string {
+ public static function video_external(string $username, string $id): string {
return "https://www.tiktok.com/@" . $username . "/video/" . $id;
}
}
diff --git a/app/Helpers/Wrappers.php b/app/Helpers/Wrappers.php
index ae8ba50..cd9a4e7 100644
--- a/app/Helpers/Wrappers.php
+++ b/app/Helpers/Wrappers.php
@@ -12,7 +12,7 @@ class Wrappers {
/**
* Setup of Latte template engine
*/
- static public function latte(string $template, BaseTemplate $base) {
+ public static function latte(string $template, BaseTemplate $base) {
$latte = new \Latte\Engine;
$cache_path = Misc::env('LATTE_CACHE', __DIR__ . '/../../cache/latte');
$latte->setTempDirectory($cache_path);
@@ -91,9 +91,19 @@ class Wrappers {
return UrlBuilder::download($url, $username, $id, $watermark);
});
+ $latte->addFunction('bool_to_str', function (bool $cond): string {
+ return $cond ? 'yes' : 'no';
+ });
+
// Add URLs to video descriptions
// TODO: Make it work with unicode characters such as emojis
$latte->addFunction('render_desc', function (string $desc, array $textExtras = []): string {
+ $bytesCount = strlen($desc);
+ $charsCount = mb_strlen($desc);
+ // Skip urlify for now if there is a special char like an emoji to avoid issues
+ if ($bytesCount !== $charsCount) {
+ return $desc;
+ }
$sanitizedDesc = htmlspecialchars($desc);
$out = $sanitizedDesc;
foreach ($textExtras as $extra) {
@@ -121,7 +131,7 @@ class Wrappers {
/**
* Setup of TikTok Api wrapper
*/
- static public function api(): \TikScraper\Api {
+ public static function api(): \TikScraper\Api {
$method = Misc::env('API_SIGNER', '');
$url = Misc::env('API_SIGNER_URL', '');
if (!$method) {
diff --git a/composer.json b/composer.json
index f646137..3c5d0a7 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "pablouser1/proxitok",
"description": "An alternative frontend for TikTok",
- "version": "2.4.8.1",
+ "version": "2.4.9.1",
"license": "AGPL-3.0-or-later",
"type": "project",
"authors": [
diff --git a/composer.lock b/composer.lock
index a10ffef..405d55e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "15a71acabddd2588be9800ae1bb37c92",
+ "content-hash": "790ea9098323ef66c520cfe44b92b7d3",
"packages": [
{
"name": "bramus/router",
@@ -303,16 +303,16 @@
},
{
"name": "pablouser1/tikscraper",
- "version": "v2.3.6.2",
+ "version": "v2.3.6.4",
"source": {
"type": "git",
"url": "https://github.com/pablouser1/TikScraperPHP.git",
- "reference": "10394fb5fb5213d05fe0eb29f7582423fc15d08a"
+ "reference": "b26764777121dbc4408f84140b802869a77b575e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/10394fb5fb5213d05fe0eb29f7582423fc15d08a",
- "reference": "10394fb5fb5213d05fe0eb29f7582423fc15d08a",
+ "url": "https://api.github.com/repos/pablouser1/TikScraperPHP/zipball/b26764777121dbc4408f84140b802869a77b575e",
+ "reference": "b26764777121dbc4408f84140b802869a77b575e",
"shasum": ""
},
"require": {
@@ -346,9 +346,9 @@
"description": "Get data from TikTok API",
"support": {
"issues": "https://github.com/pablouser1/TikScraperPHP/issues",
- "source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.3.6.2"
+ "source": "https://github.com/pablouser1/TikScraperPHP/tree/v2.3.6.4"
},
- "time": "2023-04-01T13:46:50+00:00"
+ "time": "2023-04-05T15:08:06+00:00"
},
{
"name": "php-webdriver/webdriver",
diff --git a/docker-compose.yml b/docker-compose.yml
index ae98621..5503751 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -4,8 +4,8 @@ services:
web:
container_name: proxitok-web
image: ghcr.io/pablouser1/proxitok:master
- ports:
- - 8080:80
+ # ports:
+ # - 8080:80
environment:
- LATTE_CACHE=/cache
- API_CACHE=redis
@@ -13,6 +13,7 @@ services:
- REDIS_PORT=6379
- API_SIGNER=remote
- API_SIGNER_URL=http://proxitok-signer:8080/signature
+ - APP_URL=https://proxitok.tams.tech
volumes:
- proxitok-cache:/cache
depends_on:
@@ -20,6 +21,7 @@ services:
- signer
networks:
- proxitok
+ - web
security_opt:
- no-new-privileges:true
cap_drop:
@@ -28,6 +30,20 @@ services:
- CHOWN
- SETGID
- SETUID
+ labels:
+ # Traefik
+ traefik.docker.network: web
+ traefik.domain: tams.tech
+ traefik.enable: "true"
+ # Traefik v1
+ traefik.frontend.rule: Host:proxitok.tams.tech
+ # DNS discovery (not used)
+ tech.tams.dns_hosts: proxitok.tams.tech
+ # Traefik V2
+ traefik.http.routers.proxitok.rule: Host(`proxitok.tams.tech`)
+ traefik.http.routers.proxitok.tls: true
+ traefik.http.routers.proxitok.tls.certresolver: letsencrypt
+
redis:
container_name: proxitok-redis
@@ -62,3 +78,6 @@ volumes:
networks:
proxitok:
+ internal: true
+ web:
+ external: true
diff --git a/misc/scss/cssgg.scss b/misc/scss/cssgg.scss
index 12d7f85..8d0e66f 100644
--- a/misc/scss/cssgg.scss
+++ b/misc/scss/cssgg.scss
@@ -15,6 +15,7 @@
@import "./node_modules/css.gg/icons/scss/comment.scss";
@import "./node_modules/css.gg/icons/scss/share.scss";
@import "./node_modules/css.gg/icons/scss/software-download.scss";
+@import "./node_modules/css.gg/icons/scss/check-o.scss";
@import "./node_modules/css.gg/icons/scss/lock.scss";
@import "./node_modules/css.gg/icons/scss/lock-unlock.scss";
diff --git a/styles/misc.css b/styles/misc.css
new file mode 100644
index 0000000..8b58f37
--- /dev/null
+++ b/styles/misc.css
@@ -0,0 +1,3 @@
+.new-line {
+ white-space: pre-wrap;
+}
diff --git a/styles/vendor/cssgg.min.css b/styles/vendor/cssgg.min.css
index ce5f674..f3f50dd 100644
--- a/styles/vendor/cssgg.min.css
+++ b/styles/vendor/cssgg.min.css
@@ -1 +1 @@
-.gg-home{background:linear-gradient(to left, currentColor 5px, transparent 0) no-repeat 0 bottom/4px 2px,linear-gradient(to left, currentColor 5px, transparent 0) no-repeat right bottom/4px 2px;box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:18px;height:14px;border:2px solid;border-top:0;border-bottom:0;border-top-right-radius:3px;border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:0;margin-bottom:-2px}.gg-home::after{content:"";display:block;box-sizing:border-box;position:absolute}.gg-home::before{content:"";display:block;box-sizing:border-box;position:absolute;border-top:2px solid;border-left:2px solid;border-top-left-radius:4px;transform:rotate(45deg);top:-5px;border-radius:3px;width:14px;height:14px;left:0}.gg-home::after{width:8px;height:10px;border:2px solid;border-radius:100px;border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom:0;left:3px;bottom:0}.gg-options{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:10px;height:2px;box-shadow:-3px 4px 0 0,3px -4px 0 0}.gg-options::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;border:2px solid;border-radius:100%}.gg-options::before{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;border:2px solid;border-radius:100%;top:-7px;left:-4px}.gg-options::after{bottom:-7px;right:-4px}.gg-info{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:20px;height:20px;border:2px solid;border-radius:40px}.gg-info::after,.gg-info::before{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:2px;background:currentColor;left:7px}.gg-info::after{bottom:2px;height:8px}.gg-info::before{height:2px;top:2px}.gg-code-slash{display:block;position:relative;box-sizing:border-box;transform:rotate(15deg) scale(var(--ggs, 1));width:2px;height:16px;background:currentColor}.gg-code-slash::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;transform:rotate(-60deg)}.gg-code-slash::before{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;transform:rotate(-60deg);border-left:2px solid;border-top:2px solid;left:-8px;top:5px}.gg-code-slash::after{border-right:2px solid;border-bottom:2px solid;right:-8px;top:3px}.gg-search{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:16px;height:16px;border:2px solid;border-radius:100%;margin-left:-4px;margin-top:-4px}.gg-search::after{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:2px;height:8px;background:currentColor;transform:rotate(-45deg);top:10px;left:12px}.gg-feed{display:block;box-sizing:border-box;background:currentColor;box-shadow:0 10px 0 0;margin-left:-8px;margin-top:-8px;position:relative;transform:scale(var(--ggs, 1));width:7px;height:7px;border-radius:1px}.gg-feed::after,.gg-feed::before{display:block;box-sizing:border-box;background:currentColor;box-shadow:0 10px 0 0}.gg-feed::after,.gg-feed::before{content:"";position:absolute;border-radius:3px;width:12px;height:2px;top:1px;left:9px;opacity:.8}.gg-feed::after{width:8px;top:4px;opacity:.5}.gg-eye{position:relative;display:block;transform:scale(var(--ggs, 1));width:24px;height:18px;border-bottom-right-radius:100px;border-bottom-left-radius:100px;overflow:hidden;box-sizing:border-box}.gg-eye::after,.gg-eye::before{content:"";display:block;border-radius:100px;position:absolute;box-sizing:border-box}.gg-eye::after{top:2px;box-shadow:inset 0 -8px 0 2px,inset 0 0 0 2px;width:24px;height:24px}.gg-eye::before{width:8px;height:8px;border:2px solid;bottom:4px;left:8px}.gg-heart{border:2px solid;border-top-left-radius:100px;border-top-right-radius:100px;width:10px;height:8px;border-bottom:0;box-sizing:border-box;position:relative;transform:translate(calc(-5px * var(--ggs, 1)), calc(-3px * var(--ggs, 1))) rotate(-45deg) scale(var(--ggs, 1));display:block}.gg-heart::after{border:2px solid;border-top-left-radius:100px;border-top-right-radius:100px;width:10px;height:8px;border-bottom:0;content:"";display:block;box-sizing:border-box;position:absolute}.gg-heart::before{content:"";display:block;box-sizing:border-box;position:absolute}.gg-heart::after{right:-9px;transform:rotate(90deg);top:5px}.gg-heart::before{width:11px;height:11px;border-left:2px solid;border-bottom:2px solid;left:-2px;top:3px}.gg-comment{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:20px;height:16px;border:2px solid;border-bottom:0;box-shadow:-6px 8px 0 -6px,6px 8px 0 -6px}.gg-comment::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px}.gg-comment::before{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;border:2px solid;border-top-color:rgba(0,0,0,0);border-bottom-left-radius:20px;right:4px;bottom:-6px;height:6px}.gg-comment::after{height:2px;background:currentColor;box-shadow:0 4px 0 0;left:4px;top:4px}.gg-share{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:6px;height:6px;background:currentColor;border-radius:100px;box-shadow:10px -6px 0,10px 6px 0}.gg-share::after{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:10px;height:2px;background:currentColor;left:2px}.gg-share::before{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:10px;height:2px;background:currentColor;left:2px;top:0;transform:rotate(-35deg)}.gg-share::after{bottom:0;transform:rotate(35deg)}.gg-software-download{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:16px;height:6px;border:2px solid;border-top:0;border-bottom-left-radius:2px;border-bottom-right-radius:2px;margin-top:8px}.gg-software-download::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;border-left:2px solid;border-bottom:2px solid;transform:rotate(-45deg);left:2px;bottom:4px}.gg-software-download::before{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:2px;height:10px;background:currentColor;left:5px;bottom:5px}.gg-lock{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:12px;height:11px;border:2px solid;border-top-right-radius:50%;border-top-left-radius:50%;border-bottom:rgba(0,0,0,0);margin-top:-12px}.gg-lock::after{content:"";display:block;box-sizing:border-box;position:absolute;width:16px;height:10px;border-radius:2px;border:2px solid rgba(0,0,0,0);box-shadow:0 0 0 2px;left:-4px;top:9px}.gg-lock-unlock{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:12px;height:6px;border:2px solid;border-top-right-radius:100px;border-top-left-radius:100px;border-bottom:rgba(0,0,0,0);margin-top:-18px;margin-left:-2px}.gg-lock-unlock::after,.gg-lock-unlock::before{content:"";display:block;box-sizing:border-box;position:absolute}.gg-lock-unlock::after{border:2px solid rgba(0,0,0,0);box-shadow:0 0 0 2px;width:16px;height:10px;border-radius:2px;left:-4px;top:10px}.gg-lock-unlock::before{width:2px;height:6px;background:currentColor;left:-2px;top:4px}.gg-music{display:block;box-sizing:border-box;border:2px solid;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:0;margin-top:-4px;position:relative;transform:skewY(-15deg) scale(var(--ggs, 1));width:14px;height:16px}.gg-music::after,.gg-music::before{display:block;box-sizing:border-box;border:2px solid}.gg-music::after,.gg-music::before{content:"";position:absolute;width:7px;height:7px;top:9px;left:-7px;transform:skewY(15deg);border-radius:10px}.gg-music::after{left:5px}/*# sourceMappingURL=cssgg.min.css.map */
+.gg-home{background:linear-gradient(to left, currentColor 5px, transparent 0) no-repeat 0 bottom/4px 2px,linear-gradient(to left, currentColor 5px, transparent 0) no-repeat right bottom/4px 2px;box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:18px;height:14px;border:2px solid;border-top:0;border-bottom:0;border-top-right-radius:3px;border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:0;margin-bottom:-2px}.gg-home::after{content:"";display:block;box-sizing:border-box;position:absolute}.gg-home::before{content:"";display:block;box-sizing:border-box;position:absolute;border-top:2px solid;border-left:2px solid;border-top-left-radius:4px;transform:rotate(45deg);top:-5px;border-radius:3px;width:14px;height:14px;left:0}.gg-home::after{width:8px;height:10px;border:2px solid;border-radius:100px;border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom:0;left:3px;bottom:0}.gg-options{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:10px;height:2px;box-shadow:-3px 4px 0 0,3px -4px 0 0}.gg-options::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;border:2px solid;border-radius:100%}.gg-options::before{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;border:2px solid;border-radius:100%;top:-7px;left:-4px}.gg-options::after{bottom:-7px;right:-4px}.gg-info{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:20px;height:20px;border:2px solid;border-radius:40px}.gg-info::after,.gg-info::before{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:2px;background:currentColor;left:7px}.gg-info::after{bottom:2px;height:8px}.gg-info::before{height:2px;top:2px}.gg-code-slash{display:block;position:relative;box-sizing:border-box;transform:rotate(15deg) scale(var(--ggs, 1));width:2px;height:16px;background:currentColor}.gg-code-slash::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;transform:rotate(-60deg)}.gg-code-slash::before{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;transform:rotate(-60deg);border-left:2px solid;border-top:2px solid;left:-8px;top:5px}.gg-code-slash::after{border-right:2px solid;border-bottom:2px solid;right:-8px;top:3px}.gg-search{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:16px;height:16px;border:2px solid;border-radius:100%;margin-left:-4px;margin-top:-4px}.gg-search::after{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:2px;height:8px;background:currentColor;transform:rotate(-45deg);top:10px;left:12px}.gg-feed{display:block;box-sizing:border-box;background:currentColor;box-shadow:0 10px 0 0;margin-left:-8px;margin-top:-8px;position:relative;transform:scale(var(--ggs, 1));width:7px;height:7px;border-radius:1px}.gg-feed::after,.gg-feed::before{display:block;box-sizing:border-box;background:currentColor;box-shadow:0 10px 0 0}.gg-feed::after,.gg-feed::before{content:"";position:absolute;border-radius:3px;width:12px;height:2px;top:1px;left:9px;opacity:.8}.gg-feed::after{width:8px;top:4px;opacity:.5}.gg-eye{position:relative;display:block;transform:scale(var(--ggs, 1));width:24px;height:18px;border-bottom-right-radius:100px;border-bottom-left-radius:100px;overflow:hidden;box-sizing:border-box}.gg-eye::after,.gg-eye::before{content:"";display:block;border-radius:100px;position:absolute;box-sizing:border-box}.gg-eye::after{top:2px;box-shadow:inset 0 -8px 0 2px,inset 0 0 0 2px;width:24px;height:24px}.gg-eye::before{width:8px;height:8px;border:2px solid;bottom:4px;left:8px}.gg-heart{border:2px solid;border-top-left-radius:100px;border-top-right-radius:100px;width:10px;height:8px;border-bottom:0;box-sizing:border-box;position:relative;transform:translate(calc(-5px * var(--ggs, 1)), calc(-3px * var(--ggs, 1))) rotate(-45deg) scale(var(--ggs, 1));display:block}.gg-heart::after{border:2px solid;border-top-left-radius:100px;border-top-right-radius:100px;width:10px;height:8px;border-bottom:0;content:"";display:block;box-sizing:border-box;position:absolute}.gg-heart::before{content:"";display:block;box-sizing:border-box;position:absolute}.gg-heart::after{right:-9px;transform:rotate(90deg);top:5px}.gg-heart::before{width:11px;height:11px;border-left:2px solid;border-bottom:2px solid;left:-2px;top:3px}.gg-comment{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:20px;height:16px;border:2px solid;border-bottom:0;box-shadow:-6px 8px 0 -6px,6px 8px 0 -6px}.gg-comment::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px}.gg-comment::before{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;border:2px solid;border-top-color:rgba(0,0,0,0);border-bottom-left-radius:20px;right:4px;bottom:-6px;height:6px}.gg-comment::after{height:2px;background:currentColor;box-shadow:0 4px 0 0;left:4px;top:4px}.gg-share{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:6px;height:6px;background:currentColor;border-radius:100px;box-shadow:10px -6px 0,10px 6px 0}.gg-share::after{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:10px;height:2px;background:currentColor;left:2px}.gg-share::before{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:10px;height:2px;background:currentColor;left:2px;top:0;transform:rotate(-35deg)}.gg-share::after{bottom:0;transform:rotate(35deg)}.gg-software-download{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:16px;height:6px;border:2px solid;border-top:0;border-bottom-left-radius:2px;border-bottom-right-radius:2px;margin-top:8px}.gg-software-download::after{content:"";display:block;box-sizing:border-box;position:absolute;width:8px;height:8px;border-left:2px solid;border-bottom:2px solid;transform:rotate(-45deg);left:2px;bottom:4px}.gg-software-download::before{content:"";display:block;box-sizing:border-box;position:absolute;border-radius:3px;width:2px;height:10px;background:currentColor;left:5px;bottom:5px}.gg-check-o{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:22px;height:22px;border:2px solid;border-radius:100px}.gg-check-o::after{content:"";display:block;box-sizing:border-box;position:absolute;left:3px;top:-1px;width:6px;height:10px;border-color:currentColor;border-width:0 2px 2px 0;border-style:solid;transform-origin:bottom left;transform:rotate(45deg)}.gg-lock{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:12px;height:11px;border:2px solid;border-top-right-radius:50%;border-top-left-radius:50%;border-bottom:rgba(0,0,0,0);margin-top:-12px}.gg-lock::after{content:"";display:block;box-sizing:border-box;position:absolute;width:16px;height:10px;border-radius:2px;border:2px solid rgba(0,0,0,0);box-shadow:0 0 0 2px;left:-4px;top:9px}.gg-lock-unlock{box-sizing:border-box;position:relative;display:block;transform:scale(var(--ggs, 1));width:12px;height:6px;border:2px solid;border-top-right-radius:100px;border-top-left-radius:100px;border-bottom:rgba(0,0,0,0);margin-top:-18px;margin-left:-2px}.gg-lock-unlock::after,.gg-lock-unlock::before{content:"";display:block;box-sizing:border-box;position:absolute}.gg-lock-unlock::after{border:2px solid rgba(0,0,0,0);box-shadow:0 0 0 2px;width:16px;height:10px;border-radius:2px;left:-4px;top:10px}.gg-lock-unlock::before{width:2px;height:6px;background:currentColor;left:-2px;top:4px}.gg-music{display:block;box-sizing:border-box;border:2px solid;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:0;margin-top:-4px;position:relative;transform:skewY(-15deg) scale(var(--ggs, 1));width:14px;height:16px}.gg-music::after,.gg-music::before{display:block;box-sizing:border-box;border:2px solid}.gg-music::after,.gg-music::before{content:"";position:absolute;width:7px;height:7px;top:9px;left:-7px;transform:skewY(15deg);border-radius:10px}.gg-music::after{left:5px}/*# sourceMappingURL=cssgg.min.css.map */
diff --git a/styles/vendor/cssgg.min.css.map b/styles/vendor/cssgg.min.css.map
index 846ac9c..cd52492 100644
--- a/styles/vendor/cssgg.min.css.map
+++ b/styles/vendor/cssgg.min.css.map
@@ -1 +1 @@
-{"version":3,"sourceRoot":"","sources":["../../misc/scss/node_modules/css.gg/icons/scss/home.scss","../../misc/scss/node_modules/css.gg/icons/scss/options.scss","../../misc/scss/node_modules/css.gg/icons/scss/info.scss","../../misc/scss/node_modules/css.gg/icons/scss/code-slash.scss","../../misc/scss/node_modules/css.gg/icons/scss/search.scss","../../misc/scss/node_modules/css.gg/icons/scss/feed.scss","../../misc/scss/node_modules/css.gg/icons/scss/eye.scss","../../misc/scss/node_modules/css.gg/icons/scss/heart.scss","../../misc/scss/node_modules/css.gg/icons/scss/comment.scss","../../misc/scss/node_modules/css.gg/icons/scss/share.scss","../../misc/scss/node_modules/css.gg/icons/scss/software-download.scss","../../misc/scss/node_modules/css.gg/icons/scss/lock.scss","../../misc/scss/node_modules/css.gg/icons/scss/lock-unlock.scss","../../misc/scss/node_modules/css.gg/icons/scss/music.scss"],"names":[],"mappings":"AAAA,SACE,yLACA,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,aACA,gBACA,4BACA,2BACA,6BACA,4BACA,mBAEA,gBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,cACA,sBACA,kBACA,qBACA,sBACA,2BACA,wBACA,SACA,kBACA,WACA,YACA,OAGF,gBACE,UACA,YACA,iBACA,oBACA,4BACA,6BACA,gBACA,SACA,SCjDJ,YACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,qCAEA,mBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,iBACA,mBAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,iBACA,mBACA,SACA,UAGF,mBACE,YACA,WCnCN,SACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBAEA,iCACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,wBACA,SAGF,gBACE,WACA,WAGF,iBACE,WACA,QC5BN,eACI,cACA,kBACA,sBACA,6CACA,UACA,YACA,wBAEA,sBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,yBAGF,uBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,yBACA,sBACA,qBACA,UACA,QAGF,sBACE,uBACA,wBACA,WACA,QCrCN,WACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBACA,iBACA,gBAEA,kBACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,WACA,wBACA,yBACA,SACA,UCvBN,SACI,cACA,sBACA,wBACA,sBASA,iBACA,gBACA,kBACA,+BACA,UACA,WACA,kBAbA,iCACE,cACA,sBACA,wBACA,sBAWF,iCACE,WACA,kBACA,kBACA,WACA,WACA,QACA,SACA,WAGF,gBACE,UACA,QACA,WCnCN,QACI,kBACA,cACA,+BACA,WACA,YACA,iCACA,gCACA,gBACA,sBAEA,+BACE,WACA,cACA,oBACA,kBACA,sBAGF,eACE,QACA,8CACA,WACA,YAGF,gBACE,UACA,WACA,iBACA,WACA,SC/BN,UACI,iBACA,6BACA,8BACA,WACA,WACA,gBAeA,sBACA,kBACA,gHACA,cAhBA,iBACE,iBACA,6BACA,8BACA,WACA,WACA,gBACA,WACA,cACA,sBACA,kBAQF,kBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,wBACA,QAGF,kBACE,WACA,YACA,sBACA,wBACA,UACA,QC7CN,YACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,gBACA,0CAEA,mBACE,WACA,cACA,sBACA,kBACA,UAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,iBACA,+BACA,+BACA,UACA,YACA,WAGF,mBACE,WACA,wBACA,qBACA,SACA,QCtCN,UACI,sBACA,kBACA,cACA,+BACA,UACA,WACA,wBACA,oBACA,kCAEA,iBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SAGF,kBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SACA,MACA,yBAGF,iBACE,SACA,wBCvCN,sBACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,iBACA,aACA,8BACA,+BACA,eAEA,6BACE,WACA,cACA,sBACA,kBACA,UACA,WACA,sBACA,wBACA,yBACA,SACA,WAGF,8BACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,YACA,wBACA,SACA,WCrCN,SACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,4BACA,2BACA,4BACA,iBAEA,gBACE,WACA,cACA,sBACA,kBACA,WACA,YACA,kBACA,+BACA,qBACA,UACA,QCxBN,gBACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,iBACA,8BACA,6BACA,4BACA,iBACA,iBAEA,+CACE,WACA,cACA,sBACA,kBAGF,uBACE,+BACA,qBACA,WACA,YACA,kBACA,UACA,SAGF,wBACE,UACA,WACA,wBACA,UACA,QCpCN,UACI,cACA,sBACA,iBAQA,2BACA,4BACA,gBACA,gBACA,kBACA,6CACA,WACA,YAbA,mCACE,cACA,sBACA,iBAYF,mCACE,WACA,kBACA,UACA,WACA,QACA,UACA,uBACA,mBAGF,iBACE","file":"cssgg.min.css"}
\ No newline at end of file
+{"version":3,"sourceRoot":"","sources":["../../misc/scss/node_modules/css.gg/icons/scss/home.scss","../../misc/scss/node_modules/css.gg/icons/scss/options.scss","../../misc/scss/node_modules/css.gg/icons/scss/info.scss","../../misc/scss/node_modules/css.gg/icons/scss/code-slash.scss","../../misc/scss/node_modules/css.gg/icons/scss/search.scss","../../misc/scss/node_modules/css.gg/icons/scss/feed.scss","../../misc/scss/node_modules/css.gg/icons/scss/eye.scss","../../misc/scss/node_modules/css.gg/icons/scss/heart.scss","../../misc/scss/node_modules/css.gg/icons/scss/comment.scss","../../misc/scss/node_modules/css.gg/icons/scss/share.scss","../../misc/scss/node_modules/css.gg/icons/scss/software-download.scss","../../misc/scss/node_modules/css.gg/icons/scss/check-o.scss","../../misc/scss/node_modules/css.gg/icons/scss/lock.scss","../../misc/scss/node_modules/css.gg/icons/scss/lock-unlock.scss","../../misc/scss/node_modules/css.gg/icons/scss/music.scss"],"names":[],"mappings":"AAAA,SACE,yLACA,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,aACA,gBACA,4BACA,2BACA,6BACA,4BACA,mBAEA,gBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,cACA,sBACA,kBACA,qBACA,sBACA,2BACA,wBACA,SACA,kBACA,WACA,YACA,OAGF,gBACE,UACA,YACA,iBACA,oBACA,4BACA,6BACA,gBACA,SACA,SCjDJ,YACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,qCAEA,mBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,iBACA,mBAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,iBACA,mBACA,SACA,UAGF,mBACE,YACA,WCnCN,SACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBAEA,iCACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,wBACA,SAGF,gBACE,WACA,WAGF,iBACE,WACA,QC5BN,eACI,cACA,kBACA,sBACA,6CACA,UACA,YACA,wBAEA,sBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,yBAGF,uBACE,WACA,cACA,sBACA,kBACA,UACA,WACA,yBACA,sBACA,qBACA,UACA,QAGF,sBACE,uBACA,wBACA,WACA,QCrCN,WACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,mBACA,iBACA,gBAEA,kBACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,WACA,wBACA,yBACA,SACA,UCvBN,SACI,cACA,sBACA,wBACA,sBASA,iBACA,gBACA,kBACA,+BACA,UACA,WACA,kBAbA,iCACE,cACA,sBACA,wBACA,sBAWF,iCACE,WACA,kBACA,kBACA,WACA,WACA,QACA,SACA,WAGF,gBACE,UACA,QACA,WCnCN,QACI,kBACA,cACA,+BACA,WACA,YACA,iCACA,gCACA,gBACA,sBAEA,+BACE,WACA,cACA,oBACA,kBACA,sBAGF,eACE,QACA,8CACA,WACA,YAGF,gBACE,UACA,WACA,iBACA,WACA,SC/BN,UACI,iBACA,6BACA,8BACA,WACA,WACA,gBAeA,sBACA,kBACA,gHACA,cAhBA,iBACE,iBACA,6BACA,8BACA,WACA,WACA,gBACA,WACA,cACA,sBACA,kBAQF,kBACE,WACA,cACA,sBACA,kBAGF,iBACE,WACA,wBACA,QAGF,kBACE,WACA,YACA,sBACA,wBACA,UACA,QC7CN,YACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,gBACA,0CAEA,mBACE,WACA,cACA,sBACA,kBACA,UAGF,oBACE,WACA,cACA,sBACA,kBACA,UACA,iBACA,+BACA,+BACA,UACA,YACA,WAGF,mBACE,WACA,wBACA,qBACA,SACA,QCtCN,UACI,sBACA,kBACA,cACA,+BACA,UACA,WACA,wBACA,oBACA,kCAEA,iBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SAGF,kBACE,WACA,cACA,sBACA,kBACA,kBACA,WACA,WACA,wBACA,SACA,MACA,yBAGF,iBACE,SACA,wBCvCN,sBACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,iBACA,aACA,8BACA,+BACA,eAEA,6BACE,WACA,cACA,sBACA,kBACA,UACA,WACA,sBACA,wBACA,yBACA,SACA,WAGF,8BACE,WACA,cACA,sBACA,kBACA,kBACA,UACA,YACA,wBACA,SACA,WCrCN,YACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,oBAEA,mBACE,WACA,cACA,sBACA,kBACA,SACA,SACA,UACA,YACA,0BACA,yBACA,mBACA,6BACA,wBCvBN,SACI,sBACA,kBACA,cACA,+BACA,WACA,YACA,iBACA,4BACA,2BACA,4BACA,iBAEA,gBACE,WACA,cACA,sBACA,kBACA,WACA,YACA,kBACA,+BACA,qBACA,UACA,QCxBN,gBACI,sBACA,kBACA,cACA,+BACA,WACA,WACA,iBACA,8BACA,6BACA,4BACA,iBACA,iBAEA,+CACE,WACA,cACA,sBACA,kBAGF,uBACE,+BACA,qBACA,WACA,YACA,kBACA,UACA,SAGF,wBACE,UACA,WACA,wBACA,UACA,QCpCN,UACI,cACA,sBACA,iBAQA,2BACA,4BACA,gBACA,gBACA,kBACA,6CACA,WACA,YAbA,mCACE,cACA,sBACA,iBAYF,mCACE,WACA,kBACA,UACA,WACA,QACA,UACA,uBACA,mBAGF,iBACE","file":"cssgg.min.css"}
\ No newline at end of file
diff --git a/templates/components/details.latte b/templates/components/details.latte
new file mode 100644
index 0000000..66a17c1
--- /dev/null
+++ b/templates/components/details.latte
@@ -0,0 +1,4 @@
+
+ {$title}
+ {block content}{/block}
+
diff --git a/templates/components/head.latte b/templates/components/head.latte
index dca9c55..d7dd4c6 100644
--- a/templates/components/head.latte
+++ b/templates/components/head.latte
@@ -31,6 +31,7 @@
{/if}
+
{$title} - ProxiTok
diff --git a/templates/components/themes/common/content.latte b/templates/components/themes/common/content.latte
index 9ef7827..0257da5 100644
--- a/templates/components/themes/common/content.latte
+++ b/templates/components/themes/common/content.latte
@@ -3,19 +3,25 @@
{else}
-
-
- {foreach $item->imagePost->images as $i => $image}
-
-
})
-
- {/foreach}
-
-
- {for $i = 0; $i < count($item->imagePost->images); $i++}
-
{$i + 1}
- {/for}
-
-
-
+{if isset($isSimple)}
+ {foreach $item->imagePost->images as $i => $image}
+
+ {/foreach}
+{else}
+
+
+ {foreach $item->imagePost->images as $i => $image}
+
+
})
+
+ {/foreach}
+
+
+ {for $i = 0; $i < count($item->imagePost->images); $i++}
+
{$i + 1}
+ {/for}
+
+
+
+ {/if}
{/if}
diff --git a/templates/components/themes/common/tags.latte b/templates/components/themes/common/tags.latte
index 89be8bf..f47e230 100644
--- a/templates/components/themes/common/tags.latte
+++ b/templates/components/themes/common/tags.latte
@@ -1,5 +1,5 @@
diff --git a/templates/components/themes/default.latte b/templates/components/themes/default.latte
index da3556a..a4e0390 100644
--- a/templates/components/themes/default.latte
+++ b/templates/components/themes/default.latte
@@ -17,17 +17,30 @@
{if !empty($item->challenges)}
{include './common/tags.latte', challenges: $item->challenges}
{/if}
- {render_desc($item->desc, $item->textExtra)|noescape}
+ {render_desc($item->desc, $item->textExtra ?? [])|noescape}
Song: {$item->music->title}
{include './common/stats.latte', playCount: $item->stats->playCount, diggCount: $item->stats->diggCount, commentCount: $item->stats->commentCount, shareCount: $item->stats->shareCount}
{include './common/content.latte', item: $item, isAutoplay: false, isBig: false}
+ {if isset($item->video->playAddr) && $item->video->playAddr !== ""}
+
Download video
{include './common/download.latte', playAddr: $item->video->playAddr, id: $item->id, uniqueId: $item->author->uniqueId}
+ {/if}
Share link
{include './common/share.latte', uniqueId: $item->author->uniqueId, id: $item->id}
+
+ {embed '../details.latte', title: "Details"}
+ {block content}
+
Is Ad: {bool_to_str($item->isAd)}
+
Can duet: {bool_to_str($item->duetEnabled)}
+
Can stitch (add this video to other ones): {bool_to_str($item->stitchEnabled)}
+
Can be shared: {bool_to_str($item->shareEnabled)}
+ {/block}
+ {/embed}
+
{/foreach}
diff --git a/templates/views/rss.latte b/templates/views/rss.latte
index bf48f59..bd70d97 100644
--- a/templates/views/rss.latte
+++ b/templates/views/rss.latte
@@ -1,4 +1,3 @@
-{contentType application/rss+xml}
@@ -9,7 +8,7 @@
{foreach $items as $item}
-
{$item->desc}
- {$item->desc}]]>
+ {render_desc($item->desc, $item->textExtra ?? [])|noescape}{include '../components/themes/common/content.latte', item: $item, isAutoplay: false, isSimple: true}]]>
{url_video_internal($item->author->uniqueId, $item->id)}
{date('r', $item->createTime)}
{$item->id}
diff --git a/templates/views/tag.latte b/templates/views/tag.latte
index 3de0384..0e0671b 100644
--- a/templates/views/tag.latte
+++ b/templates/views/tag.latte
@@ -14,7 +14,12 @@
{/if}
{$info->detail->title}
{include '../components/rss.latte'}
- Videos: {number($info->stats->videoCount)} / Views: {number($info->stats->viewCount)}
+ Views: {number($info->stats->viewCount)}
+ {embed '../components/details.latte', title: 'Details'}
+ {block content}
+ Is commerce: {bool_to_str($info->detail->isCommerce)}
+ {/block}
+ {/embed}
{/block}
{block content}
diff --git a/templates/views/user.latte b/templates/views/user.latte
index f8708a6..9f01839 100644
--- a/templates/views/user.latte
+++ b/templates/views/user.latte
@@ -10,17 +10,33 @@
- {$info->detail->uniqueId}
+
+ {if $info->detail->verified}
+ {include '../components/icon.latte', icon: 'check-o', text: $info->detail->uniqueId}
+ {else}
+ {$info->detail->uniqueId}
+ {/if}
+
{include '../components/rss.latte'}
{if $info->detail->privateAccount}
Private account
{/if}
- {$info->detail->signature}
+ Description
+ {$info->detail->signature}
{if isset($info->detail->bioLink)}
Link: {$info->detail->bioLink->link}
{/if}
+ Stats
Following: {number($info->stats->followingCount)} / Followers: {number($info->stats->followerCount)}
Hearts: {number($info->stats->heartCount)} / Videos: {$info->stats->videoCount}
+ {embed '../components/details.latte', title: "Details"}
+ {block content}
+ Region: {$info->detail->region}
+ {if $info->detail->commerceUserInfo->commerceUser}
+ Category: {$info->detail->commerceUserInfo->category}
+ {/if}
+ {/block}
+ {/embed}
{/block}
{block content}
diff --git a/templates/views/video.latte b/templates/views/video.latte
index c142d22..81d14ba 100644
--- a/templates/views/video.latte
+++ b/templates/views/video.latte
@@ -33,13 +33,16 @@
{include '../components/themes/common/tags.latte', challenges: $item->challenges}
{/if}
-
{render_desc($item->desc, $item->textExtra)|noescape}
+
{render_desc($item->desc, $item->textExtra ?? [])|noescape}
Song: {$item->music->title}
{include '../components/themes/common/stats.latte', playCount: $item->stats->playCount, diggCount: $item->stats->diggCount, commentCount: $item->stats->commentCount, shareCount: $item->stats->shareCount}
{include '../components/themes/common/share.latte', uniqueId: $info->detail->uniqueId, id: $item->id}
+ {if isset($item->video->playAddr) && $item->video->playAddr !== ""}
+
{include '../components/themes/common/download.latte', playAddr: $item->video->playAddr, id: $item->id, uniqueId: $info->detail->uniqueId}
+ {/if}