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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user