public void HandleNewBook_AddsMessage_IffReallyNew(bool reallyNew)
        {
            using (var collectionFolder = new TemporaryFolder("HandleNewBook_NewBook_AddsMessage_Collection"))
            {
                using (var repoFolder = new TemporaryFolder("HandleNewBook_NewBook_AddsMessage_Shared"))
                {
                    var bookFolderName1     = "New book";
                    var localBookFolderPath = SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, bookFolderName1, "Something");
                    var mockTcManager       = new Mock <ITeamCollectionManager>();
                    var tcLog = new TeamCollectionMessageLog(TeamCollectionManager.GetTcLogPathFromLcPath(collectionFolder.FolderPath));
                    var tc    = new TestFolderTeamCollection(mockTcManager.Object, collectionFolder.FolderPath,
                                                             repoFolder.FolderPath, tcLog);
                    tc.PutBook(localBookFolderPath);
                    if (reallyNew)
                    {
                        SIL.IO.RobustIO.DeleteDirectory(localBookFolderPath, true);
                    }

                    tc.HandleNewBook(new NewBookEventArgs()
                    {
                        BookFileName = "New book.bloom"
                    });

                    if (reallyNew)
                    {
                        var msg = tcLog.Messages[0];
                        Assert.That(msg.RawEnglishMessageTemplate, Is.EqualTo("A new book called '{0}' was added by a teammate."));
                    }
                    else
                    {
                        Assert.That(tcLog.Messages.Count, Is.EqualTo(0));
                    }
                }
            }
        }
Beispiel #2
0
        public void AnyBooksCheckedOutHereByCurrentUser_TrueOnlyForRealCheckouts()
        {
            using (var collectionFolder = new TemporaryFolder("AnyBooksCheckedOutHereByCurrentUser_TrueOnlyForRealCheckouts"))
            {
                using (var repoFolder = new TemporaryFolder("AnyBooksCheckedOutHereByCurrentUser_TrueOnlyForRealCheckouts"))
                {
                    TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");
                    var bookFolderName1     = "A very nice book book";
                    var localBookFolderPath = SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, bookFolderName1, "Something");
                    var mockTcManager       = new Mock <ITeamCollectionManager>();
                    var tcLog = new TeamCollectionMessageLog(TeamCollectionManager.GetTcLogPathFromLcPath(collectionFolder.FolderPath));
                    var tc    = new TestFolderTeamCollection(mockTcManager.Object, collectionFolder.FolderPath,
                                                             repoFolder.FolderPath, tcLog);

                    SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, "Another nice book", "Something");

                    Assert.That(tc.AnyBooksCheckedOutHereByCurrentUser, Is.False);                     // both currently local-only

                    tc.PutBook(localBookFolderPath);
                    Assert.That(tc.AnyBooksCheckedOutHereByCurrentUser, Is.False);                     // one local-only, one checked in

                    tc.AttemptLock(bookFolderName1, TeamCollectionManager.CurrentUser);
                    Assert.That(tc.AnyBooksCheckedOutHereByCurrentUser, Is.True);                     // one local-only, one checked out

                    tc.PutBook(localBookFolderPath, checkin: true);
                    tc.AttemptLock(bookFolderName1, "someoneElse.somewhere.org");
                    Assert.That(tc.AnyBooksCheckedOutHereByCurrentUser, Is.False);                     // one local-only, one checked out but to someone else.
                }
            }
        }
        public void HandleNewBook_RenamedBook_AddsRenameMessage()
        {
            using (var collectionFolder = new TemporaryFolder("HandleNewBook_RenamedBook_AddsRenameMessage_Collection"))
            {
                using (var repoFolder = new TemporaryFolder("HandleNewBook_RenamedBook_AddsRenameMessage_Shared"))
                {
                    var bookFolderName1     = "Renamed book";
                    var localBookFolderPath = SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, bookFolderName1, "Something");
                    var mockTcManager       = new Mock <ITeamCollectionManager>();
                    var tcLog = new TeamCollectionMessageLog(TeamCollectionManager.GetTcLogPathFromLcPath(collectionFolder.FolderPath));
                    var tc    = new TestFolderTeamCollection(mockTcManager.Object, collectionFolder.FolderPath,
                                                             repoFolder.FolderPath, tcLog);
                    tc.PutBook(localBookFolderPath);

                    SIL.IO.RobustIO.MoveDirectory(localBookFolderPath, Path.Combine(collectionFolder.FolderPath, "old name"));
                    // We could rename the book file too, but it doesn't matter for the current SUT

                    tc.HandleNewBook(new NewBookEventArgs()
                    {
                        BookFileName = "Renamed book.bloom"
                    });

                    var msg = tcLog.Messages[0];
                    Assert.That(msg.RawEnglishMessageTemplate, Is.EqualTo("The book \"{0}\" has been renamed to \"{1}\" by a teammate."));
                    Assert.That(msg.Param0, Is.EqualTo("old name"));
                    Assert.That(msg.Param1, Is.EqualTo("Renamed book"));
                }
            }
        }
        public CollectionModel(string pathToCollection, CollectionSettings collectionSettings,
                               BookSelection bookSelection,
                               SourceCollectionsList sourceCollectionsList,
                               BookCollection.Factory bookCollectionFactory,
                               EditBookCommand editBookCommand,
                               CreateFromSourceBookCommand createFromSourceBookCommand,
                               BookServer bookServer,
                               CurrentEditableCollectionSelection currentEditableCollectionSelection,
                               BookThumbNailer thumbNailer,
                               TeamCollectionManager tcManager,
                               BloomWebSocketServer webSocketServer,
                               BookCollectionHolder bookCollectionHolder,
                               LocalizationChangedEvent localizationChangedEvent)
        {
            _bookSelection         = bookSelection;
            _pathToCollection      = pathToCollection;
            _collectionSettings    = collectionSettings;
            _sourceCollectionsList = sourceCollectionsList;
            _bookCollectionFactory = bookCollectionFactory;
            _editBookCommand       = editBookCommand;
            _bookServer            = bookServer;
            _currentEditableCollectionSelection = currentEditableCollectionSelection;
            _thumbNailer              = thumbNailer;
            _tcManager                = tcManager;
            _webSocketServer          = webSocketServer;
            _bookCollectionHolder     = bookCollectionHolder;
            _localizationChangedEvent = localizationChangedEvent;

            createFromSourceBookCommand.Subscribe(CreateFromSourceBook);
        }
        public LibraryModel(string pathToLibrary, CollectionSettings collectionSettings,
                            //SendReceiver sendReceiver,
                            BookSelection bookSelection,
                            SourceCollectionsList sourceCollectionsList,
                            BookCollection.Factory bookCollectionFactory,
                            EditBookCommand editBookCommand,
                            CreateFromSourceBookCommand createFromSourceBookCommand,
                            BookServer bookServer,
                            CurrentEditableCollectionSelection currentEditableCollectionSelection,
                            BookThumbNailer thumbNailer,
                            TeamCollectionManager tcManager)
        {
            _bookSelection      = bookSelection;
            _pathToLibrary      = pathToLibrary;
            _collectionSettings = collectionSettings;
            //_sendReceiver = sendReceiver;
            _sourceCollectionsList = sourceCollectionsList;
            _bookCollectionFactory = bookCollectionFactory;
            _editBookCommand       = editBookCommand;
            _bookServer            = bookServer;
            _currentEditableCollectionSelection = currentEditableCollectionSelection;
            _thumbNailer = thumbNailer;
            _tcManager   = tcManager;

            createFromSourceBookCommand.Subscribe(CreateFromSourceBook);
        }
 public void Checkin_RenamedBook_DeletesOriginal_NoTombstone()
 {
     using (var collectionFolder =
                new TemporaryFolder("Checkin_RenamedBook_DeletesOriginal_Collection"))
     {
         using (var repoFolder =
                    new TemporaryFolder("Checkin_RenamedBook_DeletesOriginal_Shared"))
         {
             var mockTcManager = new Mock <ITeamCollectionManager>();
             TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");
             var tc = new FolderTeamCollection(mockTcManager.Object, collectionFolder.FolderPath,
                                               repoFolder.FolderPath);
             tc.CollectionId = Bloom.TeamCollection.TeamCollection.GenerateCollectionId();
             var oldFolderPath =
                 SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, "old name", "book content");
             tc.PutBook(oldFolderPath);
             tc.AttemptLock("old name");
             SyncAtStartupTests.SimulateRename(tc, "old name", "middle name");
             SyncAtStartupTests.SimulateRename(tc, "middle name", "new name");
             tc.PutBook(Path.Combine(collectionFolder.FolderPath, "new name"), true);
             Assert.That(File.Exists(tc.GetPathToBookFileInRepo("new name")), Is.True);
             Assert.That(File.Exists(tc.GetPathToBookFileInRepo("old name")), Is.False,
                         "old name was not deleted");
             var status = tc.GetLocalStatus("new name");
             Assert.That(status.oldName ?? "", Is.Empty,
                         "Should stop tracking previous name once we cleaned it up");
             Assert.That(tc.KnownToHaveBeenDeleted("old name"), Is.False);
             TeamCollectionManager.ForceCurrentUserForTests(null);
         }
     }
 }
 public WorkspaceModel(BookSelection bookSelection, string directoryPath, TeamCollectionManager tcManager, CollectionSettings collectionSettings)
 {
     _bookSelection                   = bookSelection;
     _directoryPath                   = directoryPath;
     _tcManager                       = tcManager;
     _collectionSettings              = collectionSettings;
     _bookSelection.SelectionChanged += OnSelectionChanged;
 }
 /// <summary>
 /// Set a new TC status image. Called at Idle time or startup, on the UI thread.
 /// N.B.: It also gets called if the user tries to do something and the TeamCollection suddenly
 /// recognizes it is in a disconnected state.
 /// </summary>
 public void SetTeamCollectionStatus(TeamCollectionManager tcManager)
 {
     _tcStatusButton.Update(tcManager.CollectionStatus);
     // This will cause the CollectionsTabBookPane to reload the status of the book
     // (and the collection itself), which will trickle down to the status panel.
     if (tcManager.CollectionStatus == TeamCollectionStatus.Disconnected)
     {
         _webSocketServer.SendEvent("bookStatus", "reload");
     }
 }
Beispiel #9
0
 public BookServer(Book.Factory bookFactory, BookStorage.Factory storageFactory,
                   BookStarter.Factory bookStarterFactory, Configurator.Factory configuratorFactory,
                   TeamCollectionManager tcManager = null)
 {
     _bookFactory         = bookFactory;
     _storageFactory      = storageFactory;
     _bookStarterFactory  = bookStarterFactory;
     _configuratorFactory = configuratorFactory;
     _tcManager           = tcManager;
 }
Beispiel #10
0
        public void OneTimeSetUp()
        {
            _localCollection = new TemporaryFolder("TeamCollectionApiTests");
            var collectionPath = Path.Combine(_localCollection.FolderPath,
                                              Path.ChangeExtension(Path.GetFileName(_localCollection.FolderPath), ".bloomCollection"));

            _tcManager = new TeamCollectionManager(collectionPath, new BloomWebSocketServer(), new BookRenamedEvent(), null, null, null, null);
            _api       = new TeamCollectionApi(new CurrentEditableCollectionSelection(), new CollectionSettings(collectionPath), new BookSelection(),
                                               _tcManager, null, null, null);
        }
        public void HandleBookRename_CaseChangeOnly_WorksRight()
        {
            // Setup //
            const string originalBookName = "A new book";
            var          bookBuilder      = new BookFolderBuilder()
                                            .WithRootFolder(_collectionFolder.FolderPath)
                                            .WithTitle(originalBookName)
                                            .WithHtm("<html><body>This is just a dummy</body></html>")
                                            .Build();
            string bookFolderPath = bookBuilder.BuiltBookFolderPath;
            string htmlPath       = bookBuilder.BuiltBookHtmPath;

            TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");
            _collection.PutBook(bookFolderPath);

            var locked = _collection.AttemptLock(originalBookName);

            Assert.That(locked, Is.True, "successfully checked out book to [email protected]");

            // SUT: rename changes status in local collection folder, but not in shared repo folder
            const string newBookName       = "A New Book";
            var          newBookFolderPath = Path.Combine(_collectionFolder.FolderPath, newBookName);

            File.Move(htmlPath, Path.Combine(bookFolderPath, newBookName + ".htm"));
            // renaming directory doesn't work when names are 'the same'
            var tempPath = Path.Combine(_collectionFolder.FolderPath, "tempxxyy");

            Directory.Move(bookFolderPath, tempPath);
            Directory.Move(tempPath, newBookFolderPath);

            _collection.HandleBookRename(originalBookName, newBookName);

            _collection.PutBook(newBookFolderPath, true);

            var newRepoPath = Path.Combine(_sharedFolder.FolderPath, "Books", newBookName + ".bloom");

            // It should not have been deleted! This is a regression test for BL-10156.
            // The danger is that Windows considers the old and new names the same, so after
            // we move the file to the new name, if we go to delete the old name, we get rid of the new one.
            Assert.That(File.Exists(newRepoPath));

            // Did it get renamed?
            var matchingFiles = Directory.EnumerateFiles(Path.Combine(_sharedFolder.FolderPath, "Books"), newBookName + ".bloom").ToArray();

            Assert.That(matchingFiles[0], Is.EqualTo(Path.Combine(_sharedFolder.FolderPath, "Books", newBookName + ".bloom")));

            var newStatus  = _collection.GetLocalStatus(newBookName);
            var repoStatus = _collection.GetStatus(newBookName);

            Assert.That(newStatus, Is.Not.Null, "local status of renamed book is not null");
            Assert.That(repoStatus, Is.Not.Null, "repo status of renamed book is not null");
            Assert.That(newStatus.checksum, Is.EqualTo(repoStatus.checksum), "checksums of local and remote match after rename");
            Assert.That(newStatus.lockedBy, Is.EqualTo(null), "lockedBy of local and remote match after rename");
            Assert.That(newStatus.oldName, Is.Null, "local status has original name cleared after commit");
        }
        public void ConnectToTeamCollection_SetsUpRequiredFiles()
        {
            using (var collectionFolder = new TemporaryFolder("FolderTeamCollectionTests2_Collection"))
            {
                using (var sharedFolder = new TemporaryFolder("FolderTeamCollectionTests2_Shared"))
                {
                    var bookFolderName1 = "Some book";
                    SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, bookFolderName1, "Something");
                    // BL-9573 tests cases where the book name isn't exactly the same as the folder name
                    var bookFolderName2 = "Some other book";
                    SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, "Some other name altogether",
                                                    "Strange book content", bookFolderName2);
                    var settingsFileName =
                        Path.ChangeExtension(Path.GetFileName(collectionFolder.FolderPath), "bloomCollection");
                    var settingsPath = Path.Combine(collectionFolder.FolderPath, settingsFileName);

                    // As an aside, this is a convenient place to check that a TC manager created when TC settings does not exist
                    // functions and does not have a current collection.
                    var tcManager = new TeamCollectionManager(settingsPath, null, new BookRenamedEvent(),
                                                              new BookStatusChangeEvent(), null, null);
                    Assert.That(tcManager.CurrentCollection, Is.Null);

                    RobustFile.WriteAllText(settingsPath, "This is a fake settings file");
                    FolderTeamCollection.CreateTeamCollectionLinkFile(collectionFolder.FolderPath,
                                                                      sharedFolder.FolderPath);

                    var nonBookFolder = Path.Combine(collectionFolder.FolderPath, "Some other folder");
                    Directory.CreateDirectory(nonBookFolder);
                    tcManager = new TeamCollectionManager(settingsPath, null, new BookRenamedEvent(),
                                                          new BookStatusChangeEvent(), null, null);
                    var collection = tcManager.CurrentCollection;

                    // sut
                    (collection as FolderTeamCollection)?.SetupTeamCollection(sharedFolder.FolderPath,
                                                                              new NullWebSocketProgress());

                    Assert.That(collection, Is.Not.Null);
                    var joinCollectionPath =
                        Path.Combine(sharedFolder.FolderPath, "Join this Team Collection.JoinBloomTC");
                    Assert.That(File.Exists(joinCollectionPath));

                    var teamCollectionLinkPath =
                        Path.Combine(collectionFolder.FolderPath, TeamCollectionManager.TeamCollectionLinkFileName);
                    Assert.That(File.Exists(teamCollectionLinkPath));
                    var collectionFileContent = RobustFile.ReadAllText(teamCollectionLinkPath);
                    Assert.That(collectionFileContent, Is.EqualTo(sharedFolder.FolderPath));
                    var sharedSettingsPath = Path.Combine(collectionFolder.FolderPath, settingsFileName);
                    Assert.That(RobustFile.ReadAllText(sharedSettingsPath), Is.EqualTo("This is a fake settings file"));
                    var bookPath = Path.Combine(sharedFolder.FolderPath, "Books", bookFolderName1 + ".bloom");
                    Assert.That(File.Exists(bookPath));
                    var bookPath2 = Path.Combine(sharedFolder.FolderPath, "Books", bookFolderName2 + ".bloom");
                    Assert.That(File.Exists(bookPath2));
                }
            }
        }
        public void OkToCheckIn_GivesCorrectResults()
        {
            using (var collectionFolder =
                       new TemporaryFolder("OkToCheckIn_GivesCorrectResults_Collection"))
            {
                using (var repoFolder =
                           new TemporaryFolder("OkToCheckIn_GivesCorrectResults_Shared"))
                {
                    var mockTcManager = new Mock <ITeamCollectionManager>();
                    TeamCollectionManager.ForceCurrentUserForTests("");
                    var tc = new FolderTeamCollection(mockTcManager.Object, collectionFolder.FolderPath,
                                                      repoFolder.FolderPath);
                    tc.CollectionId = Bloom.TeamCollection.TeamCollection.GenerateCollectionId();
                    var bookFolderPath =
                        SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, "some name", "book content");
                    Assert.That(tc.OkToCheckIn("some name"), Is.False, "can't check in new book when not registered");

                    TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");
                    Assert.That(tc.OkToCheckIn("some name"), Is.True, "can check in new book");

                    tc.PutBook(bookFolderPath, true);
                    tc.AttemptLock("some name");
                    Assert.That(tc.OkToCheckIn("some name"), Is.True,
                                "can check in unmodified book with normal checkout status");

                    TeamCollectionManager.ForceCurrentUserForTests("");
                    Assert.That(tc.OkToCheckIn("some name"), Is.False,
                                "normally permitted checkin is forbidden with no registration");
                    TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");

                    var status    = tc.GetStatus("some name");
                    var altStatus = status.WithChecksum("some random thing");
                    tc.WriteBookStatus("some name", altStatus);
                    tc.WriteLocalStatus("some name", status);
                    Assert.That(tc.OkToCheckIn("some name"), Is.False, "can't check in, mysteriously modified in repo");

                    altStatus = status.WithLockedBy(null);
                    tc.WriteBookStatus("some name", altStatus);
                    tc.WriteLocalStatus("some name", status);
                    Assert.That(tc.OkToCheckIn("some name"), Is.True,
                                "special case, repo has lost checkout status, but not locked or modified");

                    altStatus = status.WithLockedBy("*****@*****.**");
                    tc.WriteBookStatus("some name", altStatus);
                    tc.WriteLocalStatus("some name", status);
                    Assert.That(tc.OkToCheckIn("some name"), Is.False, "conflicting lock in repo");

                    TeamCollectionManager.ForceCurrentUserForTests("null");
                }
            }
        }
        public void Setup()
        {
            TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");

            _sharedFolder     = new TemporaryFolder("TeamCollection_Shared");
            _collectionFolder = new TemporaryFolder("TeamCollection_Local");
            _tcLog            = new TeamCollectionMessageLog(TeamCollectionManager.GetTcLogPathFromLcPath(_collectionFolder.FolderPath));
            FolderTeamCollection.CreateTeamCollectionLinkFile(_collectionFolder.FolderPath,
                                                              _sharedFolder.FolderPath);

            _mockTcManager           = new Mock <ITeamCollectionManager>();
            _collection              = new FolderTeamCollection(_mockTcManager.Object, _collectionFolder.FolderPath, _sharedFolder.FolderPath, _tcLog);
            _collection.CollectionId = Bloom.TeamCollection.TeamCollection.GenerateCollectionId();
        }
        public void HandleModifiedFile_CheckedOutToMe_RemotelyToOther_RaisesCheckedOutByOtherAndErrorMessage()
        {
            // Setup //
            // Simulate a book was just overwritten with contents indicating a remote checkout,
            // while locally it is checked out to me.
            const string bookFolderName = "My conflict book";
            var          bookBuilder    = new BookFolderBuilder()
                                          .WithRootFolder(_collectionFolder.FolderPath)
                                          .WithTitle(bookFolderName)
                                          .Build();
            string bookFolderPath = bookBuilder.BuiltBookFolderPath;

            TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");

            _collection.PutBook(bookFolderPath);
            // Temporarily, it looks locked by Nancy in both places.
            _collection.AttemptLock("My conflict book", "*****@*****.**");
            var status = _collection.GetStatus("My conflict book").WithLockedBy(TeamCollectionManager.CurrentUser);

            // Now it is locally checked out to me. (The state changes are in the opposite order to what
            // we're trying to simulate, because we don't have an easy way to change remote checkout status without
            // changing local status to match at the same time.)
            _collection.WriteLocalStatus("My conflict book", status);
            var prevMessages = _tcLog.Messages.Count;

            // System Under Test...basically HandleModifiedFile, but this is a convenient place to
            // make sure we take the right path through this calling method.
            _collection.QueuePendingBookChange(
                new BookRepoChangeEventArgs()
            {
                BookFileName = $"{bookFolderName}.bloom"
            });
            _collection.HandleRemoteBookChangesOnIdle(null, new EventArgs());

            // Verification
            var eventArgs = (BookStatusChangeEventArgs)_mockTcManager.Invocations[2].Arguments[0];

            Assert.That(eventArgs.CheckedOutByWhom, Is.EqualTo(CheckedOutBy.Other));

            Assert.That(_tcLog.Messages[prevMessages].MessageType, Is.EqualTo(MessageAndMilestoneType.Error));
            Assert.That(_tcLog.Messages[prevMessages].L10NId, Is.EqualTo("TeamCollection.ConflictingCheckout"));
            TeamCollectionManager.ForceCurrentUserForTests(null);
        }
        public void HandleBookRename_CheckedOutToMe_FixesStatusProperly()
        {
            // Setup //
            const string originalBookName = "Hello. Goodbye!";
            var          bookBuilder      = new BookFolderBuilder()
                                            .WithRootFolder(_collectionFolder.FolderPath)
                                            .WithTitle(originalBookName)
                                            .WithHtm("<html><body>This is just a dummy</body></html>")
                                            .Build();
            string bookFolderPath = bookBuilder.BuiltBookFolderPath;
            string htmlPath       = bookBuilder.BuiltBookHtmPath;

            TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");
            _collection.PutBook(bookFolderPath);

            var locked = _collection.AttemptLock(originalBookName);

            Assert.That(locked, Is.True, "successfully checked out book to [email protected]");

            // SUT: rename changes status in local collection folder, but not in shared repo folder
            const string newBookName       = "Testing is Fun. Sometimes";
            var          newBookFolderPath = Path.Combine(_collectionFolder.FolderPath, newBookName);

            File.Move(htmlPath, Path.Combine(bookFolderPath, newBookName + ".htm"));
            Directory.Move(bookFolderPath, newBookFolderPath);

            _collection.HandleBookRename(originalBookName, newBookName);
            var newStatus  = _collection.GetLocalStatus(newBookName);
            var repoStatus = _collection.GetStatus(newBookName);

            Assert.That(newStatus, Is.Not.Null, "local status of renamed book is not null");
            Assert.That(repoStatus, Is.Not.Null, "repo status of renamed book is not null");
            Assert.That(newStatus.checksum, Is.EqualTo(repoStatus.checksum), "checksums of local and remote match after rename");
            Assert.That(newStatus.lockedBy, Is.EqualTo(repoStatus.lockedBy), "lockedBy of local and remote match after rename");
            Assert.That(newStatus.lockedWhen, Is.EqualTo(repoStatus.lockedWhen), "lockedWhen of local and remote match after rename");
            Assert.That(newStatus.lockedWhere, Is.EqualTo(repoStatus.lockedWhere), "lockedWhere of local and remote match after rename");
            Assert.That(newStatus.oldName, Is.EqualTo(originalBookName), "local status has original name in oldName field after rename");
            Assert.That(repoStatus.oldName, Is.Null, "repo status still has null oldName field after rename");
        }
Beispiel #17
0
        public BookCollection(string path, CollectionType collectionType,
                              BookSelection bookSelection, TeamCollectionManager tcm = null, BloomWebSocketServer webSocketServer = null)
        {
            _path            = path;
            _bookSelection   = bookSelection;
            _tcManager       = tcm;
            _webSocketServer = webSocketServer;

            Type = collectionType;

            if (collectionType == CollectionType.TheOneEditableCollection)
            {
                MakeCollectionCSSIfMissing();
            }

            CollectionCreated?.Invoke(this, new EventArgs());

            if (ContainsDownloadedBooks)
            {
                WatchDirectory();
            }
        }
 public void OneTimeTearDown()
 {
     _collectionFolder.Dispose();
     _repoFolder.Dispose();
     TeamCollectionManager.ForceCurrentUserForTests(null);
 }
        public void SyncLocalAndRepoCollectionFiles_SyncsInRightDirection()
        {
            using (var collectionFolder =
                       new TemporaryFolder("SyncLocalAndRepoCollectionFiles_SyncsInRightDirection_Collection"))
            {
                using (var repoFolder =
                           new TemporaryFolder("SyncLocalAndRepoCollectionFiles_SyncsInRightDirection_Shared"))
                {
                    var settingsFileName =
                        Path.ChangeExtension(Path.GetFileName(collectionFolder.FolderPath), "bloomCollection");
                    var settingsPath = Path.Combine(collectionFolder.FolderPath, settingsFileName);
                    var tcManager    = new TeamCollectionManager(settingsPath, null, new BookRenamedEvent(),
                                                                 new BookStatusChangeEvent(), null, null);
                    var tc = new FolderTeamCollection(tcManager, collectionFolder.FolderPath, repoFolder.FolderPath);
                    tc.CollectionId = Bloom.TeamCollection.TeamCollection.GenerateCollectionId();
                    var bloomCollectionPath =
                        Bloom.TeamCollection.TeamCollection.CollectionPath(collectionFolder.FolderPath);
                    Assert.That(tc.LocalCollectionFilesRecordedSyncTime, Is.EqualTo(DateTime.MinValue));
                    File.WriteAllText(bloomCollectionPath, "This is a fake collection file");
                    var collectionStylesPath = Path.Combine(collectionFolder.FolderPath, "customCollectionStyles.css");
                    RobustFile.WriteAllText(collectionStylesPath, "This is the collection styles");

                    // SUT 1: nothing in repo, no sync time file. Copies to repo.
                    tc.SyncLocalAndRepoCollectionFiles();

                    var localWriteTime1 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime1, Is.LessThanOrEqualTo(DateTime.Now));
                    Assert.That(localWriteTime1, Is.GreaterThan(DateTime.Now.Subtract(new TimeSpan(0, 0, 5, 0))));
                    var otherFilesPath = FolderTeamCollection.GetRepoProjectFilesZipPath(repoFolder.FolderPath);
                    Assert.That(File.Exists(otherFilesPath));
                    var anotherPlace = Path.Combine(repoFolder.FolderPath, "anotherPlace.zip");
                    RobustFile.Copy(otherFilesPath, anotherPlace);
                    var repoWriteTime1       = new FileInfo(otherFilesPath).LastWriteTime;
                    var collectionWriteTime1 = new FileInfo(bloomCollectionPath).LastWriteTime;

                    // SUT 2: nothing has changed. But it's a startup, so sync still happens to local.
                    tc.SyncLocalAndRepoCollectionFiles();
                    var localWriteTime2 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime2, Is.GreaterThanOrEqualTo(localWriteTime1));
                    Assert.That(new FileInfo(otherFilesPath).LastWriteTime, Is.EqualTo(repoWriteTime1));
                    Assert.That(new FileInfo(bloomCollectionPath).LastWriteTime,
                                Is.GreaterThanOrEqualTo(collectionWriteTime1));

                    File.WriteAllText(bloomCollectionPath, "This is a modified fake collection file");
                    var collectionWriteTime2 = new FileInfo(bloomCollectionPath).LastWriteTime;

                    // SUT 3: local change copied to repo (only when not at startup)
                    tc.SyncLocalAndRepoCollectionFiles(false);
                    var localWriteTime3 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime3, Is.GreaterThan(localWriteTime1),
                                "localWriteTime3 should be greater than localWriteTime1");
                    var repoWriteTime2 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTime2, Is.GreaterThan(repoWriteTime1),
                                "repoWriteTime2 should be greater than repoWriteTime1");
                    // not modified by sync
                    Assert.That(new FileInfo(bloomCollectionPath).LastWriteTime, Is.EqualTo(collectionWriteTime2));

                    File.WriteAllText(bloomCollectionPath, "This is a further modified fake collection file");
                    var collectionWriteTime3 = new FileInfo(bloomCollectionPath).LastWriteTime;
                    var version2Path         = Path.Combine(repoFolder.FolderPath, "version2.zip");
                    RobustFile.Copy(otherFilesPath, version2Path);
                    // modify the remote version by copying the old one back.
                    Thread.Sleep(10);
                    RobustFile.Copy(anotherPlace, otherFilesPath, true);
                    var repoWriteTime3 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTime3, Is.GreaterThan(collectionWriteTime3),
                                "repo file written after local collection file [sanity check]");

                    // SUT 4: both changed: repo wins
                    tc.SyncLocalAndRepoCollectionFiles();
                    var localWriteTime4 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime4, Is.GreaterThan(localWriteTime3),
                                "localWriteTime4 should be greater than localWriteTime3");
                    var repoWriteTime4 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTime4, Is.EqualTo(repoWriteTime3));                     // not modified by sync
                    Assert.That(new FileInfo(bloomCollectionPath).LastWriteTime, Is.GreaterThan(collectionWriteTime3),
                                "bloomCollection LastWriteTime should be greater than collectionWriteTime3");
                    // We got the original back.
                    Assert.That(File.ReadAllText(bloomCollectionPath), Is.EqualTo("This is a fake collection file"));

                    Thread.Sleep(10);
                    var allowedWords = Path.Combine(collectionFolder.FolderPath, "Allowed Words");
                    Directory.CreateDirectory(allowedWords);
                    File.WriteAllText(Path.Combine(allowedWords, "file1.txt"), "fake word list");

                    // SUT5: local allowed words added
                    tc.SyncLocalAndRepoCollectionFiles(false);
                    var localWriteTime5 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime5, Is.GreaterThan(localWriteTime4),
                                "localWriteTime5 should be greater than localWriteTime4");
                    var repoWriteTime5 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTime5, Is.GreaterThan(repoWriteTime4),
                                "repoWriteTime5 should be greater than repoWriteTime4");

                    Thread.Sleep(5);
                    var sampleTexts = Path.Combine(collectionFolder.FolderPath, "Sample Texts");
                    Directory.CreateDirectory(sampleTexts);
                    File.WriteAllText(Path.Combine(allowedWords, "sample1.txt"), "fake sample list");

                    // SUT6: local sample texts added
                    tc.SyncLocalAndRepoCollectionFiles(false);
                    var localWriteTime6 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime6, Is.GreaterThan(localWriteTime5),
                                "localWriteTime6 should be greater than localWriteTime5");
                    var repoWriteTime6 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTime6, Is.GreaterThan(repoWriteTime5),
                                "repoWriteTime6 should be greater than repoWriteTime5");

                    Thread.Sleep(10);
                    File.WriteAllText(Path.Combine(allowedWords, "sample1.txt"), "fake sample list");

                    // SUT7: local file write time modified, but not actually changed. Want the sync time to
                    // update, but NOT to write the remote file.
                    tc.SyncLocalAndRepoCollectionFiles(false);
                    var localWriteTime7 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTime7, Is.GreaterThan(localWriteTime6),
                                "localWriteTime7 should be greater than localWriteTime6");
                    var repoWriteTime7 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTime7, Is.EqualTo(repoWriteTime6));

                    tc._haveShownRemoteSettingsChangeWarning = false;
                    File.WriteAllText(bloomCollectionPath, "This is a modified fake collection file, for SUT 8");
                    var collectionWriteTimeBeforeSut8 = new FileInfo(bloomCollectionPath).LastWriteTime;
                    var localWriteTimeBeforeSut8      = tc.LocalCollectionFilesRecordedSyncTime();
                    var repoWriteTimeBeforeSut8       = new FileInfo(otherFilesPath).LastWriteTime;

                    // SUT 8: local change copied to repo on idle
                    tc.SyncLocalAndRepoCollectionFiles(false);
                    Assert.That(tc._haveShownRemoteSettingsChangeWarning, Is.False, "user should not have been warned");
                    var localWriteTimeAfterSut8 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTimeAfterSut8, Is.GreaterThan(localWriteTimeBeforeSut8),
                                "localWriteTime should increase copying on idle");
                    var repoWriteTimeAfterSut8 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTimeAfterSut8, Is.GreaterThan(repoWriteTimeBeforeSut8),
                                "repoWriteTime should increase copying on idle");
                    // not modified by sync
                    Assert.That(new FileInfo(bloomCollectionPath).LastWriteTime,
                                Is.EqualTo(collectionWriteTimeBeforeSut8));

                    // modify the remote version by copying version2 back.
                    Thread.Sleep(10);
                    var repoWriteTimeBeforeSut9Copy = new FileInfo(otherFilesPath).LastWriteTime;
                    RobustFile.Copy(version2Path, otherFilesPath, true);
                    var collectionWriteTimeBeforeSut9 = new FileInfo(bloomCollectionPath).LastWriteTime;
                    var repoWriteTimeBeforeSut9       = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTimeBeforeSut9, Is.GreaterThan(repoWriteTimeBeforeSut9Copy),
                                "repo file written after local collection file [sanity check]");
                    tc._haveShownRemoteSettingsChangeWarning = false;

                    // SUT9: repo modified, doing check on idle. No changes or warning.
                    tc.SyncLocalAndRepoCollectionFiles(false);
                    Assert.That(tc._haveShownRemoteSettingsChangeWarning, Is.False, "user should not have been warned");
                    var collectionWriteTimeAfterSut9 = new FileInfo(bloomCollectionPath).LastWriteTime;
                    Assert.That(collectionWriteTimeAfterSut9, Is.EqualTo(collectionWriteTimeBeforeSut9),
                                "local settings should not have been modified");

                    File.WriteAllText(bloomCollectionPath, "This is a modified fake collection file, for SUT 10");
                    var collectionWriteTimeBeforeSut10 = new FileInfo(bloomCollectionPath).LastWriteTime;
                    var localWriteTimeBeforeSut10      = tc.LocalCollectionFilesRecordedSyncTime();
                    var repoWriteTimeBeforeSut10       = new FileInfo(otherFilesPath).LastWriteTime;

                    // SUT10: both modified, doing check on idle. No changes. User warned.
                    using (var nfes = new ErrorReport.NonFatalErrorReportExpected())
                    {
                        tc.SyncLocalAndRepoCollectionFiles(false);
                    }

                    Assert.That(tc._haveShownRemoteSettingsChangeWarning, Is.True, "user should have been warned");
                    var localWriteTimeAfterSut10 = tc.LocalCollectionFilesRecordedSyncTime();
                    Assert.That(localWriteTimeAfterSut10, Is.EqualTo(localWriteTimeBeforeSut10),
                                "localWriteTime should not be changed by idle sync where both changed");
                    var repoWriteTimeAfterSut10 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTimeAfterSut10, Is.EqualTo(repoWriteTimeBeforeSut10),
                                "repo should not be modified by idle sync where both changed");                 // not modified by sync
                    Assert.That(new FileInfo(bloomCollectionPath).LastWriteTime,
                                Is.EqualTo(collectionWriteTimeBeforeSut10),
                                "bloomCollection LastWriteTime should not be changed by idle sync both changed");

                    // Get everything back in sync
                    tc.SyncLocalAndRepoCollectionFiles();
                    var localWriteTimeBeforeSut11 = tc.LocalCollectionFilesRecordedSyncTime();
                    var repoWriteTimeBeforeSut11  = new FileInfo(otherFilesPath).LastWriteTime;
                    RobustFile.WriteAllText(collectionStylesPath, "This is the modified collection styles");

                    // SUT11: custom collection styles modified while Bloom was not running. Copied to repo.
                    tc.SyncLocalAndRepoCollectionFiles();
                    var repoWriteTimeAfterSut11 = new FileInfo(otherFilesPath).LastWriteTime;
                    Assert.That(repoWriteTimeAfterSut11, Is.GreaterThanOrEqualTo(repoWriteTimeBeforeSut11));
                    var localWriteTimeAfterSut11 = tc.LocalCollectionFilesRecordedSyncTime();
                    // We will update the sync time even though the write is the other way.
                    Assert.That(localWriteTimeAfterSut11, Is.GreaterThan(localWriteTimeBeforeSut11));
                    Assert.That(File.ReadAllText(collectionStylesPath),
                                Is.EqualTo("This is the modified collection styles"));
                }
            }
        }
Beispiel #20
0
 public ReadersApi(BookSelection _bookSelection, TeamCollectionManager tcManager)
 {
     this._bookSelection = _bookSelection;
     _tcManager          = tcManager;
 }
        public delegate CollectionTabView Factory();      //autofac uses this

        public CollectionTabView(CollectionModel model,
                                 SelectedTabChangedEvent selectedTabChangedEvent,
                                 TeamCollectionManager tcManager, BookSelection bookSelection,
                                 WorkspaceTabSelection tabSelection, BloomWebSocketServer webSocketServer, LocalizationChangedEvent localizationChangedEvent)
        {
            _model           = model;
            _tabSelection    = tabSelection;
            _bookSelection   = bookSelection;
            _webSocketServer = webSocketServer;
            _tcManager       = tcManager;

            BookCollection.CollectionCreated += OnBookCollectionCreated;

            InitializeComponent();
            _reactControl.SetLocalizationChangedEvent(localizationChangedEvent);             // after InitializeComponent, which creates it.
            BackColor               = _reactControl.BackColor = Palette.GeneralBackground;
            _toolStrip.Renderer     = new NoBorderToolStripRenderer();
            _toolStripLeft.Renderer = new NoBorderToolStripRenderer();

            // When going down to Shrink Stage 3 (see WorkspaceView), we want the right-side toolstrip to take precedence
            // (Settings, Other Collection).
            // This essentially makes the TC Status button's zIndex less than the buttons on the right side.
            _toolStripLeft.SendToBack();

            //TODO splitContainer1.SplitterDistance = _collectionListView.PreferredWidth;

            if (SIL.PlatformUtilities.Platform.IsMono)
            {
                BackgroundColorsForLinux();
            }

            selectedTabChangedEvent.Subscribe(c =>
            {
                if (c.To == this)
                {
                    Logger.WriteEvent("Entered Collections Tab");
                    if (_bookChangesPending && _bookSelection.CurrentSelection != null)
                    {
                        UpdateForBookChanges(_bookSelection.CurrentSelection);
                    }
                }
            });
            SetTeamCollectionStatus(tcManager);
            TeamCollectionManager.TeamCollectionStatusChanged += (sender, args) =>
            {
                if (IsHandleCreated && !IsDisposed)
                {
                    SafeInvoke.InvokeIfPossible("update TC status", this, false,
                                                () => SetTeamCollectionStatus(tcManager));
                }
            };
            _tcStatusButton.Click += (sender, args) =>
            {
                // Reinstate this to see messages from before we started up.
                // We think it might be too expensive to show a list as long as this might get.
                // Instead, in the short term we may add a button to show the file.
                // Later we may implement some efficient way to scroll through them.
                // tcManager.CurrentCollection?.MessageLog?.LoadSavedMessages();

                dynamic messageBundle = new DynamicJson();
                messageBundle.showReloadButton = tcManager.MessageLog.ShouldShowReloadButton;
                _webSocketServer.LaunchDialog("TeamCollectionDialog", messageBundle);
                tcManager.CurrentCollectionEvenIfDisconnected?.MessageLog.WriteMilestone(MessageAndMilestoneType.LogDisplayed);
            };

            // We don't want this control initializing until team collections sync (if any) is done.
            // That could change, but for now we're not trying to handle async changes arriving from
            // the TC to the local collection, and as part of that, the collection tab doesn't expect
            // the local collection to change because of TC stuff once it starts loading.
            Controls.Remove(_reactControl);
            bookSelection.SelectionChanged += (sender, e) => BookSelectionChanged(bookSelection.CurrentSelection);
        }
Beispiel #22
0
        public static int Handle(HydrateParameters options)
        {
            if (!Directory.Exists(options.Path))
            {
                if (options.Path.Contains(".htm"))
                {
                    Debug.WriteLine("Supply only the directory, not the path to the file.");
                    Console.Error.WriteLine("Supply only the directory, not the path to the file.");
                }
                else
                {
                    Debug.WriteLine("Could not find " + options.Path);
                    Console.Error.WriteLine("Could not find " + options.Path);
                }
                return(1);
            }
            Console.WriteLine("Starting Hydrating.");

            var layout = new Layout
            {
                SizeAndOrientation = SizeAndOrientation.FromString(options.SizeAndOrientation)
            };

            if (File.Exists(TeamCollectionManager.GetTcLinkPathFromLcPath(Path.GetDirectoryName(options.Path))))
            {
                throw new ApplicationException("Hydrate command cannot currently be used in Team Collections");
                // To make this possible, we'd need to spin up a TeamCollectionManager and TeamCollection and pass the latter
                // to the Book as its SaveContext and still changes would be forbidden unless the book was checked out.
            }

            var collectionSettings = new CollectionSettings
            {
                XMatterPackName     = options.XMatter,
                Language1Iso639Code = options.VernacularIsoCode,
                Language2Iso639Code = string.IsNullOrWhiteSpace(options.NationalLanguage1IsoCode) ? options.VernacularIsoCode : options.NationalLanguage1IsoCode,
                Language3Iso639Code = options.NationalLanguage2IsoCode
            };

            XMatterPackFinder xmatterFinder = new XMatterPackFinder(new[] { BloomFileLocator.GetFactoryXMatterDirectory(), });
            var locator = new BloomFileLocator(collectionSettings, xmatterFinder, ProjectContext.GetFactoryFileLocations(),
                                               ProjectContext.GetFoundFileLocations(), ProjectContext.GetAfterXMatterFileLocations());

            // alwaysSaveable is fine here, as we already checked it's not a TC.
            var bookInfo = new BookInfo(options.Path, true, new AlwaysEditSaveContext());
            var book     = new Book.Book(bookInfo, new BookStorage(options.Path, locator, new BookRenamedEvent(), collectionSettings),
                                         null, collectionSettings, null, null, new BookRefreshEvent(), new BookSavedEvent());
            // This was added as part of the phase 1 changes towards the new language system, where book languages
            // are more clearly distinct from collection languages, and there's no sense (except underlying storage) in which
            // a book has languages that are not selected for display. This made it necessary to decide explicitly
            // whether passing the national language options implies that a book is bi- or tri-lingual. Andrew and I (JohnT)
            // could not think of any reason to pass the arguments at all except to achieve that, so I made it so.
            var langs = new List <string>();

            langs.Add(options.VernacularIsoCode);
            if (!string.IsNullOrEmpty(options.NationalLanguage1IsoCode) && options.NationalLanguage1IsoCode != options.VernacularIsoCode)
            {
                langs.Add(options.NationalLanguage1IsoCode);
            }
            if (!string.IsNullOrEmpty(options.NationalLanguage2IsoCode))
            {
                langs.Add(options.NationalLanguage2IsoCode);
            }
            book.SetMultilingualContentLanguages(langs.ToArray());

            //we might change this later, or make it optional, but for now, this will prevent surprises to processes
            //running this CLI... the folder name won't change out from under it.
            book.LockDownTheFileAndFolderName = true;

            book.SetLayout(layout);
            book.BringBookUpToDate(new NullProgress());
            Console.WriteLine("Finished Hydrating.");
            Debug.WriteLine("Finished Hydrating.");
            return(0);
        }
        public static void ChangeLayoutForAllContentPagesInAllBooks(IProgress progress, string collectionPath, string bookPath, string pageGuid)
        {
            if (!File.Exists(bookPath))
            {
                MessageBox.Show("Could not find template book " + bookPath);
                return;
            }
            if (!File.Exists(collectionPath))
            {
                MessageBox.Show("Could not find collection file " + collectionPath);
                return;
            }
            var collectionFolder = Path.GetDirectoryName(collectionPath);

            if (File.Exists(TeamCollectionManager.GetTcLinkPathFromLcPath(collectionFolder)))
            {
                MessageBox.Show("Change Layout command cannot currently be used in Team Collections");
                return;
                // To make this possible, we'd need to spin up a TeamCollectionManager and TeamCollection and pass the latter
                // to the Book as its SaveContext and still changes would be forbidden unless every book was checked out.
            }

            var problems                    = new StringBuilder();
            var collection                  = new BookCollection(collectionFolder, BookCollection.CollectionType.TheOneEditableCollection, new BookSelection(), null);
            var collectionSettings          = new CollectionSettings(collectionPath);
            XMatterPackFinder xmatterFinder = new XMatterPackFinder(new[]
            {
                BloomFileLocator.GetFactoryXMatterDirectory()
            });
            var locator = new BloomFileLocator(collectionSettings, xmatterFinder, ProjectContext.GetFactoryFileLocations(),
                                               ProjectContext.GetFoundFileLocations(), ProjectContext.GetAfterXMatterFileLocations());

            // AlwaysSaveable is fine here, as we checked above that it's not a TC.
            var templateBookInfo = new BookInfo(Path.GetDirectoryName(bookPath), true, new AlwaysEditSaveContext());
            var templateBook     = new Book.Book(templateBookInfo, new BookStorage(templateBookInfo.FolderPath, locator, new BookRenamedEvent(), collectionSettings),
                                                 null, collectionSettings, null, null, new BookRefreshEvent(), new BookSavedEvent(), new NoEditSaveContext());

            var   pageDictionary = templateBook.GetTemplatePagesIdDictionary();
            IPage page           = null;

            if (!pageDictionary.TryGetValue(pageGuid, out page))
            {
                MessageBox.Show("Could not find template page " + pageGuid);
                return;
            }

            int i = 0;

            foreach (var bookInfo in collection.GetBookInfos())
            {
                i++;
                try
                {
                    var book = new Book.Book(bookInfo,
                                             new BookStorage(bookInfo.FolderPath, locator, new BookRenamedEvent(), collectionSettings),
                                             null, collectionSettings, null, null, new BookRefreshEvent(), new BookSavedEvent());
                    //progress.WriteMessage("Processing " + book.TitleBestForUserDisplay + " " + i + "/" + collection.GetBookInfos().Count());
                    progress.ProgressIndicator.PercentCompleted = i * 100 / collection.GetBookInfos().Count();

                    book.ChangeLayoutForAllContentPages(page);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    problems.AppendLine(Path.GetFileName(bookInfo.FolderPath));
                }
            }
            if (problems.Length == 0)
            {
                MessageBox.Show("All books converted successfully");
            }
            else
            {
                MessageBox.Show("Bloom had problems converting the following books; please check them:\n" + problems);
            }
        }
Beispiel #24
0
        public CollectionSettingsDialog(CollectionSettings collectionSettings, XMatterPackFinder xmatterPackFinder, QueueRenameOfCollection queueRenameOfCollection, PageRefreshEvent pageRefreshEvent, TeamCollectionManager tcManager)
        {
            _collectionSettings      = collectionSettings;
            _xmatterPackFinder       = xmatterPackFinder;
            _queueRenameOfCollection = queueRenameOfCollection;
            _pageRefreshEvent        = pageRefreshEvent;
            InitializeComponent();
            // moved from the Designer where it was deleted if the Designer was touched
            _xmatterList.Columns.AddRange(new[] { new ColumnHeader()
                                                  {
                                                      Width = 250
                                                  } });

            _language1Name.UseMnemonic              = false;    // Allow & to be part of the language display names.
            _language2Name.UseMnemonic              = false;    // This may be unlikely, but can't be ruled out.
            _language3Name.UseMnemonic              = false;    // See https://issues.bloomlibrary.org/youtrack/issue/BL-9919.
            _language1FontLabel.UseMnemonic         = false;
            _language2FontLabel.UseMnemonic         = false;
            _language3FontLabel.UseMnemonic         = false;
            CollectionSettingsApi.DialogBeingEdited = this;

            if (_collectionSettings.IsSourceCollection)
            {
                _language1Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language1InSourceCollection", "Language 1", "In a local language collection, we say 'Local Language', but in a source collection, Local Language has no relevance, so we use this different label");
                _language2Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language2InSourceCollection", "Language 2", "In a local language collection, we say 'Language 2 (e.g. National Language)', but in a source collection, National Language has no relevance, so we use this different label");
                _language3Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language3InSourceCollection", "Language 3", "In a local language collection, we say 'Language 3 (e.g. Regional Language)', but in a source collection, National Language has no relevance, so we use this different label");
            }

            _showExperimentalBookSources.Checked = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kExperimentalSourceBooks);
            _allowTeamCollection.Checked         = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections);
            if (!ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections) && tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                this._tab.Controls.Remove(this._teamCollectionTab);
            }
            // Don't allow the user to disable the Team Collection feature if we're currently in a Team Collection.
            _allowTeamCollection.Enabled = !(_allowTeamCollection.Checked && tcManager.CurrentCollectionEvenIfDisconnected != null);

            // AutoUpdate applies only to Windows: see https://silbloom.myjetbrains.com/youtrack/issue/BL-2317.
            if (SIL.PlatformUtilities.Platform.IsWindows)
            {
                _automaticallyUpdate.Checked = Settings.Default.AutoUpdate;
            }
            else
            {
                _automaticallyUpdate.Hide();
            }

            // Without this, PendingDefaultBookshelf stays null unless the user changes it.
            // The result is the bookshelf selection gets cleared when other collection settings are saved. See BL-10093.
            PendingDefaultBookshelf = _collectionSettings.DefaultBookshelf;

//		    _showSendReceive.CheckStateChanged += (sender, args) =>
//		                                              {
//		                                                  Settings.Default.ShowSendReceive = _showSendReceive.CheckState ==
//		                                                                                     CheckState.Checked;
//
//                                                          _restartRequired = true;
//		                                                  UpdateDisplay();
//		                                              };

            CollectionSettingsApi.BrandingChangeHandler = ChangeBranding;

            SetupEnterpriseBrowser();

            TeamCollectionApi.TheOneInstance.SetCallbackToReopenCollection(() =>
            {
                _restartRequired = true;
                ReactDialog.CloseCurrentModal();             // close the top Create dialog
                _okButton_Click(null, null);                 // close this dialog
            });

            UpdateDisplay();

            if (CollectionSettingsApi.FixEnterpriseSubscriptionCodeMode)
            {
                _tab.SelectedTab = _enterpriseTab;
            }

            if (tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                _noRenameTeamCollectionLabel.Visible = false;
            }
            else
            {
                _bloomCollectionName.Enabled = false;
            }

            // This code would mostly more naturally go in Designer. Unfortunately we can't run designer
            // until we get back in a state where all our dependencies are sufficiently consistent.

            _defaultBookshelfControl = ReactControl.Create("defaultBookshelfControlBundle");

            tabPage2.Controls.Add(_defaultBookshelfControl);
            _defaultBookshelfControl.Location = new Point(_xmatterDescription.Left, _xmatterDescription.Bottom + 30);
            // We'd like it to be as big as possible, not just big enough for the immediate content.
            // Until React takes over at least the whole tab, the pull-down part of the combo can't
            // stretch outside the Gecko control.
            _defaultBookshelfControl.Size = new Size(_xmatterList.Width, 200);
        }
        public ReactCollectionTabView(LibraryModel model, LibraryListView.Factory libraryListViewFactory,
                                      LibraryBookView.Factory templateBookViewFactory,
                                      SelectedTabChangedEvent selectedTabChangedEvent,
                                      SendReceiveCommand sendReceiveCommand,
                                      TeamCollectionManager tcManager)
        {
            _model = model;
            InitializeComponent();
            BackColor               = _reactControl.BackColor = Palette.GeneralBackground;
            _toolStrip.Renderer     = new NoBorderToolStripRenderer();
            _toolStripLeft.Renderer = new NoBorderToolStripRenderer();

            // When going down to Shrink Stage 3 (see WorkspaceView), we want the right-side toolstrip to take precedence
            // (Settings, Other Collection).
            // This essentially makes the TC Status button's zIndex less than the buttons on the right side.
            _toolStripLeft.SendToBack();

            //TODO splitContainer1.SplitterDistance = _collectionListView.PreferredWidth;
            _makeBloomPackButton.Visible = model.IsShellProject;
            _sendReceiveButton.Visible   = Settings.Default.ShowSendReceive;

            if (sendReceiveCommand != null)
            {
#if Chorus
                _sendReceiveButton.Click  += (x, y) => sendReceiveCommand.Raise(this);
                _sendReceiveButton.Enabled = !SendReceiver.SendReceiveDisabled;
#endif
            }
            else
            {
                _sendReceiveButton.Enabled = false;
            }

            if (SIL.PlatformUtilities.Platform.IsMono)
            {
                BackgroundColorsForLinux();
            }

            selectedTabChangedEvent.Subscribe(c =>
            {
                if (c.To == this)
                {
                    Logger.WriteEvent("Entered Collections Tab");
                }
            });
            SetTeamCollectionStatus(tcManager);
            TeamCollectionManager.TeamCollectionStatusChanged += (sender, args) =>
            {
                return;

                if (!IsDisposed)
                {
                    SafeInvoke.InvokeIfPossible("update TC status", this, false,
                                                () => SetTeamCollectionStatus(tcManager));
                }
            };
            _tcStatusButton.Click += (sender, args) =>
            {
                // Any messages for which reloading the collection is a useful action?
                var showReloadButton = tcManager.MessageLog.ShouldShowReloadButton;
                // Reinstate this to see messages from before we started up.
                // We think it might be too expensive to show a list as long as this might get.
                // Instead, in the short term we may add a button to show the file.
                // Later we may implement some efficient way to scroll through them.
                // tcManager.CurrentCollection?.MessageLog?.LoadSavedMessages();
                using (var dlg = new ReactDialog("teamCollectionDialog", new { showReloadButton }))
                {
                    dlg.ShowDialog(this);
                    tcManager.CurrentCollectionEvenIfDisconnected?.MessageLog.WriteMilestone(MessageAndMilestoneType.LogDisplayed);
                }
            };

            // We don't want this control initializing until team collections sync (if any) is done.
            // That could change, but for now we're not trying to handle async changes arriving from
            // the TC to the local collection, and as part of that, the collection tab doesn't expect
            // the local collection to change because of TC stuff once it starts loading.
            Controls.Remove(_reactControl);
        }
Beispiel #26
0
 /// <summary>
 /// Set a new TC status image. Called at Idle time or startup, on the UI thread.
 /// </summary>
 public void SetTeamCollectionStatus(TeamCollectionManager tcManager)
 {
     _tcStatusButton.Update(tcManager.CollectionStatus);
 }
 public void TearDown()
 {
     TeamCollectionManager.ForceCurrentUserForTests(null);
     _collectionFolder.Dispose();
     _sharedFolder.Dispose();
 }
        public void OneTimeSetup()
        {
            _repoFolder       = new TemporaryFolder("SyncAtStartup_Repo");
            _collectionFolder = new TemporaryFolder("SyncAtStartup_Local");
            FolderTeamCollection.CreateTeamCollectionLinkFile(_collectionFolder.FolderPath,
                                                              _repoFolder.FolderPath);
            _mockTcManager           = new Mock <ITeamCollectionManager>();
            _tcLog                   = new TeamCollectionMessageLog(TeamCollectionManager.GetTcLogPathFromLcPath(_collectionFolder.FolderPath));
            _collection              = new FolderTeamCollection(_mockTcManager.Object, _collectionFolder.FolderPath, _repoFolder.FolderPath, tcLog: _tcLog);
            _collection.CollectionId = Bloom.TeamCollection.TeamCollection.GenerateCollectionId();
            TeamCollectionManager.ForceCurrentUserForTests("*****@*****.**");

            // Simulate a book that was once shared, but has been deleted from the repo folder (has a tombstone).
            MakeBook("Should be deleted", "This should be deleted as it has local status but is not shared", true);
            var bookFolderPath = Path.Combine(_collectionFolder.FolderPath, "Should be deleted");

            _collection.DeleteBookFromRepo(bookFolderPath);

            // Simulate a book that was once shared, but has been deleted from the repo folder. But there is no tombstone.
            // (Despite the name, it is only converted to a new local in the default case. When we do a First Time Join,
            // it just gets copied into the repo.)
            MakeBook("Should be converted to new local", "This should become a new local (no status) book as it has local status but is not in the repo", true);
            var delPath = Path.Combine(_repoFolder.FolderPath, "Books", "Should be converted to new local.bloom");

            RobustFile.Delete(delPath);

            // Simulate a book newly created locally. Not in repo, but should not be deleted.
            MakeBook("A book", "This should survive as it has no local status", false);
            // By the way, like most new books, it got renamed early in life...twice
            SimulateRename(_collection, "A book", "An early name");
            SimulateRename(_collection, "An early name", "New book");

            // Simulate a book that needs nothing done to it. It's the same locally and on the repo.
            MakeBook("Keep me", "This needs nothing done to it");

            // Simulate a book that is checked out locally to the current user, but the file has
            // been deleted on the repo.
            MakeBook("Keep me too", "This also needs nothing done", false);
            _collection.WriteLocalStatus("Keep me too", new BookStatus().WithLockedBy("*****@*****.**"));

            // Simlulate a book that is only in the team repo
            MakeBook("Add me", "Fetch to local");
            var delPathAddMe = Path.Combine(_collectionFolder.FolderPath, "Add me");

            SIL.IO.RobustIO.DeleteDirectoryAndContents(delPathAddMe);

            // Simulate a book that was checked in, then checked out again and renamed,
            // but not yet checked in. Both "A renamed book" folder and content and "An old name.bloom"
            // should survive. (Except for an obscure reason when joining a TC...see comment in the test.)
            MakeBook("An old name", "Should be kept in both places with different names");
            _collection.AttemptLock("An old name", "*****@*****.**");
            SimulateRename(_collection, "An old name", "an intermediate name");
            SimulateRename(_collection, "an intermediate name", "A renamed book");

            // Simulate a book that is not checked out locally and has been modified elsewhere
            MakeBook("Update me", "Needs to be become this locally");
            UpdateLocalBook("Update me", "This is supposed to be an older value, not edited locally");

            // Simulate a book that is checked out locally but not in the repo, and where the saved local
            // checksum equals the repo checksum, and it is not checked out in the repo. This would
            // typically indicate that someone remote forced a checkout, perhaps while this user was
            // offline, but checked in again without making changes.
            // Also pretend it has been modified locally.
            // Test result: collection is updated to indicate the local checkout. Local changes are not lost.
            MakeBook("Check me out", "Local and remote checksums correspond to this");
            UpdateLocalBook("Check me out", "This is supposed to be a newer value from local editing", false);
            var oldLocalStatus = _collection.GetLocalStatus("Check me out");
            var newLocalStatus = oldLocalStatus.WithLockedBy(Bloom.TeamCollection.TeamCollectionManager.CurrentUser);

            _checkMeOutOriginalChecksum = oldLocalStatus.checksum;
            _collection.WriteLocalStatus("Check me out", newLocalStatus);

            // Simulate a book that appears newly-created locally (no local status) but is also in the
            // repo. This would indicate two people coincidentally creating a book with the same name.
            // Test result: the local book should get renamed (both folder and htm).
            // When merging while joining a new TC, this case is treated as a conflict and the
            // local book is moved to Lost and Found.
            MakeBook("Rename local", "This content is on the server");
            _collection.AttemptLock("Rename local", "*****@*****.**");
            UpdateLocalBook("Rename local", "This is a new book created independently");
            var statusFilePath = Bloom.TeamCollection.TeamCollection.GetStatusFilePath("Rename local", _collectionFolder.FolderPath);

            RobustFile.Delete(statusFilePath);

            // Simulate a book that is checked out locally but also checked out, to a different user
            // or machine, on the repo. This would indicate some sort of manual intervention, perhaps
            // while this user was long offline. The book has not been modified locally, but the local
            // status is out of date.
            // Test result: local status is updated to reflect the remote checkout, book content updated to repo.
            MakeBook("Update and undo checkout", "This content is everywhere");
            _collection.AttemptLock("Update and undo checkout", "*****@*****.**");
            _collection.WriteLocalStatus("Update and undo checkout", _collection.GetStatus("Update and undo checkout").WithLockedBy(Bloom.TeamCollection.TeamCollectionManager.CurrentUser));

            // Simulate a book that is checked out locally and not on the server, but the repo and (old)
            // local checksums are different. The book has not been edited locally.
            // Test result: book is updated to match repo. Local and remote status should match...review: which wins?
            MakeBook("Update and checkout", "This content is on the server");
            UpdateLocalBook("Update and checkout", "This simulates older content changed remotely but not locally");
            _collection.WriteLocalStatus("Update and checkout", _collection.GetLocalStatus("Update and checkout").WithLockedBy(Bloom.TeamCollection.TeamCollectionManager.CurrentUser));

            // Simulate a book that is checked out and modified locally, but has also been modified
            // remotely.
            // Test result: current local state is saved in lost-and-found. Repo version of book and state
            // copied to local. Warning to user.
            MakeBook("Update content and status and warn", "This simulates new content on server");
            _collection.AttemptLock("Update content and status and warn", "*****@*****.**");
            UpdateLocalBook("Update content and status and warn", "This is supposed to be the newest value from local editing");
            var newStatus = _collection.GetStatus("Update content and status and warn").WithLockedBy(Bloom.TeamCollection.TeamCollectionManager.CurrentUser)
                            .WithChecksum("different from either");

            _collection.WriteLocalStatus("Update content and status and warn", newStatus);

            // Simulate a book that is checked out and modified locally, but is also checked out by another
            // user or machine in the repo. It has not (yet) been modified remotely.
            // Test result: current local state is saved in lost-and-found. Repo version of book and state
            // copied to local. Warning to user.
            MakeBook("Update content and status and warn2", "This simulates new content on server");
            _collection.AttemptLock("Update content and status and warn2", "*****@*****.**");
            UpdateLocalBook("Update content and status and warn2", "This is supposed to be the newest value from local editing", false);
            newStatus = _collection.GetStatus("Update content and status and warn2").WithLockedBy(Bloom.TeamCollection.TeamCollectionManager.CurrentUser);
            _collection.WriteLocalStatus("Update content and status and warn2", newStatus);

            // Simulate a book which has no local status, but for which the computed checksum matches
            // the repo one. This could happen if a user obtained the same book independently,
            // or during initial merging of a local and team collection, where much of the material
            // was previously duplicated.
            // Test result: status is copied to local
            MakeBook("copy status", "Same content in both places");
            _collection.AttemptLock("copy status", "*****@*****.**");
            statusFilePath = Bloom.TeamCollection.TeamCollection.GetStatusFilePath("copy status", _collectionFolder.FolderPath);
            RobustFile.Delete(statusFilePath);

            // Simulate a book that was copied from another TC, using File Explorer.
            // It therefore has a book.status file, but with a different guid.
            // Test result: it should survive, and on a new collection sync get copied into the repo
            var copiedEx = "copied with Explorer";

            MakeBook(copiedEx, "This content is only local", false);
            _collection.WriteLocalStatus(copiedEx, new BookStatus(), collectionId: Bloom.TeamCollection.TeamCollection.GenerateCollectionId());

            // Simulate a book that appeared in DropBox when their software found a conflict.
            // It should NOT be copied locally, but instead moved to Lost and Found, with a report.
            MakeBook(kConflictName, "This content is only on the repo, apart from conflicting copies");
            var conflictFolderPath = Path.Combine(_collectionFolder.FolderPath, kConflictName);

            SIL.IO.RobustIO.DeleteDirectoryAndContents(conflictFolderPath);

            _collection.WriteLocalStatus(copiedEx, new BookStatus(), collectionId: Bloom.TeamCollection.TeamCollection.GenerateCollectionId());

            // Simulate a corrupt zip file, only in the repo
            File.WriteAllText(Path.Combine(_repoFolder.FolderPath, "Books", "new corrupt book.bloom"), "This is not a valid zip!");

            // Simulate a corrupt zip file that corresponds to a local book.
            var badZip = "has a bad zip in repo";

            MakeBook(badZip, "This book seems to be in both places, but the repo is corrupt");
            File.WriteAllText(Path.Combine(_repoFolder.FolderPath, "Books", badZip + ".bloom"), "This is also not a valid zip!");

            // Simulate a book that was renamed remotely. That is, there's a local book Old Name, with local status,
            // and there's no repo book by that name, but there's a repo book New Name (and no such local book).
            // The book's meta.json indicates they are the same book.
            // We'll initially make both, with the new name and new content.
            MakeBook(kNewNameForRemoteRename, "This is the new book content after remote editing and rename");
            var oldFolder = Path.Combine(_collectionFolder.FolderPath, kBookRenamedRemotely);
            var newFolder = Path.Combine(_collectionFolder.FolderPath, kNewNameForRemoteRename);

            RobustIO.MoveDirectory(newFolder, oldFolder);              // made at new path, simulate still at old.
            var oldPath = Path.Combine(_collectionFolder.FolderPath, kBookRenamedRemotely,
                                       kBookRenamedRemotely + ".htm"); // simulate old book name and content

            RobustFile.WriteAllText(oldPath, "This is the simulated original book content");
            RobustFile.Delete(Path.Combine(_collectionFolder.FolderPath, kBookRenamedRemotely,
                                           kNewNameForRemoteRename + ".htm")); // get rid of the 'new' content

            // Simulate a book that is in the repo, where there is a local book that has no status, a different name,
            // and the same ID. This might indicate (a) that it was renamed by someone else after this user's pre-TC
            // copy of the collection diverged; (b) that it was renamed by this user after the divergence;
            // (c) that they were independently copied from some common-ID source.
            // We will treat this as a conflict, moving the local version to lost and found, even on a first time join.
            MakeBook(kRepoNameForIdConflict, "This is the repo version of a book that has a no-status local book with the same ID.");
            // Move the local version to a new folder
            var oldFolder2 = Path.Combine(_collectionFolder.FolderPath, kRepoNameForIdConflict);
            var newFolder2 = Path.Combine(_collectionFolder.FolderPath, kLocalNameForIdConflict);

            RobustIO.MoveDirectory(oldFolder2, newFolder2);
            var localStatusPath =
                Bloom.TeamCollection.TeamCollection.GetStatusFilePath(kLocalNameForIdConflict,
                                                                      _collectionFolder.FolderPath);

            RobustFile.Delete(localStatusPath);

            // Make a couple of folders that are legitimately present, but not books.
            var allowedWords = Path.Combine(_collectionFolder.FolderPath, "Allowed Words");

            Directory.CreateDirectory(allowedWords);
            File.WriteAllText(Path.Combine(allowedWords, "some sample.txt"), "This a fake word list");
            var sampleTexts = Path.Combine(_collectionFolder.FolderPath, "Sample Texts");

            Directory.CreateDirectory(sampleTexts);
            File.WriteAllText(Path.Combine(sampleTexts, "a sample.txt"), "This a fake sample text");

            _progressSpy = new ProgressSpy();

            // sut for the whole suite!
            Assert.That(_collection.SyncAtStartup(_progressSpy, FirstTimeJoin()), Is.True);
        }
Beispiel #29
0
        public CollectionSettingsDialog(CollectionSettings collectionSettings,
                                        QueueRenameOfCollection queueRenameOfCollection, PageRefreshEvent pageRefreshEvent,
                                        TeamCollectionManager tcManager, XMatterPackFinder xmatterPackFinder)
        {
            _collectionSettings      = collectionSettings;
            _queueRenameOfCollection = queueRenameOfCollection;
            _pageRefreshEvent        = pageRefreshEvent;
            _xmatterPackFinder       = xmatterPackFinder;
            InitializeComponent();

            _language1Name.UseMnemonic = false;             // Allow & to be part of the language display names.
            _language2Name.UseMnemonic = false;             // This may be unlikely, but can't be ruled out.
            _language3Name.UseMnemonic = false;             // See https://issues.bloomlibrary.org/youtrack/issue/BL-9919.

            PendingFontSelections[0] = _collectionSettings.LanguagesZeroBased[0].FontName;
            PendingFontSelections[1] = _collectionSettings.LanguagesZeroBased[1].FontName;
            var have3rdLanguage = _collectionSettings.LanguagesZeroBased[2] != null;

            PendingFontSelections[2] = have3rdLanguage ?
                                       _collectionSettings.LanguagesZeroBased[2].FontName :
                                       "";
            PendingNumberingStyle = _collectionSettings.PageNumberStyle;
            PendingXmatter        = _collectionSettings.XMatterPackName;
            CollectionSettingsApi.DialogBeingEdited = this;

            if (_collectionSettings.IsSourceCollection)
            {
                _language1Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language1InSourceCollection", "Language 1", "In a local language collection, we say 'Local Language', but in a source collection, Local Language has no relevance, so we use this different label");
                _language2Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language2InSourceCollection", "Language 2", "In a local language collection, we say 'Language 2 (e.g. National Language)', but in a source collection, National Language has no relevance, so we use this different label");
                _language3Label.Text = LocalizationManager.GetString("CollectionSettingsDialog.LanguageTab.Language3InSourceCollection", "Language 3", "In a local language collection, we say 'Language 3 (e.g. Regional Language)', but in a source collection, National Language has no relevance, so we use this different label");
            }

            _showExperimentalBookSources.Checked  = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kExperimentalSourceBooks);
            _allowTeamCollection.Checked          = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections);
            _allowSpreadsheetImportExport.Checked = ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kSpreadsheetImportExport);

            if (!ExperimentalFeatures.IsFeatureEnabled(ExperimentalFeatures.kTeamCollections) && tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                this._tab.Controls.Remove(this._teamCollectionTab);
            }
            // Don't allow the user to disable the Team Collection feature if we're currently in a Team Collection.
            _allowTeamCollection.Enabled = !(_allowTeamCollection.Checked && tcManager.CurrentCollectionEvenIfDisconnected != null);

            // AutoUpdate applies only to Windows: see https://silbloom.myjetbrains.com/youtrack/issue/BL-2317.
            if (SIL.PlatformUtilities.Platform.IsWindows)
            {
                _automaticallyUpdate.Checked = Settings.Default.AutoUpdate;
            }
            else
            {
                _automaticallyUpdate.Hide();
            }

            // Without this, PendingDefaultBookshelf stays null unless the user changes it.
            // The result is the bookshelf selection gets cleared when other collection settings are saved. See BL-10093.
            PendingDefaultBookshelf = _collectionSettings.DefaultBookshelf;

            CollectionSettingsApi.BrandingChangeHandler = ChangeBranding;

            TeamCollectionApi.TheOneInstance.SetCallbackToReopenCollection(() =>
            {
                _restartRequired = true;
                ReactDialog.CloseCurrentModal();             // close the top Create dialog
                _okButton_Click(null, null);                 // close this dialog
            });

            UpdateDisplay();

            if (CollectionSettingsApi.FixEnterpriseSubscriptionCodeMode)
            {
                _tab.SelectedTab = _enterpriseTab;
            }

            if (tcManager.CurrentCollectionEvenIfDisconnected == null)
            {
                _noRenameTeamCollectionLabel.Visible = false;
            }
            else
            {
                _bloomCollectionName.Enabled = false;
            }
        }
Beispiel #30
0
        public LibraryView(LibraryModel model, LibraryListView.Factory libraryListViewFactory,
                           LibraryBookView.Factory templateBookViewFactory,
                           SelectedTabChangedEvent selectedTabChangedEvent,
                           SendReceiveCommand sendReceiveCommand,
                           TeamCollectionManager tcManager)
        {
            _model = model;
            InitializeComponent();
            splitContainer1.BackColor = Palette.BookListSplitterColor;             // controls the left vs. right splitter
            _toolStrip.Renderer       = new NoBorderToolStripRenderer();
            _toolStripLeft.Renderer   = new NoBorderToolStripRenderer();

            _collectionListView      = libraryListViewFactory();
            _collectionListView.Dock = DockStyle.Fill;
            splitContainer1.Panel1.Controls.Add(_collectionListView);

            _bookView = templateBookViewFactory();
            _bookView.TeamCollectionMgr = tcManager;
            _bookView.Dock = DockStyle.Fill;
            splitContainer1.Panel2.Controls.Add(_bookView);

            // When going down to Shrink Stage 3 (see WorkspaceView), we want the right-side toolstrip to take precedence
            // (Settings, Other Collection).
            // This essentially makes the TC Status button's zIndex less than the buttons on the right side.
            _toolStripLeft.SendToBack();

            splitContainer1.SplitterDistance = _collectionListView.PreferredWidth;
            _makeBloomPackButton.Visible     = model.IsShellProject;
            _sendReceiveButton.Visible       = Settings.Default.ShowSendReceive;

            if (sendReceiveCommand != null)
            {
#if Chorus
                _sendReceiveButton.Click  += (x, y) => sendReceiveCommand.Raise(this);
                _sendReceiveButton.Enabled = !SendReceiver.SendReceiveDisabled;
#endif
            }
            else
            {
                _sendReceiveButton.Enabled = false;
            }

            if (SIL.PlatformUtilities.Platform.IsMono)
            {
                BackgroundColorsForLinux();
            }

            selectedTabChangedEvent.Subscribe(c =>
            {
                if (c.To == this)
                {
                    Logger.WriteEvent("Entered Collections Tab");
                }
            });
            SetTeamCollectionStatus(tcManager);
            TeamCollectionManager.TeamCollectionStatusChanged += (sender, args) =>
            {
                if (IsHandleCreated && !IsDisposed)
                {
                    SafeInvoke.InvokeIfPossible("update TC status", this, false,
                                                () => SetTeamCollectionStatus(tcManager));
                }
            };
            _tcStatusButton.Click += (sender, args) =>
            {
                // Any messages for which reloading the collection is a useful action?
                var showReloadButton = tcManager.MessageLog.ShouldShowReloadButton;
                // Reinstate this to see messages from before we started up.
                // We think it might be too expensive to show a list as long as this might get.
                // Instead, in the short term we may add a button to show the file.
                // Later we may implement some efficient way to scroll through them.
                // tcManager.CurrentCollection?.MessageLog?.LoadSavedMessages();
                using (var dlg = new ReactDialog("teamCollectionDialogBundle", new
                {
                    showReloadButton
                }, "Team Collection"))
                {
                    dlg.ShowDialog(this);
                    tcManager.CurrentCollectionEvenIfDisconnected?.MessageLog.WriteMilestone(MessageAndMilestoneType
                                                                                             .LogDisplayed);
                }
            };
        }