Add ROOTLESS_CONTAINER and request UI updates

Introduce ROOTLESS_CONTAINER env to opt out of gosu (replace /proc uid_map detection) and update entrypoint messaging; adjust app-start.sh and redis-start.sh to skip gosu when ROOTLESS_CONTAINER=true and warn on UID/GID mismatch only when applicable. Backend: include audiobook audibleAsin in admin requests response (mapped to asin) and pass baseUrl through test-flaresolverr endpoint to the FlareSolverr tester. Frontend: RecentRequestsTable and RequestActionsDropdown now surface asin, accept/passthrough annasArchiveBaseUrl, and add a "View Details" flow using AudiobookDetailsModal; admin page passes ebook baseUrl from settings. InteractiveTorrentSearchModal refactor: improved UX/UI, keyboard handling, portal/modal mounting, skeleton/loading states, formatting helpers, and richer result display. Tests updated to match changes.
This commit is contained in:
kikootwo
2026-02-06 17:13:39 -05:00
parent 03371be81d
commit 95e63dfc36
18 changed files with 1027 additions and 427 deletions
@@ -98,9 +98,8 @@ describe('InteractiveTorrentSearchModal', () => {
expect(await screen.findByText('Test Torrent')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'Download' }));
const downloadButtons = screen.getAllByRole('button', { name: 'Download' });
fireEvent.click(downloadButtons[downloadButtons.length - 1]);
fireEvent.click(screen.getByRole('button', { name: 'Get' }));
fireEvent.click(await screen.findByRole('button', { name: 'Download' }));
await waitFor(() => {
expect(selectTorrentMock).toHaveBeenCalledWith('req-123', baseResult);
@@ -129,9 +128,8 @@ describe('InteractiveTorrentSearchModal', () => {
expect(searchByAudiobookMock).toHaveBeenCalledWith('Test Book', 'Test Author', 'ASIN-1');
});
fireEvent.click(screen.getByRole('button', { name: 'Download' }));
const downloadButtons = screen.getAllByRole('button', { name: 'Download' });
fireEvent.click(downloadButtons[downloadButtons.length - 1]);
fireEvent.click(screen.getByRole('button', { name: 'Get' }));
fireEvent.click(await screen.findByRole('button', { name: 'Download' }));
await waitFor(() => {
expect(requestWithTorrentMock).toHaveBeenCalledWith(fullAudiobook, baseResult);
@@ -157,9 +155,9 @@ describe('InteractiveTorrentSearchModal', () => {
expect(searchByRequestMock).toHaveBeenCalledWith('req-456', undefined);
});
const input = screen.getByPlaceholderText('Enter book title to search...');
const input = screen.getByPlaceholderText('Search title...');
fireEvent.change(input, { target: { value: 'Custom Title' } });
fireEvent.keyPress(input, { key: 'Enter', code: 'Enter', charCode: 13 });
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
await waitFor(() => {
expect(searchByRequestMock).toHaveBeenNthCalledWith(2, 'req-456', 'Custom Title');