MiniABS 1.2: Galician interface, larger text and touch targets

- Translate the interface to Galician (tools/translate_gl.py), including
  Galician month abbreviations for dates, which Android 2.3 lacks
- Resize for the Galaxy Mini's 240x320 screen: larger text, rows, tabs and
  buttons; all sizes now live in res/values/dimens.xml
- Redraw play/pause/refresh icons for every density; slightly brighter
  secondary text colours

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xockoandClaude Opus 5.5 committed 2026-10-14 21:29:17 +02:00
1 parent b7e43d7d61
commit 275bee3c11
51 files changed
+704 -372

No files matched your search

+20 -20
View File
@@ -26,7 +26,7 @@ import android.os.Build;
/** Audiobookshelf REST client (API as of server 2.x, including the 2.26+ token system). */
final class Api {
static final String VERSION = "1.1";
static final String VERSION = "1.2";
static class ApiException extends IOException {
final int code;
@@ -100,7 +100,7 @@ final class Api {
if (peer.length == 0 || !(peer[0] instanceof java.security.cert.X509Certificate)
|| !Trust.hostMatches((java.security.cert.X509Certificate) peer[0], u.getHost())) {
ss.close();
throw new SSLException("Certificate doesn't match " + u.getHost());
throw new SSLException("O certificado non corresponde a " + u.getHost());
}
io = ss;
}
@@ -123,11 +123,11 @@ final class Api {
int ch;
while ((ch = in.read()) != -1 && ch != '\n' && line.length() < 200) line.append((char) ch);
String[] parts = line.toString().trim().split(" ");
if (parts.length < 2 || !parts[0].startsWith("HTTP/")) throw new IOException("Unexpected reply from server");
if (parts.length < 2 || !parts[0].startsWith("HTTP/")) throw new IOException("Resposta inesperada do servidor");
try {
code = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new IOException("Unexpected reply from server");
throw new IOException("Resposta inesperada do servidor");
}
byte[] rest = new byte[1024];
int total = 0, n;
@@ -144,10 +144,10 @@ final class Api {
refreshIf(c, used, 0);
return rawPatch(c, path, body, false);
}
throw new AuthException("Your sign-in has expired. Please log in again.");
throw new AuthException("A túa sesión caducou. Inicia sesión de novo.");
}
if (code >= 400) throw new ApiException(code, "");
if (code >= 300) throw new ApiException(code, "The server redirected; check the address in Settings.");
if (code >= 300) throw new ApiException(code, "O servidor redirixiu a petición; comproba o enderezo do servidor.");
return "OK";
}
@@ -216,7 +216,7 @@ final class Api {
static Object call(Context c, String method, String path, JSONObject body, int maxString, String[] deepSkip,
boolean mayRefresh) throws IOException {
Prefs p = Prefs.get(c);
if (!p.loggedIn()) throw new AuthException("Please log in.");
if (!p.loggedIn()) throw new AuthException("Inicia sesión.");
if ("PATCH".equals(method)) return rawPatch(c, path, body, mayRefresh);
if (mayRefresh) ensureFresh(c, 120);
String used = p.token();
@@ -232,7 +232,7 @@ final class Api {
refreshIf(c, used, 0);
return call(c, method, path, body, maxString, deepSkip, false);
}
throw new AuthException("Your sign-in has expired. Please log in again.");
throw new AuthException("A túa sesión caducou. Inicia sesión de novo.");
}
if (code >= 400) throw new ApiException(code, errorText(conn));
return readBody(conn, maxString, deepSkip);
@@ -243,7 +243,7 @@ final class Api {
static JSONObject obj(Object o) throws IOException {
if (o instanceof JSONObject) return (JSONObject) o;
throw new IOException("Unexpected reply from server");
throw new IOException("Resposta inesperada do servidor");
}
// ------------------------------------------------------------------ sign-in
@@ -253,13 +253,13 @@ final class Api {
HttpURLConnection conn = open(c, server + "/status", "GET");
try {
int code = responseCode(conn);
if (code == 404) throw new IOException("No Audiobookshelf server at this address.");
if (code == 404) throw new IOException("Non hai ningún servidor de Audiobookshelf neste enderezo.");
if (code >= 400) throw new ApiException(code, errorText(conn));
Object o = readBody(conn, 200, null);
if (!(o instanceof JSONObject)) throw new IOException("No Audiobookshelf server at this address.");
if (!(o instanceof JSONObject)) throw new IOException("Non hai ningún servidor de Audiobookshelf neste enderezo.");
JSONObject s = (JSONObject) o;
if (s.has("isInit") && !s.optBoolean("isInit", true)) {
throw new IOException("This server hasn't been set up yet. Finish setup in a browser first.");
throw new IOException("Este servidor aínda non está configurado. Remata a configuración nun navegador.");
}
return Util.str(s, "serverVersion");
} finally {
@@ -280,19 +280,19 @@ final class Api {
}
writeBody(conn, body);
int code = responseCode(conn);
if (code == 401) throw new ApiException(401, "Wrong username or password.");
if (code == 429) throw new ApiException(429, "Too many attempts. Wait a minute and try again.");
if (code == 401) throw new ApiException(401, "Usuario ou contrasinal incorrectos.");
if (code == 429) throw new ApiException(429, "Demasiados intentos. Agarda un minuto e téntao de novo.");
if (code >= 400) throw new ApiException(code, errorText(conn));
JSONObject o = obj(readBody(conn, 500, null));
JSONObject u = o.optJSONObject("user");
if (u == null) throw new IOException("Unexpected reply from server");
if (u == null) throw new IOException("Resposta inesperada do servidor");
String access = Util.str(u, "accessToken");
String refresh = Util.str(u, "refreshToken");
String legacy = Util.str(u, "token");
Prefs p = Prefs.get(c);
if (access.length() > 0) p.setAuth(user, Prefs.MODE_JWT, access, refresh);
else if (legacy.length() > 0) p.setAuth(user, Prefs.MODE_LEGACY, legacy, "");
else throw new IOException("The server didn't return a sign-in token.");
else throw new IOException("O servidor non devolveu ningún token de sesión.");
return Util.str(o, "userDefaultLibraryId");
} finally {
conn.disconnect();
@@ -310,7 +310,7 @@ final class Api {
return name;
} catch (IOException e) {
p.logout();
if (e instanceof AuthException) throw new ApiException(401, "That API key wasn't accepted.");
if (e instanceof AuthException) throw new ApiException(401, "Non se aceptou esa chave da API.");
throw e;
}
}
@@ -335,7 +335,7 @@ final class Api {
private static void refreshIf(Context c, String stale, long minSeconds) throws IOException {
synchronized (REFRESH_LOCK) {
Prefs p = Prefs.get(c);
if (!p.canRefresh()) throw new AuthException("Your sign-in has expired. Please log in again.");
if (!p.canRefresh()) throw new AuthException("A túa sesión caducou. Inicia sesión de novo.");
if (stale != null) {
if (!stale.equals(p.token())) return;
} else if (p.tokenSecondsLeft() >= minSeconds) {
@@ -348,12 +348,12 @@ final class Api {
writeBody(conn, null);
int code = responseCode(conn);
if (code == 401 || code == 403) {
throw new AuthException("Your sign-in has expired. Please log in again.");
throw new AuthException("A túa sesión caducou. Inicia sesión de novo.");
}
if (code >= 400) throw new ApiException(code, errorText(conn));
JSONObject u = obj(readBody(conn, 500, null)).optJSONObject("user");
String access = u == null ? "" : Util.str(u, "accessToken");
if (access.length() == 0) throw new AuthException("Your sign-in has expired. Please log in again.");
if (access.length() == 0) throw new AuthException("A túa sesión caducou. Inicia sesión de novo.");
p.setTokens(access, Util.str(u, "refreshToken"));
} finally {
conn.disconnect();