<commit_before>angular.module('app')
  .directive("editorSection", function($timeout, $sce){
    return {
      restrict: 'E',
      scope: {
        remove: "&",
        note: "=",
        updateTags: "&"
      },
      templateUrl: 'editor.html',
      replace: true,
      controller: 'EditorCtrl',
      controllerAs: 'ctrl',
      bindToController: true,

      link:function(scope, elem, attrs, ctrl) {
        scope.$watch('ctrl.note', (note, oldNote) => {
          if(note) {
            ctrl.noteDidChange(note, oldNote);
          }
        });
      }
    }
  })
  .controller('EditorCtrl', function ($sce, $timeout, authManager, $rootScope, actionsManager,
    syncManager, modelManager, themeManager, componentManager, storageManager, sessionHistory,
    privilegesManager, keyboardManager) {

    this.spellcheck = true;
    this.componentManager = componentManager;
    this.componentStack = [];
    this.isDesktop = isDesktopApplication();

    const MinimumStatusDurationMs = 400;

    syncManager.addEventHandler((eventName, data) => {
      if(!this.note) {
        return;
      }

      if(eventName == "sync:taking-too-long") {
        this.syncTakingTooLong = true;
      }

      else if(eventName == "sync:completed") {
        this.syncTakingTooLong = false;
        if(this.note.dirty) {
          // if we're still dirty, don't change status, a sync is likely upcoming.
        } else {
          let savedItem = data.savedItems.find((item) => item.uuid == this.note.uuid);
          let isInErrorState = this.saveError;
          if(isInErrorState || savedItem) {
            this.showAllChangesSavedStatus();
          }
        }
      } else if(eventName == "sync:error") {
        // only show error status in editor if the note is dirty. Otherwise, it means the originating sync
        // came from somewhere else and we don't want to display an error here.
        if(this.note.dirty){
          this.showErrorStatus();
        }
      }
    });

    // Right now this only handles offline saving status changes.
    this.syncStatusObserver = syncManager.registerSyncStatusObserver((status) => {
      if(status.localError) {
        $timeout(() => {
          this.showErrorStatus({
            message: "Offline Saving Issue",
            desc: "Changes not saved"
          });
        }, 500)
      } else {
      }
    })

    modelManager.addItemSyncObserver("editor-note-observer", "Note", (allItems, validItems, deletedItems, source) => {
      if(!this.note) { return; }

      // Before checking if isMappingSourceRetrieved, we check if this item was deleted via a local source,
      // such as alternating uuids during sign in. Otherwise, we only want to make interface updates if it's a
      // remote retrieved source.
      if(this.note.deleted || this.note.content.trashed) {
        $rootScope.notifyDelete();
        return;
      }

      if(!SFModelManager.isMappingSourceRetrieved(source)) {
        return;
      }

      var matchingNote = allItems.find((item) => {
        return item.uuid == this.note.uuid;
      });

      if(!matchingNote) {
        return;
      }

      // Update tags
      this.loadTagsString();
    });

    modelManager.addItemSyncObserver("editor-tag-observer", "Tag", (allItems, validItems, deletedItems, source) => {
      if(!this.note) { return; }

      for(var tag of allItems) {
        // If a tag is deleted then we'll have lost references to notes. Reload anyway.
        if(this.note.savedTagsString == null || tag.deleted || tag.hasRelationshipWithItem(this.note)) {
          this.loadTagsString();
          return;
        }
      }
    });


    modelManager.addItemSyncObserver("editor-component-observer", "SN|Component", (allItems, validItems, deletedItems, source) => {
      if(!this.note) { return; }

      // Reload componentStack in case new ones were added or removed
      this.reloadComponentStackArray();

      // Observe editor changes to see if the current note should update its editor
      var editors = allItems.filter(function(item) {
        return item.isEditor();
      });

      // If no editors have changed
      if(editors.length == 0) {
        return;
      }

      // Look through editors again and find the most proper one
      var editor = this.editorForNote(this.note);
      this.selectedEditor = editor;
    });

    this.noteDidChange = function(note, oldNote) {
      this.setNote(note, oldNote);
      this.reloadComponentContext();
    }

    this.setNote = function(note, oldNote) {
      this.showExtensions = false;
      this.showMenu = false;
      this.noteStatus = null;
      // When setting alt key down and deleting note, an alert will come up and block the key up event when alt is released.
      // We reset it on set note so that the alt menu restores to default.
      this.altKeyDown = false;
      this.loadTagsString();

      let onReady = () => {
        this.noteReady = true;
        $timeout(() => {
          this.loadPreferences();
        })
      }<commit_msg>Reload font after remote editor change, fixes desktop#319<commit_after>angular.module('app')
  .directive("editorSection", function($timeout, $sce){
    return {
      restrict: 'E',
      scope: {
        remove: "&",
        note: "=",
        updateTags: "&"
      },
      templateUrl: 'editor.html',
      replace: true,
      controller: 'EditorCtrl',
      controllerAs: 'ctrl',
      bindToController: true,

      link:function(scope, elem, attrs, ctrl) {
        scope.$watch('ctrl.note', (note, oldNote) => {
          if(note) {
            ctrl.noteDidChange(note, oldNote);
          }
        });
      }
    }
  })
  .controller('EditorCtrl', function ($sce, $timeout, authManager, $rootScope, actionsManager,
    syncManager, modelManager, themeManager, componentManager, storageManager, sessionHistory,
    privilegesManager, keyboardManager) {

    this.spellcheck = true;
    this.componentManager = componentManager;
    this.componentStack = [];
    this.isDesktop = isDesktopApplication();

    const MinimumStatusDurationMs = 400;

    syncManager.addEventHandler((eventName, data) => {
      if(!this.note) {
        return;
      }

      if(eventName == "sync:taking-too-long") {
        this.syncTakingTooLong = true;
      }

      else if(eventName == "sync:completed") {
        this.syncTakingTooLong = false;
        if(this.note.dirty) {
          // if we're still dirty, don't change status, a sync is likely upcoming.
        } else {
          let savedItem = data.savedItems.find((item) => item.uuid == this.note.uuid);
          let isInErrorState = this.saveError;
          if(isInErrorState || savedItem) {
            this.showAllChangesSavedStatus();
          }
        }
      } else if(eventName == "sync:error") {
        // only show error status in editor if the note is dirty. Otherwise, it means the originating sync
        // came from somewhere else and we don't want to display an error here.
        if(this.note.dirty){
          this.showErrorStatus();
        }
      }
    });

    // Right now this only handles offline saving status changes.
    this.syncStatusObserver = syncManager.registerSyncStatusObserver((status) => {
      if(status.localError) {
        $timeout(() => {
          this.showErrorStatus({
            message: "Offline Saving Issue",
            desc: "Changes not saved"
          });
        }, 500)
      } else {
      }
    })

    modelManager.addItemSyncObserver("editor-note-observer", "Note", (allItems, validItems, deletedItems, source) => {
      if(!this.note) { return; }

      // Before checking if isMappingSourceRetrieved, we check if this item was deleted via a local source,
      // such as alternating uuids during sign in. Otherwise, we only want to make interface updates if it's a
      // remote retrieved source.
      if(this.note.deleted || this.note.content.trashed) {
        $rootScope.notifyDelete();
        return;
      }

      if(!SFModelManager.isMappingSourceRetrieved(source)) {
        return;
      }

      var matchingNote = allItems.find((item) => {
        return item.uuid == this.note.uuid;
      });

      if(!matchingNote) {
        return;
      }

      // Update tags
      this.loadTagsString();
    });

    modelManager.addItemSyncObserver("editor-tag-observer", "Tag", (allItems, validItems, deletedItems, source) => {
      if(!this.note) { return; }

      for(var tag of allItems) {
        // If a tag is deleted then we'll have lost references to notes. Reload anyway.
        if(this.note.savedTagsString == null || tag.deleted || tag.hasRelationshipWithItem(this.note)) {
          this.loadTagsString();
          return;
        }
      }
    });


    modelManager.addItemSyncObserver("editor-component-observer", "SN|Component", (allItems, validItems, deletedItems, source) => {
      if(!this.note) { return; }

      // Reload componentStack in case new ones were added or removed
      this.reloadComponentStackArray();

      // Observe editor changes to see if the current note should update its editor
      var editors = allItems.filter(function(item) {
        return item.isEditor();
      });

      // If no editors have changed
      if(editors.length == 0) {
        return;
      }

      // Look through editors again and find the most proper one
      var editor = this.editorForNote(this.note);
      this.selectedEditor = editor;
      if(!editor) {
        this.reloadFont();
      }
    });

    this.noteDidChange = function(note, oldNote) {
      this.setNote(note, oldNote);
      this.reloadComponentContext();
    }

    this.setNote = function(note, oldNote) {
      this.showExtensions = false;
      this.showMenu = false;
      this.noteStatus = null;
      // When setting alt key down and deleting note, an alert will come up and block the key up event when alt is released.
      // We reset it on set note so that the alt menu restores to default.
      this.altKeyDown = false;
      this.loadTagsString();

      let onReady = () => {
        this.noteReady = true;
        $timeout(() => {
          this.loadPreferences();
        })
      }
{'fraction_non_alphanumeric': 0.11650771802182676, 'fraction_numerical': 0.0016714187395536328, 'mean_word_length': 2.3015254787406687, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1078149', 'n_tokens_mistral': 2892, 'n_tokens_neox': 2785, 'n_words': 743}