<commit_before>goog.provide 'app.LocalStorage'

goog.require 'common.Storage'
goog.require 'goog.array'
goog.require 'goog.labs.userAgent.browser'
goog.require 'goog.storage.Storage'
goog.require 'goog.storage.mechanism.mechanismfactory'

class app.LocalStorage

  ###*
    @constructor
  ###
  constructor: ->
    @tryCreate()
    @migrate()

  localStorageKey: 'songary'
  localStorageVersion: 1

  ###*
    Can be null, Safari in private mode does not allow localStorage.
    @type {goog.storage.Storage}
    @protected
  ###
  localStorage: null

  ###*
    @protected
  ###
  tryCreate: ->
    mechanism = goog.storage.mechanism.mechanismfactory
      .createHTML5LocalStorage @localStorageKey
    return if !mechanism
    @localStorage = new goog.storage.Storage mechanism
    @ensureVersion()

  ensureVersion: ->
    version = @localStorage.get '@version'
    return if version
    # NOTE(steida): Update to version 1.
    @localStorage.remove 'songs'
    @localStorage.set '@version', @localStorageVersion

  ###*
    @protected
  ###
  migrate: ->
    return if !@localStorage
    storageVersion = Number @localStorage.get '@version'
    scriptVersion = @localStorageVersion
    userOrig = @localStorage.get 'user'
    try
      migrateVersion() for migrateVersion in [
        =>
          # Example:
          # user = @localStorage.get 'user'
          # user.songs = user.songs.map (song) ->
          #   lyrics = song.lyrics
          #   delete song.lyrics
          #   song.llyrics = lyrics
          #   song
          # @localStorage.set 'user', user
        =>
          # console.log 'from 2 to 3'
      ].slice storageVersion - 1, scriptVersion - 1
    catch e
      # TODO(steida): Report error to server.
      @localStorage.set 'user', userOrig
      return
    @localStorage.set '@version', scriptVersion
    return

  ###*
    @param {Array.<app.Store>} stores
  ###
  load: (stores) ->
    return if !@localStorage
    @loadFromJson stores
    @listenWindowStorage stores

  ###*
    @param {Array.<app.Store>} stores
    @protected
  ###
  loadFromJson: (stores) ->
    stores.forEach (store) =>
      json = @localStorage.get store.name
      return if !json
      # TODO(steida): Try/Catch in case of error. Report error to server.
      store.fromJson json

  ###*
    Sync app state across tabs/windows.
    @param {Array.<app.Store>} stores
    @protected
  ###
  listenWindowStorage: (stores) ->
    # IE 9/10/11 implementation of window storage event is broken. Check:
    # http://stackoverflow.com/a/4679754
    return if goog.labs.userAgent.browser.isIE()

    goog.events.listen window, 'storage', (e) =>
      # TODO(steida): Reload if localStorageVersion changed.
      browserEvent = e.getBrowserEvent()
      storeName = browserEvent.key.split('::')[1]
      return if !storeName
      store = goog.array.find stores, (store) -> store.name == storeName
      return if !store

      # NOTE(steida): Because FirebaseSimpleLogin does not propagate login
      # state across browser windows, we need to track change manually.
      if store instanceof app.user.Store
        userWasLogged = !!store.user

      # TODO(steida): Try/Catch in case of error. Report error to server.
      json = (`/** @type {Object} */`) JSON.parse browserEvent.newValue
      store.fromJson json
      store.notify()

      # NOTE(steida): Reload browser if user login state has changed.<commit_msg>serverNotify ftw. Please bower update.<commit_after>goog.provide 'app.LocalStorage'

goog.require 'common.Storage'
goog.require 'goog.array'
goog.require 'goog.labs.userAgent.browser'
goog.require 'goog.storage.Storage'
goog.require 'goog.storage.mechanism.mechanismfactory'

class app.LocalStorage

  ###*
    @constructor
  ###
  constructor: ->
    @tryCreate()
    @migrate()

  localStorageKey: 'songary'
  localStorageVersion: 1

  ###*
    Can be null, Safari in private mode does not allow localStorage.
    @type {goog.storage.Storage}
    @protected
  ###
  localStorage: null

  ###*
    @protected
  ###
  tryCreate: ->
    mechanism = goog.storage.mechanism.mechanismfactory
      .createHTML5LocalStorage @localStorageKey
    return if !mechanism
    @localStorage = new goog.storage.Storage mechanism
    @ensureVersion()

  ensureVersion: ->
    version = @localStorage.get '@version'
    return if version
    # NOTE(steida): Update to version 1.
    @localStorage.remove 'songs'
    @localStorage.set '@version', @localStorageVersion

  ###*
    @protected
  ###
  migrate: ->
    return if !@localStorage
    storageVersion = Number @localStorage.get '@version'
    scriptVersion = @localStorageVersion
    userOrig = @localStorage.get 'user'
    try
      migrateVersion() for migrateVersion in [
        =>
          # Example:
          # user = @localStorage.get 'user'
          # user.songs = user.songs.map (song) ->
          #   lyrics = song.lyrics
          #   delete song.lyrics
          #   song.llyrics = lyrics
          #   song
          # @localStorage.set 'user', user
        =>
          # console.log 'from 2 to 3'
      ].slice storageVersion - 1, scriptVersion - 1
    catch e
      # TODO(steida): Report error to server.
      @localStorage.set 'user', userOrig
      return
    @localStorage.set '@version', scriptVersion
    return

  ###*
    @param {Array.<app.Store>} stores
  ###
  load: (stores) ->
    return if !@localStorage
    @loadFromJson stores
    @listenWindowStorage stores

  ###*
    @param {Array.<app.Store>} stores
    @protected
  ###
  loadFromJson: (stores) ->
    stores.forEach (store) =>
      json = @localStorage.get store.name
      return if !json
      # TODO(steida): Try/Catch in case of error. Report error to server.
      store.fromJson json

  ###*
    Sync app state across tabs/windows.
    @param {Array.<app.Store>} stores
    @protected
  ###
  listenWindowStorage: (stores) ->
    # IE 9/10/11 implementation of window storage event is broken. Check:
    # http://stackoverflow.com/a/4679754
    return if goog.labs.userAgent.browser.isIE()

    goog.events.listen window, 'storage', (e) =>
      # TODO(steida): Reload if localStorageVersion changed.
      browserEvent = e.getBrowserEvent()
      storeName = browserEvent.key.split('::')[1]
      return if !storeName
      store = goog.array.find stores, (store) -> store.name == storeName
      return if !store

      # NOTE(steida): Because FirebaseSimpleLogin does not propagate login
      # state across browser windows, we need to track change manually.
      if store instanceof app.user.Store
        userWasLogged = !!store.user

      # TODO(steida): Try/Catch in case of error. Report error to server.
      json = (`/** @type {Object} */`) JSON.parse browserEvent.newValue
      store.fromJson json
      store.serverNotify()

      # NOTE(steida): Reload browser if user login state has changed.
{'fraction_non_alphanumeric': 0.11600523331879634, 'fraction_numerical': 0.005814798662596307, 'mean_word_length': 2.69693713057496, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 35, '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': '2742295', 'n_tokens_mistral': 2113, 'n_tokens_neox': 2034, 'n_words': 539}