feat(mobile): source-code link in Settings + Refresh thumbnail button
- AppLockSettings: a "Source code" row linking the public OSS repo (report 4c5066b8) - a trust signal for a sideloaded FOSS app (audit / self-host / contribute). - SceneDetail: a "Refresh thumbnail" button (force) for scenes whose preview is broken or stale (report d3376a71). - changelog: new What's New entry for this batch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e512665d26
commit
9269b02a4c
4 changed files with 67 additions and 2 deletions
|
|
@ -436,13 +436,14 @@ export class GoonClient {
|
|||
return this.request(`/scenes/${sceneId}/enrich-duration`, { method: 'POST' });
|
||||
}
|
||||
|
||||
async enrichSceneThumbnail(sceneId: string): Promise<{
|
||||
async enrichSceneThumbnail(sceneId: string, force = false): Promise<{
|
||||
scene_id: string;
|
||||
thumbnail_url: string | null;
|
||||
tube_used: string | null;
|
||||
sources_updated: number;
|
||||
}> {
|
||||
return this.request(`/scenes/${sceneId}/enrich-thumbnail`, { method: 'POST' });
|
||||
const qs = force ? '?force=true' : '';
|
||||
return this.request(`/scenes/${sceneId}/enrich-thumbnail${qs}`, { method: 'POST' });
|
||||
}
|
||||
|
||||
async enrichSceneStudio(sceneId: string): Promise<{
|
||||
|
|
|
|||
|
|
@ -16,6 +16,15 @@ export type ChangelogEntry = {
|
|||
};
|
||||
|
||||
export const CHANGELOG: ChangelogEntry[] = [
|
||||
{
|
||||
id: '2026-06-13',
|
||||
date: 'June 2026',
|
||||
items: [
|
||||
'Source code link added in Settings — the app is open source (MIT).',
|
||||
'New: a Refresh thumbnail button on a scene when its preview is broken or stale.',
|
||||
'Fewer dead links — deleted videos on some sites are now detected automatically.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '2026-06-12',
|
||||
date: 'June 2026',
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import {
|
||||
ActivityIndicator,
|
||||
Alert,
|
||||
Linking,
|
||||
Pressable,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
|
|
@ -266,11 +267,26 @@ export function AppLockSettingsScreen() {
|
|||
</View>
|
||||
<Text style={styles.versionValue}>{APP_VERSION}</Text>
|
||||
</View>
|
||||
<Pressable
|
||||
style={styles.row}
|
||||
onPress={() => Linking.openURL(REPO_URL).catch(() => {})}
|
||||
>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={styles.label}>Source code</Text>
|
||||
<Text style={styles.hint}>Open source (MIT) — audit it or self-host</Text>
|
||||
</View>
|
||||
<Text style={styles.linkValue}>{REPO_LABEL} ›</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
// Publiczne repo OSS (zgłoszenie usera 4c5066b8: "no source code repo linked").
|
||||
// Sygnał zaufania dla sideloadowanej apki 18+: audyt kodu / self-host / kontrybucja.
|
||||
const REPO_URL = 'https://github.com/goon-foss/goon';
|
||||
const REPO_LABEL = 'goon-foss/goon';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: { flex: 1, backgroundColor: theme.bg },
|
||||
center: { flex: 1, backgroundColor: theme.bg, alignItems: 'center', justifyContent: 'center' },
|
||||
|
|
@ -320,6 +336,7 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
chipActive: { backgroundColor: theme.accent, borderColor: theme.accent },
|
||||
versionValue: { color: theme.fg, fontSize: 15, fontWeight: '700', fontVariant: ['tabular-nums'] },
|
||||
linkValue: { color: theme.accent, fontSize: 15, fontWeight: '700' },
|
||||
chipText: { color: theme.muted, fontSize: 13 },
|
||||
chipTextActive: { color: '#fff', fontWeight: '700' },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -119,6 +119,21 @@ export function SceneDetailScreen() {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [data?.id]);
|
||||
|
||||
// Ręczny refresh miniatury (force) — zgłoszenie d3376a71: zepsuta/stała miniaturka
|
||||
// (np. rotting sxyprn/trafficdeposit). Nadpisuje istniejącą świeżą ze strony tube'a.
|
||||
const refreshThumbMutation = useMutation({
|
||||
mutationFn: () => client.enrichSceneThumbnail(id, true),
|
||||
onSuccess: (out) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['scene', id] });
|
||||
queryClient.invalidateQueries({ queryKey: ['scenes'] });
|
||||
Alert.alert(
|
||||
'Thumbnail',
|
||||
out.thumbnail_url ? 'Refreshed from the source page.' : 'Could not fetch a fresh thumbnail.',
|
||||
);
|
||||
},
|
||||
onError: (e) => Alert.alert('Thumbnail', e instanceof Error ? e.message : String(e)),
|
||||
});
|
||||
|
||||
// Auto-enrich tags: search-only scrapery nie pobierają tagów z detail page.
|
||||
// Pornhat ma `js-ajax-tag` data-setup JSON; xhamster/xvideos/youporn/inne mają
|
||||
// dedicated tag_extract patterny. SceneDetail wywołuje 1 fetch → upsert do DB.
|
||||
|
|
@ -223,6 +238,18 @@ export function SceneDetailScreen() {
|
|||
<Hero data={data} />
|
||||
|
||||
<View style={styles.body}>
|
||||
{data.playback_sources.some((s) => s.origin?.startsWith('tube:')) && (
|
||||
<Pressable
|
||||
style={styles.refreshThumbBtn}
|
||||
onPress={() => refreshThumbMutation.mutate()}
|
||||
disabled={refreshThumbMutation.isPending}
|
||||
>
|
||||
<Text style={styles.refreshThumbText}>
|
||||
{refreshThumbMutation.isPending ? 'Refreshing thumbnail…' : '↻ Refresh thumbnail'}
|
||||
</Text>
|
||||
</Pressable>
|
||||
)}
|
||||
|
||||
{(data.code || data.director) && (
|
||||
<View style={styles.metaRow}>
|
||||
{data.code ? <Text style={styles.metaDim}>code · {data.code}</Text> : null}
|
||||
|
|
@ -854,6 +881,17 @@ const styles = StyleSheet.create({
|
|||
fontSize: 13,
|
||||
},
|
||||
tagHint: { color: theme.mutedDim, fontSize: 11, marginTop: 6 },
|
||||
refreshThumbBtn: {
|
||||
alignSelf: 'flex-start',
|
||||
paddingVertical: 6,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.border,
|
||||
backgroundColor: theme.card,
|
||||
marginBottom: 12,
|
||||
},
|
||||
refreshThumbText: { color: theme.muted, fontSize: 13, fontWeight: '600' },
|
||||
|
||||
pillSource: {
|
||||
borderColor: theme.accent,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue