@@ -13,6 +13,7 @@ public sealed class MainViewModel : ObservableObject, IDisposable
1313 private readonly RangeObservableCollection < NoteItem > _allNotes ;
1414 private readonly RangeObservableCollection < NoteItem > _visibleNotes ;
1515 private readonly InfostackerPublishingService _infostackerPublishingService ;
16+ private readonly ApplicationActivityLog _activityLog ;
1617 private CancellationTokenSource ? _indexCancellation ;
1718 private CancellationTokenSource ? _mediaRefreshCancellation ;
1819 private CancellationTokenSource ? _publishCancellation ;
@@ -46,17 +47,24 @@ public sealed class MainViewModel : ObservableObject, IDisposable
4647 private const string UntaggedFilterKey = "__untagged__" ;
4748
4849 public MainViewModel (
49- InfostackerPublishingService ? infostackerPublishingService = null )
50- : this ( infostackerPublishingService , useSampleDataForTesting : false )
50+ InfostackerPublishingService ? infostackerPublishingService = null ,
51+ ApplicationActivityLog ? activityLog = null )
52+ : this (
53+ infostackerPublishingService ,
54+ activityLog ,
55+ useSampleDataForTesting : false )
5156 {
5257 }
5358
5459 private MainViewModel (
5560 InfostackerPublishingService ? infostackerPublishingService ,
61+ ApplicationActivityLog ? activityLog ,
5662 bool useSampleDataForTesting )
5763 {
5864 _infostackerPublishingService =
5965 infostackerPublishingService ?? new InfostackerPublishingService ( ) ;
66+ // Share failures are recoverable, but still need the application log's full exception details.
67+ _activityLog = activityLog ?? new ApplicationActivityLog ( ) ;
6068 _allNotes = new RangeObservableCollection < NoteItem > ( ) ;
6169 _visibleNotes = new RangeObservableCollection < NoteItem > ( ) ;
6270 NavigationItems = [ ] ;
@@ -97,8 +105,9 @@ private MainViewModel(
97105 /// need representative note data without opening a user folder.
98106 /// </summary>
99107 public static MainViewModel CreateWithSampleDataForTesting (
100- InfostackerPublishingService ? infostackerPublishingService = null )
101- => new ( infostackerPublishingService , useSampleDataForTesting : true ) ;
108+ InfostackerPublishingService ? infostackerPublishingService = null ,
109+ ApplicationActivityLog ? activityLog = null )
110+ => new ( infostackerPublishingService , activityLog , useSampleDataForTesting : true ) ;
102111
103112 public ObservableCollection < NavigationItem > NavigationItems { get ; }
104113 public ObservableCollection < NoteItem > NotesView => _visibleNotes ;
@@ -850,6 +859,8 @@ private static void DeleteCopiedImports(IEnumerable<ImportedPdf> importedPdfs)
850859 }
851860 catch ( InfostackerPublishingException exception )
852861 {
862+ // Preserve the wrapped transport or parsing cause while the dialog shows a friendly message.
863+ _activityLog . TryWriteOperationFailure ( "Publishing a public link" , exception ) ;
853864 ShareStatusText = exception . Message ;
854865 SetStatus ( exception . Message ) ;
855866 return null ;
@@ -868,8 +879,12 @@ public void ConfirmPublicLinkCopied(string publicUrl)
868879 SetStatus ( $ "Published note to Infostacker: { publicUrl } ") ;
869880 }
870881
871- public void ReportClipboardFailure ( string message )
882+ public void ReportClipboardFailure ( string message , Exception ? exception = null )
872883 {
884+ // Clipboard failures occur after publishing, so record them separately from upload failures.
885+ _activityLog . TryWriteOperationFailure (
886+ "Copying a public link to the clipboard" ,
887+ exception ?? new InvalidOperationException ( message ) ) ;
873888 ShareStatusText =
874889 $ "The note was published, but the public link could not be copied: { message } ";
875890 SetStatus ( "Note published, but copying the public link failed" ) ;
0 commit comments