image display basic functionality
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import asyncio
|
||||
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import msal
|
||||
import aiohttp
|
||||
from rich.panel import Panel
|
||||
from rich import print as rprint
|
||||
|
||||
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.binding import Binding
|
||||
@@ -16,17 +13,13 @@ from textual.containers import Container, Horizontal, Vertical
|
||||
from textual.widgets import (
|
||||
Header,
|
||||
Footer,
|
||||
Static,
|
||||
Label,
|
||||
DataTable,
|
||||
Button,
|
||||
ListView,
|
||||
ListItem,
|
||||
LoadingIndicator,
|
||||
OptionList
|
||||
OptionList,
|
||||
)
|
||||
from textual.reactive import reactive
|
||||
from textual.worker import Worker, get_current_worker
|
||||
from textual import work
|
||||
from textual.widgets.option_list import Option
|
||||
|
||||
@@ -41,7 +34,7 @@ from maildir_gtd.screens.DocumentViewer import DocumentViewerScreen
|
||||
class FolderHistoryEntry:
|
||||
"""Represents an entry in the folder navigation history."""
|
||||
|
||||
def __init__(self, folder_id: str, folder_name: str, parent_id: str = None):
|
||||
def __init__(self, folder_id: str, folder_name: str, parent_id: str = ""):
|
||||
self.folder_id = folder_id
|
||||
self.folder_name = folder_name
|
||||
self.parent_id = parent_id
|
||||
@@ -101,13 +94,15 @@ class OneDriveTUI(App):
|
||||
with Container(id="main_container"):
|
||||
with Horizontal(id="top_bar"):
|
||||
yield Button("\uf148 Up", id="back_button", classes="hide")
|
||||
yield Label("Authenticating with Microsoft Graph API...", id="status_label")
|
||||
yield Label(
|
||||
"Authenticating with Microsoft Graph API...", id="status_label"
|
||||
)
|
||||
yield LoadingIndicator(id="loading")
|
||||
yield OptionList(
|
||||
Option("Following", id="following"),
|
||||
Option("Root", id="root"),
|
||||
id="view_options"
|
||||
)
|
||||
Option("Following", id="following"),
|
||||
Option("Root", id="root"),
|
||||
id="view_options",
|
||||
)
|
||||
|
||||
with Container(id="auth_container"):
|
||||
yield Label("", id="auth_message")
|
||||
@@ -125,7 +120,7 @@ class OneDriveTUI(App):
|
||||
self.query_one("#login_button").styles.width = "20"
|
||||
self.query_one("#view_options").border_title = "My Files"
|
||||
# Initialize the table
|
||||
table = self.query_one("#items_table")
|
||||
table = self.query_one("#items_table", DataTable)
|
||||
table.cursor_type = "row"
|
||||
table.add_columns("◇", "Name", "Last Modified", "Size", "Web URL")
|
||||
table.focus()
|
||||
@@ -173,13 +168,17 @@ class OneDriveTUI(App):
|
||||
@work
|
||||
async def get_token_silent(self, account):
|
||||
"""Get token silently."""
|
||||
token_response = self.msal_app.acquire_token_silent(self.scopes, account=account)
|
||||
token_response = self.msal_app.acquire_token_silent(
|
||||
self.scopes, account=account
|
||||
)
|
||||
if token_response and "access_token" in token_response:
|
||||
self.access_token = token_response["access_token"]
|
||||
self.is_authenticated = True
|
||||
self.load_initial_data()
|
||||
else:
|
||||
self.query_one("#status_label").update("Silent authentication failed. Please log in.")
|
||||
self.query_one("#status_label").update(
|
||||
"Silent authentication failed. Please log in."
|
||||
)
|
||||
self.query_one("#auth_container").remove_class("hide")
|
||||
self.query_one("#loading").remove()
|
||||
|
||||
@@ -237,11 +236,13 @@ class OneDriveTUI(App):
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
"https://graph.microsoft.com/v1.0/me/drives",
|
||||
headers=headers
|
||||
"https://graph.microsoft.com/v1.0/me/drives", headers=headers
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
self.notify(f"Failed to load drives: {response.status}", severity="error")
|
||||
self.notify(
|
||||
f"Failed to load drives: {response.status}",
|
||||
severity="error",
|
||||
)
|
||||
return
|
||||
|
||||
drives_data = await response.json()
|
||||
@@ -269,7 +270,9 @@ class OneDriveTUI(App):
|
||||
if self.selected_drive_id:
|
||||
self.load_followed_items()
|
||||
|
||||
async def on_option_list_option_selected(self, event: OptionList.OptionSelected) -> None:
|
||||
async def on_option_list_option_selected(
|
||||
self, event: OptionList.OptionSelected
|
||||
) -> None:
|
||||
"""Handle option list selection."""
|
||||
selected_option = event.option.id
|
||||
if selected_option == "following":
|
||||
@@ -286,12 +289,20 @@ class OneDriveTUI(App):
|
||||
selected_id = event.row_key.value
|
||||
self.open_item(selected_id)
|
||||
|
||||
async def on_data_table_row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
||||
async def on_data_table_row_highlighted(
|
||||
self, event: DataTable.RowHighlighted
|
||||
) -> None:
|
||||
self.selected_item_id = event.row_key.value
|
||||
|
||||
def open_item(self, selected_id: str):
|
||||
if selected_id:
|
||||
self.folder_history.append(FolderHistoryEntry(self.current_folder_id, self.current_folder_name, self.selected_drive_id))
|
||||
self.folder_history.append(
|
||||
FolderHistoryEntry(
|
||||
self.current_folder_id,
|
||||
self.current_folder_name,
|
||||
self.selected_drive_id,
|
||||
)
|
||||
)
|
||||
# Get an item from current items by ID string
|
||||
selected_row = self.current_items[selected_id]
|
||||
|
||||
@@ -303,22 +314,31 @@ class OneDriveTUI(App):
|
||||
self.notify(f"Selected folder: {item_name}", timeout=1)
|
||||
# Load items in the folder
|
||||
self.query_one("#back_button").remove_class("hide")
|
||||
self.query_one("#status_label").update(f"Loading items in folder: {item_name}")
|
||||
self.load_drive_folder_items(folder_id=selected_id, drive_id=selected_row.get("parentReference", {}).get("driveId", self.selected_drive_id))
|
||||
self.query_one("#status_label").update(
|
||||
f"Loading items in folder: {item_name}"
|
||||
)
|
||||
self.load_drive_folder_items(
|
||||
folder_id=selected_id,
|
||||
drive_id=selected_row.get("parentReference", {}).get(
|
||||
"driveId", self.selected_drive_id
|
||||
),
|
||||
)
|
||||
|
||||
else:
|
||||
self.notify(f"Selected file: {item_name}")
|
||||
self.action_view_document()
|
||||
|
||||
@work
|
||||
async def load_drive_folder_items(self, folder_id: str = "", drive_id: str = "", track_history: bool = True):
|
||||
async def load_drive_folder_items(
|
||||
self, folder_id: str = "", drive_id: str = "", track_history: bool = True
|
||||
):
|
||||
"""Load root items from the selected drive."""
|
||||
if not self.access_token or not self.selected_drive_id:
|
||||
return
|
||||
|
||||
self.query_one("#status_label").update("Loading drive folder items...")
|
||||
headers = {"Authorization": f"Bearer {self.access_token}"}
|
||||
url = f"https://graph.microsoft.com/v1.0/me/drive/root/children"
|
||||
url = "https://graph.microsoft.com/v1.0/me/drive/root/children"
|
||||
|
||||
if folder_id and drive_id and folder_id != "root":
|
||||
url = f"https://graph.microsoft.com/v1.0/drives/{drive_id}/items/{folder_id}/children"
|
||||
@@ -326,30 +346,38 @@ class OneDriveTUI(App):
|
||||
# self.folder_history.append(FolderHistoryEntry(folder_id, self.current_folder_name, drive_id))
|
||||
self.selected_drive_id = drive_id
|
||||
self.current_folder_id = folder_id
|
||||
self.current_folder_name = self.current_items[folder_id].get("name", "Unknown")
|
||||
self.current_folder_name = self.current_items[folder_id].get(
|
||||
"name", "Unknown"
|
||||
)
|
||||
try:
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url, headers=headers) as response:
|
||||
if response.status != 200:
|
||||
self.notify(f"Failed to load drive items: {response.status}", severity="error")
|
||||
self.notify(
|
||||
f"Failed to load drive items: {response.status}",
|
||||
severity="error",
|
||||
)
|
||||
return
|
||||
|
||||
items_data = await response.json()
|
||||
|
||||
|
||||
# Update the table with the root items
|
||||
self.update_items_table(items_data.get("value", []))
|
||||
except Exception as e:
|
||||
self.notify(f"Error loading root items: {str(e)}", severity="error")
|
||||
|
||||
#update the status label with breadcrumbs from the folder_history
|
||||
# update the status label with breadcrumbs from the folder_history
|
||||
if self.folder_history:
|
||||
breadcrumbs = " / \uf07b ".join([entry.folder_name for entry in self.folder_history])
|
||||
self.query_one("#status_label").update(f"\uf07b {breadcrumbs} / \uf07b {self.current_folder_name}")
|
||||
breadcrumbs = " / \uf07b ".join(
|
||||
[entry.folder_name for entry in self.folder_history]
|
||||
)
|
||||
self.query_one("#status_label").update(
|
||||
f"\uf07b {breadcrumbs} / \uf07b {self.current_folder_name}"
|
||||
)
|
||||
else:
|
||||
self.query_one("#status_label").update(f" \uf07b {self.current_folder_name}")
|
||||
|
||||
self.query_one("#status_label").update(
|
||||
f" \uf07b {self.current_folder_name}"
|
||||
)
|
||||
|
||||
@work
|
||||
async def load_followed_items(self):
|
||||
@@ -361,18 +389,20 @@ class OneDriveTUI(App):
|
||||
headers = {"Authorization": f"Bearer {self.access_token}"}
|
||||
|
||||
try:
|
||||
url = f"https://graph.microsoft.com/v1.0/me/drive/following"
|
||||
url = "https://graph.microsoft.com/v1.0/me/drive/following"
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url, headers=headers) as response:
|
||||
if response.status != 200:
|
||||
self.notify(f"Failed to load followed items: {response.status}", severity="error")
|
||||
self.notify(
|
||||
f"Failed to load followed items: {response.status}",
|
||||
severity="error",
|
||||
)
|
||||
return
|
||||
|
||||
items_data = await response.json()
|
||||
followed_items = items_data.get("value", [])
|
||||
|
||||
|
||||
# Update the table with the followed items
|
||||
self.update_items_table(followed_items)
|
||||
except Exception as e:
|
||||
@@ -402,7 +432,9 @@ class OneDriveTUI(App):
|
||||
last_modified = item.get("lastModifiedDateTime", "")
|
||||
if last_modified:
|
||||
try:
|
||||
date_obj = datetime.fromisoformat(last_modified.replace('Z', '+00:00'))
|
||||
date_obj = datetime.fromisoformat(
|
||||
last_modified.replace("Z", "+00:00")
|
||||
)
|
||||
last_modified = date_obj.strftime("%Y-%m-%d %H:%M")
|
||||
except:
|
||||
pass
|
||||
@@ -422,10 +454,9 @@ class OneDriveTUI(App):
|
||||
size_str = "N/A"
|
||||
|
||||
web_url = item.get("webUrl", "")
|
||||
item_id = item.get("id")
|
||||
|
||||
# Limit filename length to 160 characters
|
||||
display_name = name[:50] + '...' if len(name) > 50 else name
|
||||
display_name = name[:50] + "..." if len(name) > 50 else name
|
||||
|
||||
# Add row to table with the appropriate icon class for styling
|
||||
row_key = table.add_row(
|
||||
@@ -434,7 +465,7 @@ class OneDriveTUI(App):
|
||||
last_modified,
|
||||
size_str,
|
||||
web_url,
|
||||
key=item.get("id")
|
||||
key=item.get("id"),
|
||||
)
|
||||
|
||||
# Add item to the list of current items keyed by row_key so we can look up all information later
|
||||
@@ -490,10 +521,14 @@ class OneDriveTUI(App):
|
||||
return
|
||||
|
||||
selected_name = selected_row.get("name")
|
||||
drive_id = selected_row.get("parentReference", {}).get("driveId", self.selected_drive_id)
|
||||
drive_id = selected_row.get("parentReference", {}).get(
|
||||
"driveId", self.selected_drive_id
|
||||
)
|
||||
web_url = selected_row.get("webUrl", "")
|
||||
# Open the document viewer screen with all required details
|
||||
viewer = DocumentViewerScreen(self.selected_item_id, selected_name, self.access_token, drive_id)
|
||||
viewer = DocumentViewerScreen(
|
||||
self.selected_item_id, selected_name, self.access_token, drive_id
|
||||
)
|
||||
viewer.web_url = web_url # Pass the webUrl to the viewer
|
||||
self.push_screen(viewer)
|
||||
|
||||
@@ -509,7 +544,11 @@ class OneDriveTUI(App):
|
||||
self.current_folder_name = previous_entry.folder_name
|
||||
if len(self.folder_history) <= 0:
|
||||
self.query_one("#back_button").add_class("hide")
|
||||
self.load_drive_folder_items(folder_id=previous_entry.folder_id, drive_id=previous_entry.parent_id, track_history=False)
|
||||
self.load_drive_folder_items(
|
||||
folder_id=previous_entry.folder_id,
|
||||
drive_id=previous_entry.parent_id,
|
||||
track_history=False,
|
||||
)
|
||||
else:
|
||||
self.notify("No previous folder to navigate back to")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user