Skip to content
This repository has been archived by the owner on Dec 25, 2023. It is now read-only.

Commit

Permalink
Pre-render HTML header on server-side
Browse files Browse the repository at this point in the history
  • Loading branch information
nagmat84 committed Oct 23, 2022
1 parent 3acd822 commit 04973e7
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 143 deletions.
239 changes: 103 additions & 136 deletions html/frontend.html
Original file line number Diff line number Diff line change
@@ -1,152 +1,119 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="dist/frontend.css">
<link type="text/css" rel="stylesheet" href="dist/user.css">
<link rel="shortcut icon" href="favicon.ico">
<link rel="apple-touch-icon" href="img/apple-touch-icon-ipad.png" sizes="120x120">
<link rel="apple-touch-icon" href="img/apple-touch-icon-iphone.png" sizes="152x152">
<link rel="apple-touch-icon" href="img/apple-touch-icon-iphone-plus.png" sizes="180x180">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=4.0, user-scalable=yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="generator" content="Lychee v4">
<!-- Meta data which is set programmatically via JS -->
<title></title>
<meta name="description" content="">
<meta name="author" content="">
<meta name="publisher" content="">
<!-- Twitter Meta Data -->
<meta name="twitter:title" content="">
<meta name="twitter:description" content="">
<meta name="twitter:image" content="">
<!-- OpenGraph Meta Data (e.g. used by Facebook) -->
<meta property="og:title" content="">
<meta property="og:description" content="">
<meta property="og:image" content="">
<meta property="og:url" content="">
</head>
<body class="mode-none">
<!-- This file contains the actual HTML body only. The HTML header is pre-rendered by the backend -->

<!-- inject:svg -->
<!-- endinject -->

<!-- DIV for the loading indicator -->
<div id="loading"></div>
<!-- DIV for the loading indicator -->
<div id="loading"></div>

<!-- TODO: Header is invisible for "frame" mode, but visible for "view" and "gallery" -->
<header class="header">
<div class="header__toolbar header__toolbar--public">
<a class="button" id="button_signin"><svg class="iconic"><use xlink:href="#account-login" /></svg></a>
<a class="header__title"></a>
<div class="header__search__field">
<input class="header__search" type="text" name="search">
<a class="header__clear">&times;</a>
</div>
<a class="button button--map-albums"><svg class="iconic"><use xlink:href="#map" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--albums">
<a class="button" id="button_settings"><svg class="iconic"><use xlink:href="#cog" /></svg></a>
<a class="header__title"></a>
<div class="header__search__field">
<input class="header__search" type="text" name="search">
<a class="header__clear">&times;</a>
</div>
<a class="header__divider"></a>
<a class="button button--map-albums"><svg class="iconic"><use xlink:href="#map" /></svg></a>
<a class="button button_add"><svg class="iconic"><use xlink:href="#plus" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--album">
<a class="button" id="button_back_home"><svg class="iconic"><use xlink:href="#chevron-left" /></svg></a>
<a class="header__title"></a>
<a class="button button--eye" id="button_visibility_album"><svg class="iconic iconic--eye"><use xlink:href="#eye" /></svg></a>
<a class="button" id="button_sharing_album_users"><svg class="iconic"><use xlink:href="#people" /></svg></a>
<a class="button button--nsfw" id="button_nsfw_album"><svg class="iconic"><use xlink:href="#warning" /></svg></a>
<a class="button button--share" id="button_share_album"><svg class="iconic ionicons"><use xlink:href="#share-ion" /></svg></a>
<a class="button" id="button_archive"><svg class="iconic"><use xlink:href="#cloud-download" /></svg></a>
<a class="button button--info" id="button_info_album"><svg class="iconic"><use xlink:href="#info" /></svg></a>
<a class="button button--map" id="button_map_album"><svg class="iconic"><use xlink:href="#map" /></svg></a>
<a class="button" id="button_move_album"><svg class="iconic"><use xlink:href="#folder" /></svg></a>
<a class="button" id="button_trash_album"><svg class="iconic"><use xlink:href="#trash" /></svg></a>
<a class="button" id="button_fs_album_enter"><svg class="iconic"><use xlink:href="#fullscreen-enter" /></svg></a>
<a class="button" id="button_fs_album_exit"><svg class="iconic"><use xlink:href="#fullscreen-exit" /></svg></a>
<a class="header__divider"></a>
<a class="button button_add"><svg class="iconic"><use xlink:href="#plus" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--photo">
<a class="button" id="button_back"><svg class="iconic"><use xlink:href="#chevron-left" /></svg></a>
<a class="header__title"></a>
<a class="button button--star" id="button_star"><svg class="iconic"><use xlink:href="#star" /></svg></a>
<a class="button button--eye" id="button_visibility"><svg class="iconic"><use xlink:href="#eye" /></svg></a>
<a class="button button--rotate" id="button_rotate_ccwise"><svg class="iconic"><use xlink:href="#counterclockwise" /></svg></a>
<a class="button button--rotate" id="button_rotate_cwise"><svg class="iconic"><use xlink:href="#clockwise" /></svg></a>
<a class="button button--share" id="button_share"><svg class="iconic ionicons"><use xlink:href="#share-ion" /></svg></a>
<a class="button button--info" id="button_info"><svg class="iconic"><use xlink:href="#info" /></svg></a>
<a class="button button--map" id="button_map"><svg class="iconic"><use xlink:href="#map" /></svg></a>
<a class="button" id="button_move"><svg class="iconic"><use xlink:href="#folder" /></svg></a>
<a class="button" id="button_trash"><svg class="iconic"><use xlink:href="#trash" /></svg></a>
<a class="button" id="button_fs_enter"><svg class="iconic"><use xlink:href="#fullscreen-enter" /></svg></a>
<a class="button" id="button_fs_exit"><svg class="iconic"><use xlink:href="#fullscreen-exit" /></svg></a>
<a class="header__divider"></a>
<a class="button" id="button_more"><svg class="iconic"><use xlink:href="#ellipses" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--map">
<a class="button" id="button_back_map"><svg class="iconic"><use xlink:href="#chevron-left" /></svg></a>
<a class="header__title"></a>
<!-- TODO: Header is invisible for "frame" mode, but visible for "view" and "gallery" -->
<header class="header">
<div class="header__toolbar header__toolbar--public">
<a class="button" id="button_signin"><svg class="iconic"><use xlink:href="#account-login" /></svg></a>
<a class="header__title"></a>
<div class="header__search__field">
<input class="header__search" type="text" name="search">
<a class="header__clear">&times;</a>
</div>
<div class="header__toolbar header__toolbar--config">
<a class="button" id="button_close_config"><svg class="iconic"><use xlink:href="#plus" /></svg></a>
<a class="header__title"></a>
<a class="button button--map-albums"><svg class="iconic"><use xlink:href="#map" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--albums">
<a class="button" id="button_settings"><svg class="iconic"><use xlink:href="#cog" /></svg></a>
<a class="header__title"></a>
<div class="header__search__field">
<input class="header__search" type="text" name="search">
<a class="header__clear">&times;</a>
</div>
</header>

<div id="container">
<!-- leftMenu -->
<div class="leftMenu"></div>

<!-- Content -->
<div class="content"></div>
<a class="header__divider"></a>
<a class="button button--map-albums"><svg class="iconic"><use xlink:href="#map" /></svg></a>
<a class="button button_add"><svg class="iconic"><use xlink:href="#plus" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--album">
<a class="button" id="button_back_home"><svg class="iconic"><use xlink:href="#chevron-left" /></svg></a>
<a class="header__title"></a>
<a class="button button--eye" id="button_visibility_album"><svg class="iconic iconic--eye"><use xlink:href="#eye" /></svg></a>
<a class="button" id="button_sharing_album_users"><svg class="iconic"><use xlink:href="#people" /></svg></a>
<a class="button button--nsfw" id="button_nsfw_album"><svg class="iconic"><use xlink:href="#warning" /></svg></a>
<a class="button button--share" id="button_share_album"><svg class="iconic ionicons"><use xlink:href="#share-ion" /></svg></a>
<a class="button" id="button_archive"><svg class="iconic"><use xlink:href="#cloud-download" /></svg></a>
<a class="button button--info" id="button_info_album"><svg class="iconic"><use xlink:href="#info" /></svg></a>
<a class="button button--map" id="button_map_album"><svg class="iconic"><use xlink:href="#map" /></svg></a>
<a class="button" id="button_move_album"><svg class="iconic"><use xlink:href="#folder" /></svg></a>
<a class="button" id="button_trash_album"><svg class="iconic"><use xlink:href="#trash" /></svg></a>
<a class="button" id="button_fs_album_enter"><svg class="iconic"><use xlink:href="#fullscreen-enter" /></svg></a>
<a class="button" id="button_fs_album_exit"><svg class="iconic"><use xlink:href="#fullscreen-exit" /></svg></a>
<a class="header__divider"></a>
<a class="button button_add"><svg class="iconic"><use xlink:href="#plus" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--photo">
<a class="button" id="button_back"><svg class="iconic"><use xlink:href="#chevron-left" /></svg></a>
<a class="header__title"></a>
<a class="button button--star" id="button_star"><svg class="iconic"><use xlink:href="#star" /></svg></a>
<a class="button button--eye" id="button_visibility"><svg class="iconic"><use xlink:href="#eye" /></svg></a>
<a class="button button--rotate" id="button_rotate_ccwise"><svg class="iconic"><use xlink:href="#counterclockwise" /></svg></a>
<a class="button button--rotate" id="button_rotate_cwise"><svg class="iconic"><use xlink:href="#clockwise" /></svg></a>
<a class="button button--share" id="button_share"><svg class="iconic ionicons"><use xlink:href="#share-ion" /></svg></a>
<a class="button button--info" id="button_info"><svg class="iconic"><use xlink:href="#info" /></svg></a>
<a class="button button--map" id="button_map"><svg class="iconic"><use xlink:href="#map" /></svg></a>
<a class="button" id="button_move"><svg class="iconic"><use xlink:href="#folder" /></svg></a>
<a class="button" id="button_trash"><svg class="iconic"><use xlink:href="#trash" /></svg></a>
<a class="button" id="button_fs_enter"><svg class="iconic"><use xlink:href="#fullscreen-enter" /></svg></a>
<a class="button" id="button_fs_exit"><svg class="iconic"><use xlink:href="#fullscreen-exit" /></svg></a>
<a class="header__divider"></a>
<a class="button" id="button_more"><svg class="iconic"><use xlink:href="#ellipses" /></svg></a>
</div>
<div class="header__toolbar header__toolbar--map">
<a class="button" id="button_back_map"><svg class="iconic"><use xlink:href="#chevron-left" /></svg></a>
<a class="header__title"></a>
</div>
<div class="header__toolbar header__toolbar--config">
<a class="button" id="button_close_config"><svg class="iconic"><use xlink:href="#plus" /></svg></a>
<a class="header__title"></a>
</div>
</header>

<!-- MapView -->
<div id="mapview">
<div id="leaflet_map_full"></div>
</div>
<div id="container">
<!-- leftMenu -->
<div class="leftMenu"></div>

<!-- ImageView -->
<div id="imageview"></div>
<!-- Content -->
<div class="content"></div>

<!-- Sidebar -->
<div class="sidebar">
<div class="sidebar__header"><h1></h1></div>
<div class="sidebar__wrapper"></div>
</div>
<!-- MapView -->
<div id="mapview">
<div id="leaflet_map_full"></div>
</div>

<!-- Warning -->
<div id="sensitive_warning" style="display: none;"><h1></h1><p></p><p></p></div>
<!-- ImageView -->
<div id="imageview"></div>

<!-- Upload TODO: Figure out how this works -->
<div id="upload">
<input id="upload_files" type="file" name="fileElem[]" multiple accept="image/*,video/*,.mov">
<input id="upload_track_file" type="file" name="fileElem" accept="application/x-gpx+xml">
</div>
<!-- Sidebar -->
<div class="sidebar">
<div class="sidebar__header"><h1></h1></div>
<div class="sidebar__wrapper"></div>
</div>

<div id="frame">
<img id="background" alt="image background" src=""/>
<canvas id="background_canvas"></canvas>
<div id="noise"></div>
<div class="image_container"><img id="picture" alt="Random Image" src=""/></div>
<div id="frame-shutter"></div>
</div>
<!-- Warning -->
<div id="sensitive_warning" style="display: none;"><h1></h1><p></p><p></p></div>

<div id="footer" class="animate animate-up hide_footer">
<div id="home_socials" class="animate animate-up"><a class="socialicons" id="facebook" target="_blank" rel="noopener"></a><a class="socialicons" id="flickr" target="_blank" rel="noopener"></a><a class="socialicons" id="twitter" target="_blank" rel="noopener"></a><a class="socialicons" id="instagram" target="_blank" rel="noopener"></a><a class="socialicons" id="youtube" target="_blank" rel="noopener"></a></div>
<p class="home_copyright"></p>
<p class="personal_text"></p>
<p class="hosted_by"><a rel="noopener noreferrer" target="_blank" href="https://LycheeOrg.github.io" tabindex="-1"></a></p>
<!-- Upload TODO: Figure out how this works -->
<div id="upload">
<input id="upload_files" type="file" name="fileElem[]" multiple accept="image/*,video/*,.mov">
<input id="upload_track_file" type="file" name="fileElem" accept="application/x-gpx+xml">
</div>
</div>

<div id="frame">
<img id="background" alt="image background" src=""/>
<canvas id="background_canvas"></canvas>
<div id="noise"></div>
<div class="image_container"><img id="picture" alt="Random Image" src=""/></div>
<div id="frame-shutter"></div>
</div>

<script async defer type="text/javascript" src="dist/frontend.js"></script>
<script async defer type="text/javascript" src="dist/WebAuthn.js"></script>
</body>
</html>
<div id="footer" class="animate animate-up hide_footer">
<div id="home_socials" class="animate animate-up"><a class="socialicons" id="facebook" target="_blank" rel="noopener"></a><a class="socialicons" id="flickr" target="_blank" rel="noopener"></a><a class="socialicons" id="twitter" target="_blank" rel="noopener"></a><a class="socialicons" id="instagram" target="_blank" rel="noopener"></a><a class="socialicons" id="youtube" target="_blank" rel="noopener"></a></div>
<p class="home_copyright"></p>
<p class="personal_text"></p>
<p class="hosted_by"><a rel="noopener noreferrer" target="_blank" href="https://LycheeOrg.github.io" tabindex="-1"></a></p>
</div>
37 changes: 30 additions & 7 deletions scripts/main/lychee.js
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,11 @@ lychee.reloadIfLegacyIDs = function (albumID, photoID, autoplay) {

/**
* This is a "God method" that is used to load pretty much anything, based
* on what's in the web browser's URL bar after the '#' character:
* on what's in the web browser's URL.
*
* Traditionally, Lychee has been using client-side navigation based on
* URL fragments (i.e. based on the part after the '#' character)
* Fragments can match one of the following cases:
*
* - (nothing): load root album, assign `null` to `albumID` and `photoID`
* - `{albumID}`: load the album; `albumID` equals the given ID, `photoID` is
Expand All @@ -889,16 +893,35 @@ lychee.reloadIfLegacyIDs = function (albumID, photoID, autoplay) {
* which assumes that the user is always unauthenticated.
* - `frame`: shows random, starred photos in a kiosk mode
*
* Additionally, Lychee supports the following proper paths:
*
* - `/view/{photoID}` and `/view?p={photoID}`: See `view/{photoID}` above
* for the fragment-based approach
* - `/frame`: See `frame` above for the fragment-based approach.
*
* @param {boolean} [autoplay=true]
* @returns {void}
*/
lychee.load = function (autoplay = true) {
let hash = document.location.hash.replace("#", "").split("/");
let albumID = hash[0];
if (albumID === SearchAlbumIDPrefix && hash.length > 1) {
albumID += "/" + hash[1];
let albumID = "";
let photoID = "";

const viewMatch = document.location.href.match(/\/view(?:\/|(\?p=))(?<photoID>[-_0-9A-Za-z]+)$/);
const hashMatch = document.location.hash.replace("#", "").split("/");

if (/\/frame\/?$/.test(document.location.href)) {
albumID = "frame";
photoID = "";
} else if (viewMatch !== null && viewMatch.groups.photoID) {
albumID = "view";
photoID = viewMatch.groups.photoID;
} else {
albumID = hashMatch[0];
if (albumID === SearchAlbumIDPrefix && hashMatch.length > 1) {
albumID += "/" + hashMatch[1];
}
photoID = hashMatch[album.isSearchID(albumID) ? 2 : 1];
}
let photoID = hash[album.isSearchID(albumID) ? 2 : 1];

contextMenu.close();
multiselect.close();
Expand Down Expand Up @@ -1054,7 +1077,7 @@ lychee.load = function (autoplay = true) {
view.album.content.restoreScroll();
} else if (album.isSearchID(albumID)) {
// Search has been triggered
let search_string = decodeURIComponent(hash[1]).trim();
let search_string = decodeURIComponent(hashMatch[1]).trim();

if (search_string === "") {
// do nothing on "only space" search strings
Expand Down

0 comments on commit 04973e7

Please sign in to comment.