/// <inheritdoc/>
        public ShortenedNoteViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IThemeService themeService,
            IBaseUrlService webviewBaseUrl,
            SearchableHtmlConverter searchableTextConverter,
            IRepositoryStorageService repositoryService,
            IFeedbackService feedbackService,
            ISettingsService settingsService,
            ICryptor cryptor,
            SafeListModel safes,
            NoteModel noteFromRepository)
            : base(navigationService, languageService, svgIconService, themeService, webviewBaseUrl, searchableTextConverter, repositoryService, feedbackService, settingsService, cryptor, safes, noteFromRepository)
        {
            if (_unlockedContent != null)
            {
                // Create a short version for large notes, with only the first part of the note.
                // This is a performance improvement if there are large notes in the repository.
                HtmlShortener shortener = new HtmlShortener();
                shortener.WantedLength    = 600; // Should be enough even for settings with
                shortener.WantedTagNumber = 20;  // small font and very height notes.

                string shortenedContent = shortener.Shorten(_unlockedContent);
                if (shortenedContent.Length != _unlockedContent.Length)
                {
                    // Because the note will be truncated, we have to build the searchable content
                    // first, before overwriting the original content.
                    string dummy = SearchableContent;
                    _unlockedContent = shortenedContent;
                }
            }
        }
示例#2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NoteViewModel"/> class.
        /// </summary>
        public NoteViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IThemeService themeService,
            IBaseUrlService webviewBaseUrl,
            SearchableHtmlConverter searchableTextConverter,
            IRepositoryStorageService repositoryService,
            IFeedbackService feedbackService,
            ISettingsService settingsService,
            ICryptor cryptor,
            SafeListModel safes,
            NoteModel noteFromRepository)
            : base(navigationService, languageService, svgIconService, themeService, webviewBaseUrl)
        {
            _repositoryService       = repositoryService;
            _feedbackService         = feedbackService;
            _settingsService         = settingsService;
            _searchableTextConverter = searchableTextConverter;
            _cryptor = cryptor;
            _safes   = safes;
            MarkSearchableContentAsDirty();
            PushNoteToOnlineStorageCommand   = new RelayCommand(PushNoteToOnlineStorage);
            PullNoteFromOnlineStorageCommand = new RelayCommand(PullNoteFromOnlineStorage);
            ToggleShoppingModeCommand        = new RelayCommand(ToggleShoppingMode);
            GoBackCommand = new RelayCommand(GoBack);

            Model            = noteFromRepository;
            _unlockedContent = IsInSafe ? UnlockIfSafeOpen(Model.HtmlContent) : Model.HtmlContent;
        }
        public void DoesNotShowContentWhenSafeIsClosed()
        {
            SearchableHtmlConverter          searchableConverter = new SearchableHtmlConverter();
            Mock <IRepositoryStorageService> repositoryService   = new Mock <IRepositoryStorageService>();
            Mock <ISettingsService>          settingsService     = new Mock <ISettingsService>();
            Mock <ICryptor> cryptor = new Mock <ICryptor>();

            SafeListModel safes = new SafeListModel(new[]
            {
                new SafeModel {
                    Id = Guid.NewGuid()
                },
            });
            NoteModel note = new NoteModel {
                Id = Guid.NewGuid(), HtmlContent = "secret", SafeId = safes[0].Id
            };

            NoteViewModel noteViewModel = new NoteViewModel(
                new Mock <INavigationService>().Object,
                new Mock <ILanguageService>().Object,
                new Mock <ISvgIconService>().Object,
                new Mock <IThemeService>().Object,
                new Mock <IBaseUrlService>().Object,
                searchableConverter,
                repositoryService.Object,
                new Mock <IFeedbackService>().Object,
                settingsService.Object,
                cryptor.Object,
                safes,
                new List <string>(),
                note);

            Assert.IsNull(noteViewModel.UnlockedHtmlContent);
            Assert.IsNull(noteViewModel.SearchableContent);
        }
        public void NormalizeWhitespacesLeavesTagsIntact()
        {
            string note = @"  Hello  <p> world  </p>  ";
            string res  = SearchableHtmlConverter.NormalizeWhitespaces(note);

            Assert.AreEqual(" Hello <p> world </p> ", res);
        }
        public void ModifiedNoteIsEncryptedAndStored()
        {
            string modelHtmlContent = "c2VjcmV0";

            byte[]                           safeKey             = new byte[] { 88 };
            SettingsModel                    settingsModel       = new SettingsModel();
            SearchableHtmlConverter          searchableConverter = new SearchableHtmlConverter();
            Mock <IRepositoryStorageService> repositoryService   = new Mock <IRepositoryStorageService>();
            Mock <ISettingsService>          settingsService     = new Mock <ISettingsService>();

            settingsService.
            Setup(m => m.LoadSettingsOrDefault()).Returns(settingsModel);
            Mock <ICryptor> cryptor = new Mock <ICryptor>();

            cryptor.
            Setup(m => m.Decrypt(It.IsAny <byte[]>(), It.Is <byte[]>(v => v == safeKey))).
            Returns(CryptoUtils.StringToBytes("not secret anymore"));

            SafeListModel safes = new SafeListModel(new[]
            {
                new SafeModel {
                    Id = Guid.NewGuid(), Key = safeKey
                },
            });
            NoteModel note = new NoteModel {
                Id = Guid.NewGuid(), HtmlContent = modelHtmlContent, SafeId = safes[0].Id
            };

            NoteViewModel noteViewModel = new NoteViewModel(
                new Mock <INavigationService>().Object,
                new Mock <ILanguageService>().Object,
                new Mock <ISvgIconService>().Object,
                new Mock <IThemeService>().Object,
                new Mock <IBaseUrlService>().Object,
                searchableConverter,
                repositoryService.Object,
                new Mock <IFeedbackService>().Object,
                settingsService.Object,
                cryptor.Object,
                safes,
                new List <string>(),
                note);

            noteViewModel.UnlockedHtmlContent = "something new";
            noteViewModel.OnStoringUnsavedData();

            cryptor.Verify(m => m.Encrypt(
                               It.Is <byte[]>(p => p.SequenceEqual(CryptoUtils.StringToBytes("something new"))),
                               It.Is <byte[]>(p => p.SequenceEqual(safeKey)),
                               It.IsAny <string>(),
                               It.Is <string>(p => p == null)),
                           Times.Once);
            repositoryService.Verify(m => m.TrySaveRepository(It.IsAny <NoteRepositoryModel>()), Times.Once);
        }
        public void NormalizeWhitespacesAcceptsNullAndSpace()
        {
            string res = SearchableHtmlConverter.NormalizeWhitespaces(null);

            Assert.AreEqual(string.Empty, res);

            res = SearchableHtmlConverter.NormalizeWhitespaces(string.Empty);
            Assert.AreEqual(string.Empty, res);

            res = SearchableHtmlConverter.NormalizeWhitespaces(" ");
            Assert.AreEqual(" ", res);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="NoteRepositoryViewModel"/> class.
        /// </summary>
        public NoteRepositoryViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IThemeService themeService,
            IBaseUrlService webviewBaseUrl,
            IStoryBoardService storyBoardService,
            IFeedbackService feedbackService,
            ISettingsService settingsService,
            IEnvironmentService environmentService,
            ICryptoRandomSource randomSource,
            IRepositoryStorageService repositoryService)
            : base(navigationService, languageService, svgIconService, themeService, webviewBaseUrl)
        {
            _storyBoardService       = storyBoardService;
            _repositoryService       = repositoryService;
            _feedbackService         = feedbackService;
            _settingsService         = settingsService;
            _environmentService      = environmentService;
            _noteCryptor             = new Cryptor(NoteModel.CryptorPackageName, randomSource);
            _searchableTextConverter = new SearchableHtmlConverter();
            AllNotes      = new List <NoteViewModel>();
            FilteredNotes = new ObservableCollection <NoteViewModel>();

            _repositoryService.LoadRepositoryOrDefault(out NoteRepositoryModel noteRepository);
            Model = noteRepository;

            // Initialize commands and events
            ShowNoteCommand           = new RelayCommand <object>(ShowNote);
            NewNoteCommand            = new RelayCommand(NewNote);
            NewChecklistCommand       = new RelayCommand(NewChecklist);
            DeleteNoteCommand         = new RelayCommand <object>(DeleteNote);
            ClearFilterCommand        = new RelayCommand(ClearFilter);
            SynchronizeCommand        = new RelayCommand(Synchronize);
            ShowTransferCodeCommand   = new RelayCommand(ShowTransferCode);
            ShowSettingsCommand       = new RelayCommand(ShowSettings);
            ShowRecycleBinCommand     = new RelayCommand(ShowRecycleBin);
            ShowExportCommand         = new RelayCommand(ShowExport);
            ShowInfoCommand           = new RelayCommand(ShowInfo);
            OpenSafeCommand           = new RelayCommand(OpenSafe);
            CloseSafeCommand          = new RelayCommand(CloseSafe);
            ChangeSafePasswordCommand = new RelayCommand(ChangeSafePassword);

            Modified = false;

            // If a filter was set before e.g. opening a note, set the same filter again.
            if (!string.IsNullOrEmpty(_lastFilter))
            {
                Filter = _lastFilter;
            }
        }
        private void ApplyFilter(string filter)
        {
            string     normalizedFilter = SearchableHtmlConverter.NormalizeWhitespaces(filter);
            NoteFilter noteFilter       = new NoteFilter(normalizedFilter);

            FilteredNotes.Clear();
            foreach (NoteViewModel noteViewModel in AllNotes)
            {
                if (!noteViewModel.InRecyclingBin && noteFilter.ContainsPattern(noteViewModel.SearchableContent))
                {
                    FilteredNotes.Add(noteViewModel);
                }
            }
        }
        public NoteRepositoryViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IThemeService themeService,
            IBaseUrlService webviewBaseUrl,
            IStoryBoardService storyBoardService,
            IFeedbackService feedbackService,
            ISettingsService settingsService,
            IEnvironmentService environmentService,
            ICryptoRandomSource randomSource,
            IRepositoryStorageService repositoryService)
            : base(navigationService, languageService, svgIconService, themeService, webviewBaseUrl)
        {
            _storyBoardService       = storyBoardService;
            _repositoryService       = repositoryService;
            _feedbackService         = feedbackService;
            _settingsService         = settingsService;
            _environmentService      = environmentService;
            _noteCryptor             = new Cryptor(NoteModel.CryptorPackageName, randomSource);
            _searchableTextConverter = new SearchableHtmlConverter();
            AllNotes      = new List <NoteViewModel>();
            FilteredNotes = new ObservableCollection <NoteViewModel>();

            _repositoryService.LoadRepositoryOrDefault(out NoteRepositoryModel noteRepository);
            Model = noteRepository;

            // Initialize commands and events
            ShowNoteCommand           = new RelayCommand <Guid>(ShowNote);
            NewNoteCommand            = new RelayCommand(NewNote);
            NewChecklistCommand       = new RelayCommand(NewChecklist);
            DeleteNoteCommand         = new RelayCommand <Guid>(DeleteNote);
            ClearFilterCommand        = new RelayCommand(ClearFilter);
            SynchronizeCommand        = new RelayCommand(Synchronize);
            ShowTransferCodeCommand   = new RelayCommand(ShowTransferCode);
            ShowSettingsCommand       = new RelayCommand(ShowSettings);
            ShowRecycleBinCommand     = new RelayCommand(ShowRecycleBin);
            ShowInfoCommand           = new RelayCommand(ShowInfo);
            OpenSafeCommand           = new RelayCommand(OpenSafe);
            CloseSafeCommand          = new RelayCommand(CloseSafe);
            ChangeSafePasswordCommand = new RelayCommand(ChangeSafePassword);

            OnPropertyChanged(nameof(FilterButtonMagnifierVisible));
            OnPropertyChanged(nameof(FilterButtonCancelVisible));
            Modified = false;
        }
示例#10
0
        public NoteViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IBaseUrlService webviewBaseUrl,
            SearchableHtmlConverter searchableTextConverter,
            IRepositoryStorageService repositoryService,
            ISettingsService settingsService,
            NoteModel noteFromRepository)
            : base(navigationService, languageService, svgIconService, webviewBaseUrl)
        {
            _repositoryService       = repositoryService;
            _settingsService         = settingsService;
            _searchableTextConverter = searchableTextConverter;
            MarkSearchableContentAsDirty();
            GoBackCommand = new RelayCommand(GoBack);

            Model = noteFromRepository;
        }
        public void ShowsUnlockedContentWhenSafeIsOpen()
        {
            string modelHtmlContent = "c2VjcmV0";

            byte[] safeKey = new byte[] { 88 };
            SearchableHtmlConverter          searchableConverter = new SearchableHtmlConverter();
            Mock <IRepositoryStorageService> repositoryService   = new Mock <IRepositoryStorageService>();
            Mock <ISettingsService>          settingsService     = new Mock <ISettingsService>();
            Mock <ICryptor> cryptor = new Mock <ICryptor>();

            cryptor.
            Setup(m => m.Decrypt(It.IsAny <byte[]>(), It.Is <byte[]>(v => v == safeKey))).
            Returns(CryptoUtils.StringToBytes("not secret anymore"));

            SafeListModel safes = new SafeListModel(new[]
            {
                new SafeModel {
                    Id = Guid.NewGuid(), Key = safeKey
                },
            });
            NoteModel note = new NoteModel {
                Id = Guid.NewGuid(), HtmlContent = modelHtmlContent, SafeId = safes[0].Id
            };

            NoteViewModel noteViewModel = new NoteViewModel(
                new Mock <INavigationService>().Object,
                new Mock <ILanguageService>().Object,
                new Mock <ISvgIconService>().Object,
                new Mock <IThemeService>().Object,
                new Mock <IBaseUrlService>().Object,
                searchableConverter,
                repositoryService.Object,
                new Mock <IFeedbackService>().Object,
                settingsService.Object,
                cryptor.Object,
                safes,
                new List <string>(),
                note);

            Assert.AreEqual("not secret anymore", noteViewModel.UnlockedHtmlContent);
            Assert.AreEqual("not secret anymore", noteViewModel.SearchableContent);
        }
        private void ApplyFilter(string filter)
        {
            SettingsModel settings         = _settingsService?.LoadSettingsOrDefault();
            string        normalizedFilter = SearchableHtmlConverter.NormalizeWhitespaces(filter);
            NoteFilter    noteFilter       = new NoteFilter(normalizedFilter);

            FilteredNotes.Clear();
            foreach (NoteViewModel noteViewModel in AllNotes)
            {
                bool hideNote =
                    noteViewModel.InRecyclingBin ||
                    (settings.HideClosedSafeNotes && noteViewModel.IsLocked) ||
                    !noteFilter.ContainsPattern(noteViewModel.SearchableContent);

                if (!hideNote)
                {
                    FilteredNotes.Add(noteViewModel);
                }
            }
        }