<commit_before>########################################################
# AngularJS service to read entries in a feed or folder
########################################################

angular.module('feedbunch').service 'loadEntriesSvc',
['$rootScope', '$timeout', 'csrfTokenSvc', 'timerFlagSvc', 'openFolderSvc',
'entriesPaginationSvc', 'openEntrySvc', 'feedsFoldersSvc', 'favicoSvc', 'lazyLoadingSvc', 'startPageSvc',
'findSvc', 'changeUnreadCountSvc', 'highlightedEntrySvc',
($rootScope, $timeout, csrfTokenSvc, timerFlagSvc, openFolderSvc,
entriesPaginationSvc, openEntrySvc, feedsFoldersSvc, favicoSvc, lazyLoadingSvc, startPageSvc,
findSvc, changeUnreadCountSvc, highlightedEntrySvc)->

  # Maximum number of entries in each page.
  # This MUST match the entries page size set in the server!
  entries_page_size = 25

  # Constants for the different operations the web worker can perform
  LOAD_FEED_ENTRIES = 'load_feed_entries'
  LOAD_FOLDER_ENTRIES = 'load_folder_entries'

  # CSRF token
  token = csrfTokenSvc.get_token()

  # Web worker to load entries
  worker = new Worker '<%= asset_path 'workers/load_entries_worker' %>'
  worker.onmessage = (e) ->
    if e.data.status == 200 || e.data.status == 304
      if e.data.operation == LOAD_FEED_ENTRIES
        feed_entries_loaded e.data.params, e.data.response
      else if e.data.operation == LOAD_FOLDER_ENTRIES
        folder_entries_loaded e.data.params, e.data.response
    else if e.data.status == 401 || e.data.status == 422
      $window.location.href = '/login'
    else if e.data.status == 404
      entriesPaginationSvc.set_busy false
      entriesPaginationSvc.set_more_entries_available false
      if e.data.operation == LOAD_FEED_ENTRIES
        feed = findSvc.find_feed e.data.params.feed_id
        correct_feed_unread_counts feed
        if entriesPaginationSvc.is_first_page()
          entriesPaginationSvc.set_error_no_entries true
          feed.unread_entries = 0
      else if e.data.operation == LOAD_FOLDER_ENTRIES
        folder = findSvc.find_folder e.data.params.folder_id
        correct_folder_unread_counts folder
        if entriesPaginationSvc.is_first_page()
          entriesPaginationSvc.set_error_no_entries true
    else
      entriesPaginationSvc.set_busy false
      startPageSvc.show_start_page()
      timerFlagSvc.start 'error_loading_entries'

  #--------------------------------------------
  # PRIVATE FUNCTION: Operations after entries of a feed have been loaded
  #--------------------------------------------
  feed_entries_loaded = (params, response)->
    entriesPaginationSvc.set_busy false

    # If entries list is empty, populate it with received entries and highlight first entry.
    # Otherwise concatenate the received page of entries to the list of entries.
    if !$rootScope.entries || $rootScope.entries?.length == 0
      $rootScope.entries = response.slice()
      highlightedEntrySvc.reset()
    else
      $rootScope.entries = $rootScope.entries.concat response.slice()

    # Set correct state (open or closed) for new entries, based on user configuration
    openEntrySvc.add_entries response.slice()

    # If the user has selected the "open all entries by default" option, lazy load images
    if $rootScope.open_all_entries
      $timeout ->
        lazyLoadingSvc.load_viewport_images()
      , 250

    feed = findSvc.find_feed params.feed_id
    # If less than a full page of entries is received, this is the last page of entries available.
    if response.length < entries_page_size
      entriesPaginationSvc.set_more_entries_available false
      correct_feed_unread_counts feed
    else if entriesPaginationSvc.is_first_page()
      # After loading the first page of entries, load a second one to ensure the list is fully populated
      load_feed_entries feed

  #--------------------------------------------
  # PRIVATE FUNCTION: Operations after entries of a folder have been loaded
  #--------------------------------------------
  folder_entries_loaded = (params, response)->
    entriesPaginationSvc.set_busy false

    # If entries list is empty, populate it with received entries and highlight first entry.
    # Otherwise concatenate the received page of entries to the list of entries.
    if !$rootScope.entries || $rootScope.entries?.length == 0
      $rootScope.entries = response.slice()
      highlightedEntrySvc.reset()
    else
      $rootScope.entries = $rootScope.entries.concat response.slice()

    # Set correct state (open or closed) for new entries, based on user configuration
    openEntrySvc.add_entries response.slice()

    # If the user has selected the "open all entries by default" option, lazy load images
    if $rootScope.open_all_entries
      $timeout ->
        lazyLoadingSvc.load_viewport_images()
      , 250

    folder = findSvc.find_folder params.folder_id
    # If less than a full page of entries is received, this is the last page of entries available.
    if data.length < entries_page_size
      entriesPaginationSvc.set_more_entries_available false
      correct_folder_unread_counts folder
    else if entriesPaginationSvc.is_first_page()
      # After loading the first page of entries, load a second one to ensure the list is fully populated
      load_folder_entries folder

  #--------------------------------------------
  # PRIVATE FUNCTION: Validations and setup that runs every time entries are loaded.
  # Returns true if the load process can continue, false if it must be cancelled.
  #--------------------------------------------
  load_entries_setup = ->
    # If busy, do nothing
    return false if entriesPaginationSvc.is_busy()
    # If a 404 has been received in a previous page (no more entries available), do nothing
    return false if !entriesPaginationSvc.more_entries_available()

    # Reset the timer that updates feeds every minute
    feedsFoldersSvc.reset_refresh_timer()
    # Increment the results page
    entriesPaginationSvc.increment_entries_page()
    # Indicate that AJAX request/response cycle is busy so no more calls are done until finished
    entriesPaginationSvc.set_busy true

    return true

  #--------------------------------------------
  # PRIVATE FUNCTION: Load entries in the feed passed as argument.
  #--------------------------------------------
  load_feed_entries = (feed)->
    return if load_entries_setup() == false

    url = "/api/feeds/#{feed.id}/entries.json"
    worker.postMessage {operation: LOAD_FEED_ENTRIES, token: token, feed_id: feed.id, include_read: $rootScope.show_read, page: entriesPaginationSvc.get_entries_page()}

  #--------------------------------------------
  # PRIVATE FUNCTION: After all entries in a feed have been received, set the unread count for the feed
  # to the number of unread entries actually present.
  #--------------------------------------------
  correct_feed_unread_counts = (feed)->
    entries = findSvc.find_feed_unread_entries feed
    if entries
      changeUnreadCountSvc.set_feed_count feed, entries.length
    else
      changeUnreadCountSvc.set_feed_count feed, 0

  #--------------------------------------------
  # PRIVATE FUNCTION: Load entries in the folder passed as argument.
  #--------------------------------------------
  load_folder_entries = (folder)->
    return if load_entries_setup() == false

    url = "/api/folders/#{folder.id}/entries.json"
    worker.postMessage {operation: LOAD_FOLDER_ENTRIES, token: token, feed_id: feed.id, include_read: $rootScope.show_read, page: entriesPaginationSvc.get_entries_page()}

  #--------------------------------------------
  # PRIVATE FUNCTION: After retrieving entries in a folder, set to zero the unread count of
  # feeds for which no entries have been received.
  #--------------------------------------------
  correct_folder_unread_counts = (folder)->
    feeds = findSvc.find_folder_feeds folder
    if feeds && feeds?.length > 0
      for f in feeds
        correct_feed_unread_counts f
<commit_msg>Fixed small bugs in javascript loading folder entries.<commit_after>########################################################
# AngularJS service to read entries in a feed or folder
########################################################

angular.module('feedbunch').service 'loadEntriesSvc',
['$rootScope', '$timeout', 'csrfTokenSvc', 'timerFlagSvc', 'openFolderSvc',
'entriesPaginationSvc', 'openEntrySvc', 'feedsFoldersSvc', 'favicoSvc', 'lazyLoadingSvc', 'startPageSvc',
'findSvc', 'changeUnreadCountSvc', 'highlightedEntrySvc',
($rootScope, $timeout, csrfTokenSvc, timerFlagSvc, openFolderSvc,
entriesPaginationSvc, openEntrySvc, feedsFoldersSvc, favicoSvc, lazyLoadingSvc, startPageSvc,
findSvc, changeUnreadCountSvc, highlightedEntrySvc)->

  # Maximum number of entries in each page.
  # This MUST match the entries page size set in the server!
  entries_page_size = 25

  # Constants for the different operations the web worker can perform
  LOAD_FEED_ENTRIES = 'load_feed_entries'
  LOAD_FOLDER_ENTRIES = 'load_folder_entries'

  # CSRF token
  token = csrfTokenSvc.get_token()

  # Web worker to load entries
  worker = new Worker '<%= asset_path 'workers/load_entries_worker' %>'
  worker.onmessage = (e) ->
    if e.data.status == 200 || e.data.status == 304
      if e.data.operation == LOAD_FEED_ENTRIES
        feed_entries_loaded e.data.params, e.data.response
      else if e.data.operation == LOAD_FOLDER_ENTRIES
        folder_entries_loaded e.data.params, e.data.response
    else if e.data.status == 401 || e.data.status == 422
      $window.location.href = '/login'
    else if e.data.status == 404
      entriesPaginationSvc.set_busy false
      entriesPaginationSvc.set_more_entries_available false
      if e.data.operation == LOAD_FEED_ENTRIES
        feed = findSvc.find_feed e.data.params.feed_id
        correct_feed_unread_counts feed
        if entriesPaginationSvc.is_first_page()
          entriesPaginationSvc.set_error_no_entries true
          feed.unread_entries = 0
      else if e.data.operation == LOAD_FOLDER_ENTRIES
        folder = findSvc.find_folder e.data.params.folder_id
        correct_folder_unread_counts folder
        if entriesPaginationSvc.is_first_page()
          entriesPaginationSvc.set_error_no_entries true
    else
      entriesPaginationSvc.set_busy false
      startPageSvc.show_start_page()
      timerFlagSvc.start 'error_loading_entries'

  #--------------------------------------------
  # PRIVATE FUNCTION: Operations after entries of a feed have been loaded
  #--------------------------------------------
  feed_entries_loaded = (params, response)->
    entriesPaginationSvc.set_busy false

    # If entries list is empty, populate it with received entries and highlight first entry.
    # Otherwise concatenate the received page of entries to the list of entries.
    if !$rootScope.entries || $rootScope.entries?.length == 0
      $rootScope.entries = response.slice()
      highlightedEntrySvc.reset()
    else
      $rootScope.entries = $rootScope.entries.concat response.slice()

    # Set correct state (open or closed) for new entries, based on user configuration
    openEntrySvc.add_entries response.slice()

    # If the user has selected the "open all entries by default" option, lazy load images
    if $rootScope.open_all_entries
      $timeout ->
        lazyLoadingSvc.load_viewport_images()
      , 250

    feed = findSvc.find_feed params.feed_id
    # If less than a full page of entries is received, this is the last page of entries available.
    if response.length < entries_page_size
      entriesPaginationSvc.set_more_entries_available false
      correct_feed_unread_counts feed
    else if entriesPaginationSvc.is_first_page()
      # After loading the first page of entries, load a second one to ensure the list is fully populated
      load_feed_entries feed

  #--------------------------------------------
  # PRIVATE FUNCTION: Operations after entries of a folder have been loaded
  #--------------------------------------------
  folder_entries_loaded = (params, response)->
    entriesPaginationSvc.set_busy false

    # If entries list is empty, populate it with received entries and highlight first entry.
    # Otherwise concatenate the received page of entries to the list of entries.
    if !$rootScope.entries || $rootScope.entries?.length == 0
      $rootScope.entries = response.slice()
      highlightedEntrySvc.reset()
    else
      $rootScope.entries = $rootScope.entries.concat response.slice()

    # Set correct state (open or closed) for new entries, based on user configuration
    openEntrySvc.add_entries response.slice()

    # If the user has selected the "open all entries by default" option, lazy load images
    if $rootScope.open_all_entries
      $timeout ->
        lazyLoadingSvc.load_viewport_images()
      , 250

    folder = findSvc.find_folder params.folder_id
    # If less than a full page of entries is received, this is the last page of entries available.
    if response.length < entries_page_size
      entriesPaginationSvc.set_more_entries_available false
      correct_folder_unread_counts folder
    else if entriesPaginationSvc.is_first_page()
      # After loading the first page of entries, load a second one to ensure the list is fully populated
      load_folder_entries folder

  #--------------------------------------------
  # PRIVATE FUNCTION: Validations and setup that runs every time entries are loaded.
  # Returns true if the load process can continue, false if it must be cancelled.
  #--------------------------------------------
  load_entries_setup = ->
    # If busy, do nothing
    return false if entriesPaginationSvc.is_busy()
    # If a 404 has been received in a previous page (no more entries available), do nothing
    return false if !entriesPaginationSvc.more_entries_available()

    # Reset the timer that updates feeds every minute
    feedsFoldersSvc.reset_refresh_timer()
    # Increment the results page
    entriesPaginationSvc.increment_entries_page()
    # Indicate that AJAX request/response cycle is busy so no more calls are done until finished
    entriesPaginationSvc.set_busy true

    return true

  #--------------------------------------------
  # PRIVATE FUNCTION: Load entries in the feed passed as argument.
  #--------------------------------------------
  load_feed_entries = (feed)->
    return if load_entries_setup() == false

    url = "/api/feeds/#{feed.id}/entries.json"
    worker.postMessage {operation: LOAD_FEED_ENTRIES, token: token, feed_id: feed.id, include_read: $rootScope.show_read, page: entriesPaginationSvc.get_entries_page()}

  #--------------------------------------------
  # PRIVATE FUNCTION: After all entries in a feed have been received, set the unread count for the feed
  # to the number of unread entries actually present.
  #--------------------------------------------
  correct_feed_unread_counts = (feed)->
    entries = findSvc.find_feed_unread_entries feed
    if entries
      changeUnreadCountSvc.set_feed_count feed, entries.length
    else
      changeUnreadCountSvc.set_feed_count feed, 0

  #--------------------------------------------
  # PRIVATE FUNCTION: Load entries in the folder passed as argument.
  #--------------------------------------------
  load_folder_entries = (folder)->
    return if load_entries_setup() == false

    url = "/api/folders/#{folder.id}/entries.json"
    worker.postMessage {operation: LOAD_FOLDER_ENTRIES, token: token, folder_id: folder.id, include_read: $rootScope.show_read, page: entriesPaginationSvc.get_entries_page()}

  #--------------------------------------------
  # PRIVATE FUNCTION: After retrieving entries in a folder, set to zero the unread count of
  # feeds for which no entries have been received.
  #--------------------------------------------
  correct_folder_unread_counts = (folder)->
    feeds = findSvc.find_folder_feeds folder
    if feeds && feeds?.length > 0
      for f in feeds
        correct_feed_unread_counts f

{'fraction_non_alphanumeric': 0.1559862457017818, 'fraction_numerical': 0.0038762113160362615, 'mean_word_length': 2.7156794425087107, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 29, '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': '3140170', 'n_tokens_mistral': 4478, 'n_tokens_neox': 4363, 'n_words': 1327}