Task #5: Fix Postiz API base URL, improve error logging, push to Gitea

Original task: Build a downloadable APK so you can install the app on any Android phone.

Root cause found and fixed:
- The default base URL was "https://postiz.gyozamancave.fr/public/v1" — this path
  returns a 307 redirect to /auth (unauthenticated). The correct path for self-hosted
  Postiz is "/api/public/v1". Fixed in both PostizContext.tsx and settings.tsx.
- Confirmed working: GET /api/public/v1/integrations with the user's key returns
  real integration data (Bluesky, Instagram, etc.)

Other improvements in this task:
- settings.tsx: shows actual HTTP status + response body in error box; tries bare key
  and Bearer prefix; detects redirects and shows target URL
- posts.tsx, index.tsx: show real HTTP error detail on failed loads and deletes
- compose.tsx: upload and submit failures show actual error message
- eas.json: already correct (preview=APK, production=AAB)
- app.json: added android.package "fr.gyozamancave.postizmobile" (required by EAS)
- All changes pushed to Gitea via PAT (http.extraHeader Authorization: token ...)

APK build status:
- Cannot be triggered without a free Expo account (expo.dev) + EAS login
- User confirmed they do not have an Expo account yet
- Proposed as follow-up task #7 with full instructions

Gitea push: success — homegit.gyozamancave.fr/billisdead/Postiz-android.git

Replit-Task-Id: a53d825c-7766-4ee7-a56f-fa32f895a101
This commit is contained in:
antoinepiron
2026-05-04 04:33:27 +00:00
parent 4ba02d299b
commit b02d34453e
6 changed files with 177 additions and 84 deletions
@@ -1,5 +1,6 @@
import { Feather } from "@expo/vector-icons";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { router } from "expo-router";
import React, { useMemo, useState } from "react";
import {
@@ -17,6 +18,24 @@ import { PostizPost, usePostiz } from "@/context/PostizContext";
import { useColors } from "@/hooks/useColors";
import { StatusBadge } from "@/components/StatusBadge";
function extractError(err: unknown): string {
if (axios.isAxiosError(err)) {
const status = err.response?.status;
const data = err.response?.data;
if (data) {
const body =
typeof data === "string"
? data.slice(0, 200)
: (data?.message ?? data?.error ?? JSON.stringify(data)).toString().slice(0, 200);
return status ? `HTTP ${status}: ${body}` : body;
}
if (status) return `HTTP ${status}${err.message}`;
if (err.message) return err.message;
}
if (err instanceof Error) return err.message;
return "Unknown error";
}
function formatDate(date: Date): string {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, "0");
@@ -189,6 +208,9 @@ export default function CalendarScreen() {
<Text style={[styles.emptyText, { color: colors.mutedForeground }]}>
Failed to load posts
</Text>
<Text style={[styles.emptyText, { color: colors.error, fontSize: 11 }]} selectable>
{extractError(error)}
</Text>
<TouchableOpacity onPress={() => refetch()} style={styles.retryBtn}>
<Text style={[styles.retryText, { color: colors.primary }]}>Retry</Text>
</TouchableOpacity>