| import io |
| import base64 |
| from PIL import Image |
| import streamlit as st |
| from typing import Dict, Any |
| from log_utils import setup_logging |
|
|
| logger = setup_logging('pdf_details_page') |
|
|
| def display_pdf_details(pdf_details, filename): |
| """ |
| Display detailed information about a specific PDF page. |
| Parameters: |
| - pdf_details: dict containing the PDF information |
| - filename: name of the PDF file |
| """ |
| logger.info(f"Displaying PDF details for file: {filename}") |
| |
| |
| if 'reader_mode' not in st.session_state: |
| st.session_state.reader_mode = False |
| logger.debug("Initialized reader mode state") |
|
|
| def toggle_reader_mode(): |
| """Toggle reader mode state with logging.""" |
| previous_state = st.session_state.reader_mode |
| st.session_state.reader_mode = not previous_state |
| logger.info(f"Reader mode toggled from {previous_state} to {st.session_state.reader_mode}") |
| |
| try: |
| |
| st.markdown(""" |
| <style> |
| .page-container { |
| background-color: #ffffff; |
| padding: 30px; |
| margin: 20px auto; |
| border-radius: 12px; |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| max-width: 1200px; |
| font-family: Arial, sans-serif; |
| } |
| .stApp { |
| background-color: #f8f9fa; |
| } |
| .detail-box { |
| border-radius: 12px; |
| padding: 25px; |
| margin-bottom: 25px; |
| } |
| .header { |
| text-align: center; |
| color: #1a237e; |
| margin-bottom: 30px; |
| font-family: 'Helvetica Neue', sans-serif; |
| } |
| .metadata-table { |
| width: 100%; |
| border-collapse: collapse; |
| margin: 20px 0; |
| font-family: 'Helvetica Neue', sans-serif; |
| } |
| .metadata-table td { |
| padding: 12px 15px; |
| border: 1px solid #e0e0e0; |
| } |
| .metadata-table tr:nth-child(even) { |
| background-color: #f8f9fa; |
| } |
| .metadata-table tr:hover { |
| background-color: #f5f5f5; |
| } |
| .metadata-table td:first-child { |
| font-weight: 600; |
| width: 30%; |
| color: #2c3e50; |
| } |
| .stButton>button { |
| width: 100%; |
| border-radius: 8px; |
| height: 45px; |
| margin-top: 10px; |
| } |
| .stTextArea>div>div { |
| border-radius: 8px; |
| } |
| .page-preview { |
| border-radius: 8px; |
| overflow: hidden; |
| box-shadow: 0 4px 8px rgba(0,0,0,0.1); |
| max-width: 100%; |
| max-height: 500px; |
| margin: auto; |
| } |
| .reader-mode { |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100vw; |
| height: 100vh; |
| background: rgba(0, 0, 0, 0.9); |
| z-index: 9999; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| padding: 2rem; |
| } |
| .reader-mode img { |
| max-height: 90vh; |
| max-width: 90vw; |
| object-fit: contain; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
| logger.debug("Applied CSS styling") |
| |
| |
| if st.session_state.reader_mode: |
| logger.info("Displaying reader mode view") |
| st.markdown('<div class="reader-mode-container">', unsafe_allow_html=True) |
| if st.button("β Close Reader Mode", key="close_reader", help="Exit reader mode"): |
| logger.info("Reader mode closed") |
| st.session_state.reader_mode = False |
| st.rerun() |
| |
| |
| page_image_bytes = base64.b64decode(pdf_details['page_image']) |
| page_image = Image.open(io.BytesIO(page_image_bytes)) |
| st.image(page_image, use_container_width=True, caption=f"Page {pdf_details['current_page']}") |
| st.markdown('</div>', unsafe_allow_html=True) |
| return |
| |
| logger.info("Displaying regular interface") |
| |
| st.markdown('<h1 class="header">π Smart PDF Search</h1>', unsafe_allow_html=True) |
| |
| |
| col1, col2 = st.columns([1.5, 2]) |
| |
| with col1: |
| logger.debug("Rendering details section") |
| st.markdown("<h3 style='color: #1a237e; margin-bottom: 15px;'>πΌοΈ Page Preview</h3>", unsafe_allow_html=True) |
| current_page = pdf_details['current_page'] |
| st.markdown(f"<div style='text-align: center; padding: 15px;'>Page {current_page} of {pdf_details['total_pages']}</div>", unsafe_allow_html=True) |
| |
| page_image_bytes = base64.b64decode(pdf_details['page_image']) |
| page_image = Image.open(io.BytesIO(page_image_bytes)) |
| st.image(page_image, caption=f"Page {current_page}", use_container_width=True) |
| |
| with col2: |
| st.markdown("<div class='detail-box'>", unsafe_allow_html=True) |
| |
| |
| col1, col2, col3 = st.columns(3) |
|
|
| |
| with col1: |
| logger.info("Reader mode button clicked") |
| st.button("π Reader Mode", on_click=toggle_reader_mode) |
| |
| with col2: |
| if st.button("π Ask a Question"): |
| logger.info("Ask a Question button clicked") |
| st.query_params["page"] = "home" |
| st.rerun() |
|
|
| with col3: |
| logger.debug("Rendering Romanized Text link") |
| st.markdown(f""" |
| <a href="?page=romanized_text&filename={filename}" style=" |
| display: inline-block; |
| padding: 10px 10px; |
| font-size: 16px; |
| font-weight: 400; |
| color: white; |
| background-color: #3498db; |
| border: none; |
| border-radius: 8px; |
| text-align: center; |
| text-decoration: none; |
| margin-top: 10px; |
| transition: all 0.3s ease; |
| text-transform: uppercase; |
| letter-spacing: 0.5px; |
| width: -webkit-fill-available; |
| "> |
| π Romanized Text |
| </a> |
| """, unsafe_allow_html=True) |
|
|
| |
| with st.expander("π Page Content", expanded=True): |
| logger.debug("Displaying page content in expander") |
| st.markdown(pdf_details['page_text'], unsafe_allow_html=True) |
| |
| |
| metadata_html = f""" |
| <table class="metadata-table"> |
| <tr><td>PDF Name</td><td>{pdf_details['metadata'].get('title', filename)}</td></tr> |
| <tr><td>Page</td><td>{pdf_details['current_page']}</td></tr> |
| <tr><td>Author</td><td>{pdf_details['metadata'].get('author', 'N/A')}</td></tr> |
| <tr><td>Total Pages</td><td>{pdf_details['total_pages']}</td></tr> |
| <tr><td>Language</td><td>{pdf_details['language']}</td></tr> |
| <tr><td>File Size</td><td>{pdf_details['file_size_kb']}</td></tr> |
| </table> |
| """ |
| st.markdown(metadata_html, unsafe_allow_html=True) |
| logger.info(f"Completed rendering PDF details page for {filename}") |
| |
| except Exception as e: |
| logger.error(f"Error in display_pdf_details: {str(e)}", exc_info=True) |
| st.error(f"An error occurred: {e}") |
| |
| def display_romanized_text_page(data): |
| """ |
| Displays romanized text and PDF details in a Streamlit layout. |
| Takes preprocessed data instead of filename. |
| """ |
| logger.info(f"Displaying romanized text page for file: {data['filename']}") |
| try: |
| st.markdown( |
| """ |
| <style> |
| .metadata { |
| display: flex; |
| justify-content: space-between; |
| margin-bottom: 20px; |
| font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; |
| font-size: 16px; |
| color: #34495e; |
| margin-top: 20px; |
| } |
| .metadata div { |
| text-align: left; |
| } |
| .page-section { |
| margin-bottom: 40px; |
| } |
| .page-header { |
| font-size: 20px; |
| color: #3498db; |
| font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; |
| margin-bottom: 10px; |
| font-weight: bold; |
| } |
| .page-text { |
| font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; |
| font-size: 16px; |
| color: #2c3e50; |
| line-height: 1.5; |
| margin-bottom: 20px; |
| } |
| hr { |
| border: 0; |
| height: 1px; |
| background: #ddd; |
| margin: 30px 0; |
| } |
| </style> |
| """, |
| unsafe_allow_html=True |
| ) |
| |
| |
| st.markdown("<h1 style='text-align: center; margin-top: -1%;}'>π Smart PDF Search</h1>", unsafe_allow_html=True) |
| |
| |
| word_count = len(data['full_text'].split()) |
| st.markdown( |
| f""" |
| <div class='metadata'> |
| <div> |
| <strong>Filename: </strong>{data['filename']} <br> |
| <strong>Total Pages: </strong>{data['total_pages']} <br> |
| <strong>File Size: </strong>{data['file_size_kb']}KB <br> |
| <strong>Total Words: </strong>{word_count} |
| </div> |
| </div> |
| """, |
| unsafe_allow_html=True |
| ) |
|
|
| |
| for page in data['pages']: |
| st.markdown( |
| f""" |
| <div class='page-section'> |
| <div class='page-header'>Page {page['page_number']}</div> |
| <div class='page-text'>{page['text']}</div> |
| <hr> |
| </div> |
| """, |
| unsafe_allow_html=True |
| ) |
| |
| except Exception as e: |
| logger.error(f"Unexpected error in display_romanized_text_page: {str(e)}", exc_info=True) |
| st.error(f"An unexpected error occurred: {e}") |