feat: add support for non-markdown files and improve drawings UI

- Added scanning and metadata tracking for non-markdown files (images, PDFs, videos, code files)
- Redesigned drawings editor header with new toolbar layout and dropdown menus
- Added file picker dropdown to easily open existing .excalidraw files
- Implemented new file creation flow with auto-generated filenames
- Added export options menu with PNG/SVG/JSON export variants
- Updated proxy config to support vault file access
- Adde
This commit is contained in:
2025-10-30 12:05:00 -04:00
parent b1f142c4f7
commit 6f01d65411
42 changed files with 2182 additions and 504 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 946 KiB

+72
View File
@@ -0,0 +1,72 @@
<#
.SYNOPSIS
Exemple de script PowerShell de démonstration.
.DESCRIPTION
Ce script montre comment :
- Définir des variables
- Lire des entrées utilisateur
- Utiliser des conditions et des boucles
- Écrire dans un fichier de log
- Gérer des erreurs
.AUTHOR
Bruno Charest
#>
# =======================
# ⚙️ Variables de base
# =======================
$UserName = $env:USERNAME
$DateNow = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogFile = "C:\Logs\ExampleScript.log"
# Crée le répertoire de logs si nécessaire
if (!(Test-Path (Split-Path $LogFile))) {
New-Item -Path (Split-Path $LogFile) -ItemType Directory -Force | Out-Null
}
# =======================
# 📝 Fonction pour journaliser les événements
# =======================
function Write-Log {
param (
[string]$Message,
[string]$Level = "INFO"
)
$LogEntry = "$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) [$Level] $Message"
Add-Content -Path $LogFile -Value $LogEntry
Write-Host $LogEntry
}
Write-Log "Script démarré par $UserName"
# =======================
# 👋 Interaction utilisateur
# =======================
$name = Read-Host "Quel est ton prénom"
Write-Log "Nom entré : $name"
# =======================
# 🔁 Exemple de boucle
# =======================
for ($i = 1; $i -le 5; $i++) {
Write-Host "Itération $i"
Start-Sleep -Milliseconds 500
}
# =======================
# ⚠️ Exemple de gestion d'erreur
# =======================
try {
# Exemple : tentative de suppression d’un fichier inexistant
Remove-Item "C:\FichierInexistant.txt" -ErrorAction Stop
} catch {
Write-Log "Erreur détectée : $($_.Exception.Message)" "ERROR"
}
# =======================
# ✅ Fin du script
# =======================
Write-Log "Script terminé avec succès."
Write-Host "`n✅ Exécution terminée avec succès."
Binary file not shown.
+217
View File
@@ -0,0 +1,217 @@
{
"elements": [
{
"type": "ellipse",
"version": 132,
"versionNonce": 283426111,
"isDeleted": false,
"id": "75xXCsrYeEIpx-bVFdD26",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"angle": 0,
"x": 152,
"y": 143.5,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"width": 245.50000000000003,
"height": 174.49999999999997,
"seed": 1925880401,
"groupIds": [],
"frameId": null,
"roundness": {
"type": 2
},
"boundElements": [],
"updated": 1761676663352,
"link": null,
"locked": false
},
{
"type": "line",
"version": 281,
"versionNonce": 1637513215,
"isDeleted": false,
"id": "Ee7Y120RtAdQsiCUEU0r7",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"angle": 0,
"x": 209.5,
"y": 158.5,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"width": 5.5,
"height": 147.5,
"seed": 1375870513,
"groupIds": [],
"frameId": null,
"roundness": {
"type": 2
},
"boundElements": [],
"updated": 1761676682202,
"link": null,
"locked": false,
"startBinding": null,
"endBinding": null,
"lastCommittedPoint": null,
"startArrowhead": null,
"endArrowhead": null,
"points": [
[
0,
0
],
[
5.5,
147.5
]
]
},
{
"type": "line",
"version": 200,
"versionNonce": 1266585960,
"isDeleted": false,
"id": "TwSQiyuxGNT_cWR9zLRTk",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"angle": 0,
"x": 213.57179654033308,
"y": 230.71709399425663,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"width": 187,
"height": 3.5,
"seed": 1447624159,
"groupIds": [],
"frameId": null,
"roundness": {
"type": 2
},
"boundElements": [],
"updated": 1761677094707,
"link": null,
"locked": false,
"startBinding": null,
"endBinding": null,
"lastCommittedPoint": null,
"startArrowhead": null,
"endArrowhead": null,
"points": [
[
0,
0
],
[
187,
-3.5
]
]
}
],
"appState": {
"showWelcomeScreen": true,
"theme": "dark",
"currentChartType": "bar",
"currentItemBackgroundColor": "transparent",
"currentItemEndArrowhead": "arrow",
"currentItemFillStyle": "solid",
"currentItemFontFamily": 1,
"currentItemFontSize": 20,
"currentItemOpacity": 100,
"currentItemRoughness": 1,
"currentItemStartArrowhead": null,
"currentItemStrokeColor": "#1e1e1e",
"currentItemRoundness": "round",
"currentItemStrokeStyle": "solid",
"currentItemStrokeWidth": 2,
"currentItemTextAlign": "left",
"cursorButton": "up",
"activeEmbeddable": null,
"draggingElement": null,
"editingElement": null,
"editingGroupId": null,
"editingLinearElement": null,
"activeTool": {
"type": "hand",
"customType": null,
"locked": false,
"lastActiveTool": null
},
"penMode": false,
"penDetected": false,
"errorMessage": null,
"exportBackground": true,
"exportScale": 2,
"exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null,
"gridSize": null,
"isBindingEnabled": true,
"defaultSidebarDockedPreference": false,
"isLoading": false,
"isResizing": false,
"isRotating": false,
"lastPointerDownWith": "touch",
"multiElement": null,
"name": "Untitled-2025-10-28-1436",
"contextMenu": null,
"openMenu": null,
"openPopup": null,
"openSidebar": null,
"openDialog": null,
"pasteDialog": {
"shown": false,
"data": null
},
"previousSelectedElementIds": {},
"resizingElement": null,
"scrolledOutside": false,
"scrollX": 141.7025899014401,
"scrollY": 113.16506876319784,
"selectedElementIds": {},
"selectedGroupIds": {},
"selectedElementsAreBeingDragged": false,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"showStats": false,
"startBoundElement": null,
"suggestedBindings": [],
"frameRendering": {
"enabled": true,
"clip": true,
"name": true,
"outline": true
},
"frameToHighlight": null,
"editingFrame": null,
"elementsToHighlight": null,
"toast": null,
"viewBackgroundColor": "#f8f9fa",
"zenModeEnabled": false,
"zoom": {
"value": 0.7938006350863728
},
"viewModeEnabled": false,
"pendingImageElementId": null,
"showHyperlinkPopup": false,
"selectedLinearElement": null,
"snapLines": [],
"originSnapOffset": null,
"objectsSnapModeEnabled": false,
"offsetLeft": 723,
"offsetTop": 228,
"width": 665,
"height": 546
},
"files": {}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 825 KiB

+61
View File
@@ -0,0 +1,61 @@
"""Exemple de script Python illustrant l'usage des dataclasses."""
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import Iterable
@dataclass
class Task:
"""Représente une tâche planifiée avec une durée estimée."""
name: str
estimated_minutes: int
created_at: datetime = field(default_factory=datetime.now)
completed: bool = False
def remaining_minutes(self) -> int:
"""Calcule le temps restant estimé."""
return 0 if self.completed else self.estimated_minutes
def mark_done(self) -> None:
"""Marque la tâche comme terminée."""
self.completed = True
def summarize(tasks: Iterable[Task]) -> str:
"""Retourne un résumé textuel de la charge de travail."""
task_list = list(tasks)
total = sum(task.estimated_minutes for task in task_list)
remaining = sum(task.remaining_minutes() for task in task_list)
done = total - remaining
return (
f"Tâches: {len(task_list)}\n"
f"Terminé: {done} min\n"
f"Restant: {remaining} min\n"
f"Charge totale: {total} min"
)
def main() -> None:
"""Point d'entrée du script avec quelques exemples."""
tasks = [
Task("Préparer la réunion", estimated_minutes=45),
Task("Répondre aux emails", estimated_minutes=20),
Task("Prototyper l'interface", estimated_minutes=90),
]
# Marquer une tâche comme terminée pour illustrer la logique.
tasks[1].mark_done()
print("Résumé du jour:")
print(summarize(tasks))
# Afficher l'échéance approximative si toutes les tâches sont démarrées maintenant.
deadline = datetime.now() + timedelta(minutes=sum(task.remaining_minutes() for task in tasks))
print(f"Heure de fin estimée: {deadline:%H:%M}")
if __name__ == "__main__":
main()