mirror of
https://github.com/alexankitty/Myrient-Search-Engine.git
synced 2026-01-15 08:23:18 -03:00
add load spinner
add flag icons add console icons
This commit is contained in:
22
lib/consoleicons.js
Normal file
22
lib/consoleicons.js
Normal file
@@ -0,0 +1,22 @@
|
||||
export default class ConsoleIcons {
|
||||
constructor(consoleData){
|
||||
this.consoleData = consoleData
|
||||
}
|
||||
|
||||
getConsoleImage(console){
|
||||
return this.consoleData[console]?.icon
|
||||
}
|
||||
ifConsoleExists(console){
|
||||
return this.consoleData[console] ? true : false
|
||||
}
|
||||
createConsoleImage(console){
|
||||
//fixups
|
||||
console = console.replace('Sony PlayStation', 'PlayStation')
|
||||
console = console.replace('Microsoft Xbox', 'Xbox')
|
||||
console = console.replace(/^Xbox$/, 'Xbox Classic')
|
||||
if(this.ifConsoleExists(console)){
|
||||
return `<img class='console' src='/proxy-image?url=${encodeURIComponent(this.getConsoleImage(console))}'>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
41
lib/flag.js
Normal file
41
lib/flag.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import fs from "fs";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const flagsDir = path.join(__dirname, "../views/public/images/flags");
|
||||
|
||||
|
||||
export default class Flags {
|
||||
constructor() {
|
||||
this.flags = this.getAvailableFlags();
|
||||
this.basePath = '/public/images/flags/'
|
||||
}
|
||||
|
||||
getAvailableFlags() {
|
||||
try {
|
||||
return fs
|
||||
.readdirSync(flagsDir)
|
||||
.filter((file) => file.endsWith(".png"))
|
||||
.map((file) => path.basename(file, ".png"));
|
||||
} catch (error) {
|
||||
console.error("Error reading flags directory:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
ifFlagExists(string){
|
||||
return this.flags.includes(string)
|
||||
}
|
||||
|
||||
getFlagPath(string){
|
||||
return `${this.basePath}${string}.png`
|
||||
}
|
||||
|
||||
createFlag(string){
|
||||
if(this.ifFlagExists(string)){
|
||||
return `<img class="flag" src="${this.getFlagPath(string)}"></img>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
13
server.js
13
server.js
@@ -22,6 +22,8 @@ import i18n, { locales } from "./config/i18n.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { optimizeDatabaseKws } from "./lib/dboptimize.js";
|
||||
import MetadataSearch from "./lib/metadatasearch.js";
|
||||
import Flag from "./lib/flag.js";
|
||||
import ConsoleIcons from "./lib/consoleicons.js";
|
||||
|
||||
let categoryListPath = "./lib/categories.json";
|
||||
let nonGameTermsPath = "./lib/nonGameTerms.json";
|
||||
@@ -33,6 +35,8 @@ let crawlTime = 0;
|
||||
let queryCount = 0;
|
||||
let fileCount = 0;
|
||||
let indexPage = "pages/index";
|
||||
let flags = new Flag();
|
||||
let consoleIcons = new ConsoleIcons(emulatorsData);
|
||||
|
||||
// Initialize databases
|
||||
await initDB();
|
||||
@@ -200,7 +204,8 @@ app.get("/search", async function (req, res) {
|
||||
if (settings.combineWith != "AND") {
|
||||
delete settings.combineWith;
|
||||
}
|
||||
let loadOldResults = req.query.old === "true" || !metadataSearch.authorized ? true : false
|
||||
let loadOldResults =
|
||||
req.query.old === "true" || !metadataSearch.authorized ? true : false;
|
||||
settings.pageSize = loadOldResults ? 100 : 10;
|
||||
settings.page = pageNum - 1;
|
||||
settings.sort = req.query.o || "";
|
||||
@@ -225,6 +230,8 @@ app.get("/search", async function (req, res) {
|
||||
indexing: search.indexing,
|
||||
urlPrefix: urlPrefix,
|
||||
settings: settings,
|
||||
flags: flags,
|
||||
consoleIcons: consoleIcons
|
||||
};
|
||||
let page = loadOldResults ? "resultsold" : "results";
|
||||
options = buildOptions(page, options);
|
||||
@@ -259,7 +266,7 @@ app.get("/lucky", async function (req, res) {
|
||||
app.get("/settings", function (req, res) {
|
||||
let options = { defaultSettings: defaultSettings };
|
||||
let page = "settings";
|
||||
options.oldSettingsAvailable = metadataSearch.authorized
|
||||
options.oldSettingsAvailable = metadataSearch.authorized;
|
||||
options = buildOptions(page, options);
|
||||
res.render(indexPage, options);
|
||||
});
|
||||
@@ -328,6 +335,8 @@ app.get("/info/:id", async function (req, res) {
|
||||
}
|
||||
let options = {
|
||||
romFile: romInfo[0],
|
||||
flags: flags,
|
||||
consoleIcons: consoleIcons
|
||||
};
|
||||
let page = "info";
|
||||
options = buildOptions(page, options);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="col-12 col-lg-10 col-xl-8">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white"><%= metadata.title %></h2>
|
||||
<p class="text-secondary"><%= file.category %></p>
|
||||
<p class="text-secondary"><%= file.category %> <%- consoleIcons.createConsoleImage(file.category) %></p>
|
||||
</div>
|
||||
<div class="row ml-1">
|
||||
<img class="coverart col-md d-block mx-auto" src="<%= coverUrl %>" href="<%= file.path %>">
|
||||
@@ -62,7 +62,7 @@
|
||||
<% } %>
|
||||
<% if(file.region) {%>
|
||||
<div>
|
||||
<p><span class="info"><%= __('search.region') %></span> <%= file.region %></p>
|
||||
<p><span class="info"><%= __('search.region') %></span> <%= file.region %> <%- flags.createFlag(file.region) %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
<% if(metadata.genre) {%>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%>
|
||||
<link rel="stylesheet" href="/public/css/result.css">
|
||||
<div class="row w-100 m-0">
|
||||
<form class="ml-2 form-inline w-100" action="/search">
|
||||
<form id="searchform" class="ml-2 form-inline w-100" action="/search">
|
||||
<div class="w-100 align-items-center">
|
||||
<div class="form-group">
|
||||
<a href="/">
|
||||
@@ -16,7 +16,7 @@
|
||||
</a>
|
||||
<input type="hidden" name="s" id="searchSettings">
|
||||
<input id="search" type="text" class="w-50 form-control bg-dark text-white ml-2" name="q" value="<%= query %>" autocomplete="off" placeholder="<%= __('search.placeholder') %>">
|
||||
<button type="submit" class="btn btn-secondary ml-2"><%= __('search.button') %></button>
|
||||
<button type="submit" class="btn btn-secondary ml-2"><div id="loading" class="hidden spinner-border text-dark" role="status"></div><%= __('search.button') %></button>
|
||||
|
||||
</div>
|
||||
<ul class="SuggestionList col-sm-12" id="suggestionList" style="width: 50%;left: 195px;"></ul>
|
||||
@@ -91,4 +91,9 @@
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script defer>
|
||||
$( "#searchform" ).on( "submit", function( event ) {
|
||||
$("#loading").removeClass('hidden')
|
||||
});
|
||||
</script>
|
||||
@@ -22,7 +22,7 @@
|
||||
</a>
|
||||
<input type="hidden" name="s" id="searchSettings">
|
||||
<input id="search" type="text" class="w-50 form-control bg-dark text-white ml-2" name="q" value="<%= query %>" autocomplete="off" placeholder="<%= __('search.placeholder') %>">
|
||||
<button type="submit" class="btn btn-secondary ml-2"><%= __('search.button') %></button>
|
||||
<button type="submit" class="btn btn-secondary ml-2"><div id="loading" class="hidden spinner-border text-dark" role="status"></div><%= __('search.button') %></button>
|
||||
|
||||
</div>
|
||||
<ul class="SuggestionList col-sm-12" id="suggestionList" style="width: 50%;left: 195px;"></ul>
|
||||
@@ -175,4 +175,9 @@
|
||||
// window.location = location.protocol + '//' + location.host + location.pathname + '?' + URLParams.toString()
|
||||
// })
|
||||
// })
|
||||
</script>
|
||||
<script defer>
|
||||
$( "#searchform" ).on( "submit", function( event ) {
|
||||
$("#loading").removeClass('hidden')
|
||||
});
|
||||
</script>
|
||||
@@ -5,17 +5,22 @@
|
||||
<%= __('nav.search') %>!
|
||||
</pre>
|
||||
<div class="text-center text-white">
|
||||
<form>
|
||||
<form id="searchform">
|
||||
<input type="hidden" name="s" id="searchSettings">
|
||||
<input type="hidden" name="old" id="oldResults">
|
||||
<input id="search" type="text" style="width: 80%;display: inline;" class="form-control bg-dark text-white mb-2"
|
||||
name="q" autocomplete="off" placeholder="<%= __('search.placeholder') %>">
|
||||
<ul class="SuggestionList col-sm-12" id="suggestionList" style="width: 78%;left: 11%;"></ul>
|
||||
<div>
|
||||
<button type="submit" formaction="/search" class="btn btn-secondary"><%= __('search.button') %></button>
|
||||
<button type="submit" formaction="/search" class="btn btn-secondary"><div id="loading" class="hidden spinner-border text-dark" role="status"></div><%= __('search.button') %></button>
|
||||
<button type="submit" formaction="/lucky" class="btn btn-secondary"><%= __('search.lucky') %></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script defer>
|
||||
$( "#searchform" ).on( "submit", function( event ) {
|
||||
$("#loading").removeClass('hidden')
|
||||
});
|
||||
</script>
|
||||
@@ -8,10 +8,10 @@
|
||||
<img class="coverart" src="<%= coverUrl %>" href="<%= file.path %>">
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<p class="title"><a href="<%= file.path %>"><%= metadata.title || file.filename %></a></p>
|
||||
<p class="info"><span class="infoitem badge badge-secondary"><%= __('search.released') %>: <%= metadata.releasedate || file.date %></span>
|
||||
<span class="infoitem badge badge-secondary"><%= __('search.region') %> <%= file.region %></span>
|
||||
<span class="infoitem badge badge-secondary"><%= __('search.platform') %> <%= file.category %></span>
|
||||
<p class="title"><a href="/info/<%=file.id %>"><%= metadata.title || file.filename %></a></p>
|
||||
<p class="info"><span class="infoitem badge badge-secondary"><%= __('search.released') %> <%= metadata.releasedate || file.date %></span>
|
||||
<span class="infoitem badge badge-secondary"><%= __('search.region') %> <%= file.region %> <%- flags.createFlag(file.region) %></span>
|
||||
<span class="infoitem badge badge-secondary"><%= __('search.platform') %> <%= file.category %> <%- consoleIcons.createConsoleImage(file.category) %></span>
|
||||
<% if(metadata.genre){ %>
|
||||
<span class="infoitem badge badge-secondary"><%= __('search.genre') %> <%= JSON.parse(metadata.genre).join(' / ') %></span>
|
||||
<% } %>
|
||||
|
||||
@@ -43,4 +43,11 @@
|
||||
object-fit: contain;
|
||||
height: auto;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.console {
|
||||
height: 1.5rem;
|
||||
}
|
||||
.text-secondary{
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
@@ -20,13 +20,14 @@
|
||||
font-weight: bold;
|
||||
color: #f0a400;
|
||||
margin-bottom: 0!important;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
.title a {
|
||||
font-weight: bold;
|
||||
color: #f0a400;
|
||||
}
|
||||
.info {
|
||||
font-size: 0.8em;
|
||||
font-size: 1em;
|
||||
}
|
||||
.file {
|
||||
font-size: 0.8em;
|
||||
@@ -36,7 +37,21 @@
|
||||
}
|
||||
.infoitem{
|
||||
margin-right: 0;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
height: 1.75em;
|
||||
vertical-align: middle;
|
||||
align-content: center;
|
||||
}
|
||||
.cover{
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.flag{
|
||||
height: 1.25em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.console {
|
||||
height: 1.25em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -144,3 +144,18 @@ td a {
|
||||
position: relative;
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
.flag {
|
||||
object-fit: contain;
|
||||
}
|
||||
.console {
|
||||
object-fit: contain;
|
||||
}
|
||||
.spinner-border {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
margin-right: 0.25em;
|
||||
vertical-align: sub;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
32
views/public/js/video.js
Normal file
32
views/public/js/video.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// index.js
|
||||
const videos = [];
|
||||
const tag = document.createElement("script");
|
||||
const firstScriptTag = document.getElementsByTagName("script")[0];
|
||||
|
||||
tag.src = "https://www.youtube.com/iframe_api";
|
||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||
|
||||
// YouTube wants this function, don't rename it
|
||||
function onYouTubeIframeAPIReady() {
|
||||
const slides = Array.from(document.querySelectorAll(".carousel-item"));
|
||||
slides.forEach((slide, index) => {
|
||||
// does this slide have a video?
|
||||
const video = slide.querySelector(".video-player");
|
||||
if (video && video.dataset) {
|
||||
const player = createPlayer({
|
||||
id: video.id,
|
||||
videoId: video.dataset.videoId,
|
||||
});
|
||||
videos.push({ player, index });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createPlayer(playerInfo) {
|
||||
return new YT.Player(playerInfo.id, {
|
||||
videoId: playerInfo.videoId,
|
||||
playerVars: {
|
||||
showinfo: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user