Skip to content

Commit 6c4d6c1

Browse files
committed
feat: 移动端修改 tts 页面布局
1 parent 1f81795 commit 6c4d6c1

1 file changed

Lines changed: 38 additions & 7 deletions

File tree

apps/mobile/src/screens/TTSScreen.tsx

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,10 @@ export function TTSScreen() {
127127
const playbackState = usePlaybackState();
128128
const progress = useProgress();
129129

130-
const isPlaying = playbackState.state === State.Playing;
131-
const isPaused = playbackState.state === State.Paused;
132-
const isLoadingAudio = playbackState.state === State.Loading || playbackState.state === State.Buffering;
130+
const currentState = playbackState?.state;
131+
const isPlaying = currentState === State.Playing;
132+
const isPaused = currentState === State.Paused;
133+
const isLoadingAudio = currentState === State.Loading || currentState === State.Buffering;
133134

134135
const [currentParagraph, setCurrentParagraph] = useState(0);
135136
const [paragraphProgress, setParagraphProgress] = useState(0);
@@ -167,8 +168,11 @@ export function TTSScreen() {
167168
],
168169
progressUpdateEventInterval: 1,
169170
});
171+
// Reset player to clear any stuck loading/buffering state
172+
await TrackPlayer.reset();
170173
} catch (e) {
171-
// Player may already be set up
174+
// Player may already be set up, try reset anyway
175+
try { await TrackPlayer.reset(); } catch {}
172176
}
173177
})();
174178
return () => {
@@ -184,37 +188,46 @@ export function TTSScreen() {
184188
setLoadError(null);
185189
try {
186190
const apiClient = getApiClient();
191+
console.log('[TTSScreen] Starting load, book.id:', book.id);
187192

188193
// Providers
189194
const provRes = await apiClient.getTtsProviders();
195+
console.log('[TTSScreen] Providers response:', JSON.stringify(provRes));
190196
if (cancelled) return;
191197
const ps = (provRes.success && provRes.data?.providers) || [];
192198
setProviders(ps);
193199
const enabledNames = ps.filter((p) => p.enabled).map((p) => p.name);
194200
const finalProvider = enabledNames.includes(provider)
195201
? provider
196202
: enabledNames[0] || "edge";
203+
console.log('[TTSScreen] Final provider:', finalProvider);
197204
if (finalProvider !== provider) setProvider(finalProvider);
198205

199206
// Voices
200207
const vRes = await apiClient.getVoices(finalProvider);
208+
console.log('[TTSScreen] Voices response:', JSON.stringify(vRes));
201209
if (cancelled) return;
202210
const vs = (vRes.success && vRes.data) || [];
203211
setVoices(vs);
204212
if (!voiceId && vs[0]) setVoiceId(vs[0].id);
205213

206214
// Chapters
215+
console.log('[TTSScreen] Loading chapters for book:', book.id);
207216
const chRes = await apiClient.getChapters(book.id);
217+
console.log('[TTSScreen] Chapters response:', JSON.stringify(chRes));
208218
if (cancelled) return;
209219
if (!chRes.success || !chRes.data || chRes.data.length === 0) {
220+
console.log('[TTSScreen] No chapters found');
210221
setLoadError("本书暂无章节内容,请先解析章节。");
211222
return;
212223
}
213224
setChapters(chRes.data);
214225

215-
// Load first chapter paragraphs
226+
// Load first chapter (loadChapter will skip empty ones)
227+
console.log('[TTSScreen] Loading chapter 0, voice:', vs[0]?.id || voiceId, 'provider:', finalProvider);
216228
await loadChapter(0, vs[0]?.id || voiceId, finalProvider);
217229
} catch (e) {
230+
console.error('[TTSScreen] Load error:', e);
218231
setLoadError((e as Error).message || "加载失败");
219232
} finally {
220233
if (!cancelled) setLoading(false);
@@ -303,14 +316,32 @@ export function TTSScreen() {
303316
}, [ttsStore]);
304317

305318
const loadChapter = async (ci: number, vid: string, prov: string) => {
319+
console.log('[TTSScreen] loadChapter called, ci:', ci, 'vid:', vid, 'prov:', prov);
306320
setChapterIndex(ci);
307321
try {
308322
const apiClient = getApiClient();
323+
console.log('[TTSScreen] Fetching paragraphs for book:', book.id, 'chapter:', ci);
309324
const pRes = await apiClient.getChapterParagraphs(book.id, ci);
325+
console.log('[TTSScreen] Paragraphs response:', JSON.stringify(pRes).substring(0, 500));
310326
if (!pRes.success || !pRes.data) {
327+
console.log('[TTSScreen] Failed to load paragraphs:', pRes);
311328
setLoadError("加载章节失败");
312329
return;
313330
}
331+
console.log('[TTSScreen] Paragraphs loaded, count:', pRes.data.paragraphs?.length);
332+
333+
// If chapter has no paragraphs, try next chapter
334+
if (!pRes.data.paragraphs || pRes.data.paragraphs.length === 0) {
335+
const nextChapter = ci + 1;
336+
if (nextChapter < chapters.length) {
337+
console.log('[TTSScreen] Chapter empty, trying next:', nextChapter);
338+
return loadChapter(nextChapter, vid, prov);
339+
} else {
340+
setLoadError("没有可朗读的内容");
341+
return;
342+
}
343+
}
344+
314345
setChapterTitle(pRes.data.title);
315346
setParagraphs(pRes.data.paragraphs);
316347
setCurrentParagraph(0);
@@ -763,7 +794,7 @@ export function TTSScreen() {
763794
style={[styles.iconButton, { backgroundColor: theme.colors.surface }]}
764795
onPress={handleSkipBack}
765796
>
766-
<Ionicons name="play-skip-back" size={22} color={theme.colors.text} />
797+
<Ionicons name="play-skip-back-outline" size={22} color={theme.colors.text} />
767798
</TouchableOpacity>
768799

769800
{/* Play/Pause */}
@@ -788,7 +819,7 @@ export function TTSScreen() {
788819
style={[styles.iconButton, { backgroundColor: theme.colors.surface }]}
789820
onPress={handleSkipForward}
790821
>
791-
<Ionicons name="play-skip-forward" size={22} color={theme.colors.text} />
822+
<Ionicons name="play-skip-forward-outline" size={22} color={theme.colors.text} />
792823
</TouchableOpacity>
793824

794825
{/* Chapter picker */}

0 commit comments

Comments
 (0)