diff --git a/MiraiNotes.Android/App.cs b/MiraiNotes.Android/App.cs index 591521b8..33899472 100644 --- a/MiraiNotes.Android/App.cs +++ b/MiraiNotes.Android/App.cs @@ -1,11 +1,11 @@ -using Android.App; -using AutoMapper; +using AutoMapper; using FluentValidation; using MiraiNotes.Abstractions.Data; using MiraiNotes.Abstractions.GoogleApi; using MiraiNotes.Abstractions.Services; using MiraiNotes.Android.Background; using MiraiNotes.Android.Common; +using MiraiNotes.Android.Common.Utils; using MiraiNotes.Android.Common.Validators; using MiraiNotes.Android.Interfaces; using MiraiNotes.Android.Services; @@ -112,8 +112,7 @@ private ILogger SetupLogging() { const string fileOutputTemplate = "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{Level}] {Message:lj}{NewLine}{Exception}"; - var externalFolder = Application.Context.GetExternalFilesDir(null).AbsolutePath; - var basePath = Path.Combine(externalFolder, "Logs"); + var basePath = AndroidUtils.GetLogsPath(); var loggerConfig = new LoggerConfiguration().MinimumLevel .Verbose(); diff --git a/MiraiNotes.Android/Common/Utils/AndroidUtils.cs b/MiraiNotes.Android/Common/Utils/AndroidUtils.cs index 7969ffbb..d3eb298d 100644 --- a/MiraiNotes.Android/Common/Utils/AndroidUtils.cs +++ b/MiraiNotes.Android/Common/Utils/AndroidUtils.cs @@ -178,5 +178,11 @@ public static bool IsViewVisibleOnScreen(Context context, View view) return actualPosition.Intersect(screen); } + + public static string GetLogsPath() + { + var externalFolder = Application.Context.GetExternalFilesDir(null).AbsolutePath; + return System.IO.Path.Combine(externalFolder, "Logs"); + } } } \ No newline at end of file diff --git a/MiraiNotes.Android/Common/Utils/MiscellaneousUtils.cs b/MiraiNotes.Android/Common/Utils/MiscellaneousUtils.cs index 6db38137..d1a30893 100644 --- a/MiraiNotes.Android/Common/Utils/MiscellaneousUtils.cs +++ b/MiraiNotes.Android/Common/Utils/MiscellaneousUtils.cs @@ -1,9 +1,9 @@ +using Android.App; +using Android.Content; using System; using System.IO; using System.Net.Http; using System.Threading.Tasks; -using Android.App; -using Android.Content; using AndroidGraphics = Android.Graphics; namespace MiraiNotes.Android.Common.Utils @@ -16,9 +16,14 @@ public class MiscellaneousUtils public static string GetAppVersion() { - return Application.Context.PackageManager + string appVersion = Application.Context.PackageManager .GetPackageInfo(Application.Context.PackageName, 0) .VersionName; +#if DEBUG + return $"{appVersion} - DEBUG"; +#else + return appVersion; +#endif } public static async Task DownloadProfileImage(string url, string googleUserId) diff --git a/MiraiNotes.Android/Properties/AndroidManifest.xml b/MiraiNotes.Android/Properties/AndroidManifest.xml index 965478d5..21cfacdc 100644 --- a/MiraiNotes.Android/Properties/AndroidManifest.xml +++ b/MiraiNotes.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/MiraiNotes.Android/ViewModels/Dialogs/AddEditTaskListDialogViewModel.cs b/MiraiNotes.Android/ViewModels/Dialogs/AddEditTaskListDialogViewModel.cs index 0aa581b0..0061a483 100644 --- a/MiraiNotes.Android/ViewModels/Dialogs/AddEditTaskListDialogViewModel.cs +++ b/MiraiNotes.Android/ViewModels/Dialogs/AddEditTaskListDialogViewModel.cs @@ -205,7 +205,8 @@ public async Task UpdateTaskList(TaskListItemViewModel taskList) private void Validate() { Errors.Clear(); - var validationResult = _validator.Validate(this); + var validationContext = new ValidationContext(this); + var validationResult = _validator.Validate(validationContext); Errors.AddRange(validationResult.ToDictionary()); RaisePropertyChanged(() => IsSaveButtonEnabled); } diff --git a/MiraiNotes.Android/ViewModels/Dialogs/AddSubTaskDialogViewModel.cs b/MiraiNotes.Android/ViewModels/Dialogs/AddSubTaskDialogViewModel.cs index 96a1fd32..deb8c64b 100644 --- a/MiraiNotes.Android/ViewModels/Dialogs/AddSubTaskDialogViewModel.cs +++ b/MiraiNotes.Android/ViewModels/Dialogs/AddSubTaskDialogViewModel.cs @@ -144,7 +144,8 @@ private async Task SaveSubTask() private void Validate() { Errors.Clear(); - var validationResult = _validator.Validate(this); + var validationContext = new ValidationContext(this); + var validationResult = _validator.Validate(validationContext); Errors.AddRange(validationResult.ToDictionary()); RaisePropertyChanged(() => IsSaveButtonEnabled); } diff --git a/MiraiNotes.Android/ViewModels/Dialogs/PasswordDialogViewModel.cs b/MiraiNotes.Android/ViewModels/Dialogs/PasswordDialogViewModel.cs index dd84b1fe..ec8aac30 100644 --- a/MiraiNotes.Android/ViewModels/Dialogs/PasswordDialogViewModel.cs +++ b/MiraiNotes.Android/ViewModels/Dialogs/PasswordDialogViewModel.cs @@ -159,7 +159,8 @@ private async Task SavePassword() private void Validate() { Errors.Clear(); - var validationResult = _validator.Validate(this); + var validationContext = new ValidationContext(this); + var validationResult = _validator.Validate(validationContext); Errors.AddRange(validationResult.ToDictionary()); RaisePropertyChanged(() => IsSaveButtonEnabled); } diff --git a/MiraiNotes.Android/ViewModels/Dialogs/TaskDateDialogViewModel.cs b/MiraiNotes.Android/ViewModels/Dialogs/TaskDateDialogViewModel.cs index 5233af17..f4a702f5 100644 --- a/MiraiNotes.Android/ViewModels/Dialogs/TaskDateDialogViewModel.cs +++ b/MiraiNotes.Android/ViewModels/Dialogs/TaskDateDialogViewModel.cs @@ -317,7 +317,8 @@ private void SendUpdatedDateMsg() private void Validate() { Errors.Clear(); - var validationResult = _validator.Validate(this); + var validationContext = new ValidationContext(this); + var validationResult = _validator.Validate(validationContext); Errors.AddRange(validationResult.ToDictionary()); RaisePropertyChanged(() => IsSaveButtonEnabled); } diff --git a/MiraiNotes.Android/ViewModels/MainViewModel.cs b/MiraiNotes.Android/ViewModels/MainViewModel.cs index 6f3bdaa4..3040f1ce 100644 --- a/MiraiNotes.Android/ViewModels/MainViewModel.cs +++ b/MiraiNotes.Android/ViewModels/MainViewModel.cs @@ -1,17 +1,20 @@ using MiraiNotes.Abstractions.Data; using MiraiNotes.Abstractions.Services; using MiraiNotes.Android.Common.Messages; +using MiraiNotes.Android.Common.Utils; using MiraiNotes.Android.Interfaces; using MiraiNotes.Android.Models; using MiraiNotes.Android.Models.Parameters; using MiraiNotes.Android.ViewModels.Dialogs; using MiraiNotes.Android.ViewModels.Settings; using MiraiNotes.Core.Enums; +using MiraiNotes.Shared.Utils; using MvvmCross.Commands; using MvvmCross.Navigation; using MvvmCross.Plugin.Messenger; using MvvmCross.ViewModels; using Serilog; +using System; using System.Threading.Tasks; namespace MiraiNotes.Android.ViewModels @@ -101,6 +104,22 @@ public MainViewModel( _backgroundTaskManager = backgroundTaskManager; } + public override Task Initialize() + { + try + { + Logger.Information($"{nameof(Prepare)}: Trying to delete old logs..."); + var logsPath = AndroidUtils.GetLogsPath(); + FileUtils.DeleteFilesInDirectory(logsPath, DateTime.Now.AddDays(-3)); + } + catch (Exception e) + { + Logger.Error(e, $"{nameof(Prepare)}: Unknonw error while trying to delete old logs"); + TelemetryService.TrackError(e); + } + return base.Initialize(); + } + public override void SetCommands() { base.SetCommands(); diff --git a/MiraiNotes.Android/ViewModels/NewTaskViewModel.cs b/MiraiNotes.Android/ViewModels/NewTaskViewModel.cs index ccc16471..620d7534 100644 --- a/MiraiNotes.Android/ViewModels/NewTaskViewModel.cs +++ b/MiraiNotes.Android/ViewModels/NewTaskViewModel.cs @@ -528,7 +528,8 @@ private void OnTaskDeleted(string taskId, bool hasParentTask) private void Validate() { Errors.Clear(); - var validationResult = _validator.Validate(Task); + var validationContext = new ValidationContext(Task); + var validationResult = _validator.Validate(validationContext); Errors.AddRange(validationResult.ToDictionary()); } diff --git a/MiraiNotes.Shared/Utils/FileUtils.cs b/MiraiNotes.Shared/Utils/FileUtils.cs new file mode 100644 index 00000000..12dd023d --- /dev/null +++ b/MiraiNotes.Shared/Utils/FileUtils.cs @@ -0,0 +1,21 @@ +using System; +using System.IO; +using System.Linq; + +namespace MiraiNotes.Shared.Utils +{ + public static class FileUtils + { + public static void DeleteFilesInDirectory(string dir, DateTime lastAccessTime) + { + var files = new DirectoryInfo(dir) + .GetFiles() + .Where(f => f.LastAccessTime < lastAccessTime) + .ToList(); + foreach (var file in files) + { + file.Delete(); + } + } + } +} diff --git a/MiraiNotes.UWP/Package.appxmanifest b/MiraiNotes.UWP/Package.appxmanifest index 57148cd2..1645b223 100644 --- a/MiraiNotes.UWP/Package.appxmanifest +++ b/MiraiNotes.UWP/Package.appxmanifest @@ -1,6 +1,6 @@  - + Mirai Notes diff --git a/MiraiNotes.UWP/Utils/MiscellaneousUtils.cs b/MiraiNotes.UWP/Utils/MiscellaneousUtils.cs index bf7e0bf5..31c1afbb 100644 --- a/MiraiNotes.UWP/Utils/MiscellaneousUtils.cs +++ b/MiraiNotes.UWP/Utils/MiscellaneousUtils.cs @@ -15,7 +15,7 @@ namespace MiraiNotes.UWP.Utils { - public class MiscellaneousUtils + public static class MiscellaneousUtils { const string USER_IMAGE_FILE_NAME = "user_image.png"; @@ -28,7 +28,12 @@ public static string GetAppVersion() var package = Package.Current; var packageId = package.Id; var version = packageId.Version; - return $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; + string appVersion = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; +#if DEBUG + return $"{appVersion} - DEBUG"; +#else + return appVersion; +#endif } /// @@ -166,7 +171,7 @@ public static async Task DownloadProfileImage(string url, string googleUserId) } } - public static T FindControl(UIElement parent, string ControlName) where + public static T FindControl(UIElement parent, string ControlName) where T : FrameworkElement { if (parent == null) @@ -189,5 +194,8 @@ public static T FindControl(UIElement parent, string ControlName) where } return result; } + + public static string GetLogsPath() + => Path.Combine(GetApplicationPath(), "Logs"); } } diff --git a/MiraiNotes.UWP/ViewModels/NavPageViewModel.cs b/MiraiNotes.UWP/ViewModels/NavPageViewModel.cs index 121521e4..c57ad9ac 100644 --- a/MiraiNotes.UWP/ViewModels/NavPageViewModel.cs +++ b/MiraiNotes.UWP/ViewModels/NavPageViewModel.cs @@ -18,22 +18,23 @@ using MiraiNotes.UWP.Interfaces; using MiraiNotes.UWP.Models; using MiraiNotes.UWP.Utils; +using Serilog; namespace MiraiNotes.UWP.ViewModels { public class NavPageViewModel : BaseViewModel { #region Members - private readonly ICustomDialogService _dialogService; private readonly IMessenger _messenger; private readonly INavigationService _navigationService; private readonly IUserCredentialService _userCredentialService; private readonly IMapper _mapper; private readonly IMiraiNotesDataService _dataService; - private readonly IDispatcherHelper _dispatcher; private readonly IAppSettingsService _appSettings; private readonly IBackgroundTaskManagerService _backgroundTaskManager; + private readonly ITelemetryService _telemetryService; + private readonly ILogger _logger; private object _selectedItem; @@ -167,9 +168,10 @@ public NavPageViewModel( IUserCredentialService userCredentialService, IMapper mapper, IMiraiNotesDataService dataService, - IDispatcherHelper dispatcher, IAppSettingsService appSettings, - IBackgroundTaskManagerService backgroundTaskManager) + IBackgroundTaskManagerService backgroundTaskManager, + ILogger logger, + ITelemetryService telemetryService) { _dialogService = dialogService; _messenger = messenger; @@ -177,9 +179,10 @@ public NavPageViewModel( _userCredentialService = userCredentialService; _mapper = mapper; _dataService = dataService; - _dispatcher = dispatcher; _appSettings = appSettings; _backgroundTaskManager = backgroundTaskManager; + _telemetryService = telemetryService; + _logger = logger.ForContext(); RegisterMessages(); SetCommands(); @@ -220,6 +223,7 @@ private void SetCommands() { PageLoadedCommand = new RelayCommand(async () => { + DeleteOldLogs(); await LoadProfileInfo(); await InitViewAsync(); }); @@ -589,6 +593,19 @@ private void SortTaskLists(TaskListSortType sortType) _isSelectionInProgress = false; } + private void DeleteOldLogs() + { + try + { + _logger.Information($"{nameof(DeleteOldLogs)}: Deleting old log files..."); + FileUtils.DeleteFilesInDirectory(MiscellaneousUtils.GetLogsPath(), DateTime.Now.AddDays(-3)); + } + catch (Exception e) + { + _logger.Error(e, $"{nameof(DeleteOldLogs)}: Unknown error while deleting old files.."); + _telemetryService.TrackError(e); + } + } #endregion } } \ No newline at end of file diff --git a/MiraiNotes.UWP/ViewModels/ViewModelLocator.cs b/MiraiNotes.UWP/ViewModels/ViewModelLocator.cs index 054ac2c5..363f95fe 100644 --- a/MiraiNotes.UWP/ViewModels/ViewModelLocator.cs +++ b/MiraiNotes.UWP/ViewModels/ViewModelLocator.cs @@ -180,7 +180,7 @@ private INavigationService SetupNavigation() private ILogger SetupLogging() { const string fileOutputTemplate = "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{Level}] {Message:lj}{NewLine}{Exception}"; - string basePath = Path.Combine(MiscellaneousUtils.GetApplicationPath(), "Logs"); + string basePath = MiscellaneousUtils.GetLogsPath(); var logs = new Dictionary { {typeof(NavPageViewModel).Namespace, "vm_.log" },