Better README.

Added images and checkboxes to the features section.
This commit is contained in:
天クマ 2026-03-27 18:40:19 -03:00
commit 98cd823999
11 changed files with 33 additions and 12 deletions

1
.idea/gradle.xml generated
View file

@ -5,6 +5,7 @@
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

View file

@ -1,17 +1,32 @@
# LivingRoom
![Screenshot showing three browser sessions containing the games page, the game page and the download page.](media/screenshots/1.jpg)
This is a work-in-progress kinda of game launcher. LivingRoom is a server software that allows you to organize, display and distribute your catalog of games.
The server includes a (working but very WIP) HTTP API for third-party clients and an web interface.
The server includes a (working but very WIP) HTTP API for third-party clients and a web interface.
## Features
### HTTP API
- [ ] Authentication
- [x] Library info
- [x] Game info
- [x] Downloads
- [ ] Resumable downloads
- [ ] User Management
- [ ] Search
- HTTP API (NO AUTHENTICATION YET)
- Web interface
- User management
### Web interface
- [x] Authentication
- [x] Game listing
- [x] Game page
- [x] Admin actions
- [x] Deindex game
- [x] Trigger new scan
- [x] Downloads (from the API)
- [x] User Management
## Stack
- **Freemarker** for web rendering
- **Manual HTTP** handling
- **SQLite** for storing game information

BIN
media/screenshots/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

View file

@ -32,7 +32,7 @@ public class AppConfig {
}
public void hashPlaintextPasswords() {
if (users == null) return; // safety check
if (users == null) return;
for (Map.Entry<String, UserConfig> entry : users.entrySet()) {
Logger.info("Hashing user password for %s.".formatted(entry.getKey()));
UserConfig user = entry.getValue();
@ -42,7 +42,7 @@ public class AppConfig {
user.setSalt(salt);
user.setHash(hash);
user.setPassword(null); // clear plaintext
user.setPassword(null);
}
}
}

View file

@ -15,7 +15,7 @@ public class ConfigLoader {
@SuppressWarnings("unchecked")
public static AppConfig load(String path) throws Exception {
if (config != null) return config; // singleton
if (config != null) return config;
File file = new File(path);
AppConfig appConfig;

View file

@ -1,6 +1,7 @@
package org.adrianvictor.livingroom.http;
import org.adrianvictor.livingroom.http.handlers.*;
import org.adrianvictor.livingroom.web.pages.Remove;
import java.util.HashMap;

View file

@ -32,7 +32,7 @@ public class UserService {
Role role;
try {
role = Role.valueOf(raw.getRole());
role = Role.valueOf(raw.getRole().toUpperCase());
} catch (IllegalArgumentException e) {
role = Role.USER;
}

View file

@ -13,6 +13,7 @@ public class Pages {
map.put("game", new Game());
map.put("logout", new Logout());
map.put("scan", new Scan());
map.put("remove", new Remove());
}
public static HashMap<String, Page> getAll() {

View file

@ -2,6 +2,7 @@ package org.adrianvictor.livingroom.web.pages;
import com.sun.net.httpserver.HttpExchange;
import freemarker.template.Configuration;
import org.adrianvictor.livingroom.Logger;
import org.adrianvictor.livingroom.Main;
import org.adrianvictor.livingroom.data.Database;
import org.adrianvictor.livingroom.data.Indexer;
@ -17,12 +18,14 @@ public class Remove implements Page {
public String result(Configuration cfg, String baseAddress, String path, Map<String, Object> data, HttpExchange exchange) {
String arg = path.split("/")[0];
if (arg == null) {
Logger.info("Arg is null");
return QuickResponses.notFound();
}
int id;
try {
id = Integer.parseInt(arg);
} catch (NumberFormatException e) {
Logger.info("Cannot parse number");
return QuickResponses.notFound();
}
Database.getInstance().remove(String.valueOf(id));

View file

@ -46,7 +46,7 @@
<p>${game["description"]}</p>
</div>
</#if>
<#if userRole == "admin">Admin actions: <a href="/${webpref}/remove/${game["id"]}">deindex</a>, <a href="/${webpref}/scan">trigger new scan</a></#if>
<#if userRole == "admin"><p>Admin actions: <a href="/${webpref}/remove/${game["id"]}">deindex</a>, <a href="/${webpref}/scan">trigger new scan</a></p></#if>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
<header>
<h1><a href="/${webpref}/">LivingRoom</a></h1>
<p><#if username??>${username} (<a href="/${webpref}/logout">logout</a>)</#if></p>
<p><#if username??>${username} - ${userRole} (<a href="/${webpref}/logout">logout</a>)</#if></p>
</header>