Load all data files from a single archive
This commit is contained in:
@@ -19,10 +19,10 @@ module.exports = class BaseModel extends Backbone.Model
|
|||||||
continue if name is 'id'
|
continue if name is 'id'
|
||||||
Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name)
|
Object.defineProperty this, name, get:makeGetter(name), set:makeSetter(name)
|
||||||
|
|
||||||
|
@fileCache = options.fileCache or null
|
||||||
|
@loading = null
|
||||||
@logEvents = options.logEvents or false
|
@logEvents = options.logEvents or false
|
||||||
@state = c.modelState.unloaded
|
@state = c.modelState.unloaded
|
||||||
|
|
||||||
@loading = null
|
|
||||||
|
|
||||||
Object.defineProperties this,
|
Object.defineProperties this,
|
||||||
isUnloaded: { get:-> @state is c.modelState.unloaded }
|
isUnloaded: { get:-> @state is c.modelState.unloaded }
|
||||||
@@ -60,12 +60,24 @@ module.exports = class BaseModel extends Backbone.Model
|
|||||||
|
|
||||||
@state = c.modelState.loading
|
@state = c.modelState.loading
|
||||||
@trigger c.event.request, this
|
@trigger c.event.request, this
|
||||||
@loading = w.promise (resolve, reject)=>
|
|
||||||
$.ajax
|
loadFromServer = =>
|
||||||
url: url
|
w.promise (resolve, reject)=>
|
||||||
dataType: 'text'
|
$.ajax
|
||||||
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
|
url: url
|
||||||
error: (xhr, status, error)=> reject @onLoadFailed error, status, xhr
|
dataType: 'text'
|
||||||
|
success: (text, status, xhr)=> resolve @onLoadSucceeded text, status, xhr
|
||||||
|
error: (xhr, status, error)=> reject @onLoadFailed error, status, xhr
|
||||||
|
|
||||||
|
if @fileCache?
|
||||||
|
@loading = @fileCache.loading.then =>
|
||||||
|
if @fileCache.hasFile url
|
||||||
|
@onLoadSucceeded @fileCache.getFile(url), 'success', {url:url}
|
||||||
|
return w.resolve(true)
|
||||||
|
else
|
||||||
|
@loading = loadFromServer()
|
||||||
|
else
|
||||||
|
@loading = loadFromServer()
|
||||||
|
|
||||||
@loading.catch (e)-> # do nothing
|
@loading.catch (e)-> # do nothing
|
||||||
return @loading
|
return @loading
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
###
|
#
|
||||||
# Crafting Guide - event_recorder.coffee
|
# Crafting Guide - event_recorder.coffee
|
||||||
#
|
#
|
||||||
# Copyright (c) 2014-2015 by Redwood Labs
|
# Copyright © 2014-2016 by Redwood Labs
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
###
|
#
|
||||||
|
|
||||||
util = require 'util'
|
util = require 'util'
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ module.exports = class Mod extends BaseModel
|
|||||||
|
|
||||||
@_modVersions.push modVersion
|
@_modVersions.push modVersion
|
||||||
@listenTo modVersion, c.event.change, => @trigger c.event.change, this
|
@listenTo modVersion, c.event.change, => @trigger c.event.change, this
|
||||||
|
modVersion.fileCache = this.fileCache
|
||||||
modVersion.mod = this
|
modVersion.mod = this
|
||||||
|
|
||||||
@trigger c.event.add + ':modVersion', modVersion, this
|
@trigger c.event.add + ':modVersion', modVersion, this
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#
|
||||||
|
# Crafting Guide - file_cache.coffee
|
||||||
|
#
|
||||||
|
# Copyright © 2014-2016 by Redwood Labs
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
module.exports = class FileCache extends Backbone.Events
|
||||||
|
|
||||||
|
@::FILE_TOKEN = '#file='
|
||||||
|
|
||||||
|
constructor: (url)->
|
||||||
|
@_ajax = $.ajax
|
||||||
|
@_files = {}
|
||||||
|
@_loading = w.resolve(true)
|
||||||
|
|
||||||
|
if url? then @loadArchive(url).catch(->)
|
||||||
|
|
||||||
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
|
getFile: (file)->
|
||||||
|
return null unless @hasFile file
|
||||||
|
return @_files[file]
|
||||||
|
|
||||||
|
hasFile: (file)->
|
||||||
|
return @_files[file]?
|
||||||
|
|
||||||
|
loadArchive: (url)->
|
||||||
|
if not _.isFunction(@_ajax) then throw new Error '$.ajax is required'
|
||||||
|
|
||||||
|
newLoading = w.promise (resolve, reject)=>
|
||||||
|
@_ajax
|
||||||
|
url: url
|
||||||
|
dataType: 'text'
|
||||||
|
success: (text, status, xhr)=> resolve @_onLoadSuccess text, status, xhr
|
||||||
|
error: (xhr, status, error)=> resolve @_onLoadError error, status, xhr
|
||||||
|
|
||||||
|
@_loading = w.join @_loading, newLoading
|
||||||
|
|
||||||
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
|
Object.defineProperties @prototype,
|
||||||
|
|
||||||
|
loading:
|
||||||
|
get: -> return @_loading
|
||||||
|
|
||||||
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_onLoadError: (error, status, xhr)->
|
||||||
|
console.error "Failed to load archive: #{xhr.responseText}"
|
||||||
|
return false
|
||||||
|
|
||||||
|
_onLoadSuccess: (text, status, xhr)->
|
||||||
|
return @_parseArchive text
|
||||||
|
|
||||||
|
_parseArchive: (text)->
|
||||||
|
file = null
|
||||||
|
tokenIndex = nameStartIndex = nameEndIndex = fileStartIndex = fileEndIndex = 0
|
||||||
|
fileCount = 0
|
||||||
|
|
||||||
|
while true
|
||||||
|
tokenIndex = text.indexOf @FILE_TOKEN, fileStartIndex
|
||||||
|
if tokenIndex is -1
|
||||||
|
if file?
|
||||||
|
@_files[file] = text.substring fileStartIndex, text.length
|
||||||
|
fileCount += 1
|
||||||
|
break
|
||||||
|
|
||||||
|
if file?
|
||||||
|
fileEndIndex = tokenIndex - 1
|
||||||
|
@_files[file] = text.substring fileStartIndex, fileEndIndex
|
||||||
|
fileCount += 1
|
||||||
|
|
||||||
|
nameStartIndex = tokenIndex + @FILE_TOKEN.length
|
||||||
|
nameEndIndex = text.indexOf '\n', nameStartIndex
|
||||||
|
if nameEndIndex is -1
|
||||||
|
file = text.substring nameStartIndex, text.length
|
||||||
|
@_files[file] = ''
|
||||||
|
break
|
||||||
|
|
||||||
|
file = text.substring nameStartIndex, nameEndIndex
|
||||||
|
fileStartIndex = nameEndIndex + '\n'.length
|
||||||
|
|
||||||
|
return fileCount > 0
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
|
||||||
|
FileCache = require './file_cache'
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
describe 'file_cache.coffee', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@cache = new FileCache
|
||||||
|
|
||||||
|
makeTestAjax = (text)->
|
||||||
|
return (options)->
|
||||||
|
options.success text, 'success', {url:options.url}
|
||||||
|
|
||||||
|
it 'can load an archive with a single file', ->
|
||||||
|
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie delta'
|
||||||
|
@cache.loadArchive 'http://test'
|
||||||
|
.then =>
|
||||||
|
@cache.hasFile('alpha').should.equal true
|
||||||
|
@cache.getFile('alpha').should.equal 'bravo charlie delta'
|
||||||
|
|
||||||
|
it 'can load an archive with multiple files', ->
|
||||||
|
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\necho foxtrot'
|
||||||
|
@cache.loadArchive 'http://test'
|
||||||
|
.then =>
|
||||||
|
@cache.hasFile('alpha').should.equal true
|
||||||
|
@cache.getFile('alpha').should.equal 'bravo charlie'
|
||||||
|
@cache.hasFile('delta').should.equal true
|
||||||
|
@cache.getFile('delta').should.equal 'echo foxtrot'
|
||||||
|
|
||||||
|
it 'can cope with an empty file in the middle of an archive', ->
|
||||||
|
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\n#file=echo\nfoxtrot golf'
|
||||||
|
@cache.loadArchive 'http://test'
|
||||||
|
.then =>
|
||||||
|
@cache.hasFile('alpha').should.equal true
|
||||||
|
@cache.getFile('alpha').should.equal 'bravo charlie'
|
||||||
|
@cache.hasFile('delta').should.equal true
|
||||||
|
@cache.getFile('delta').should.equal '\n'
|
||||||
|
@cache.hasFile('echo').should.equal true
|
||||||
|
@cache.getFile('echo').should.equal 'foxtrot golf'
|
||||||
|
|
||||||
|
it 'can cope with an empty file at the end of an archive', ->
|
||||||
|
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta'
|
||||||
|
@cache.loadArchive 'http://test'
|
||||||
|
.then =>
|
||||||
|
@cache.hasFile('alpha').should.equal true
|
||||||
|
@cache.getFile('alpha').should.equal 'bravo charlie'
|
||||||
|
@cache.hasFile('delta').should.equal true
|
||||||
|
@cache.getFile('delta').should.equal ''
|
||||||
|
|
||||||
|
it 'can load multiple, non-overlapping archives', ->
|
||||||
|
@cache._ajax = makeTestAjax '#file=alpha\nbravo charlie\n#file=delta\necho foxtrot'
|
||||||
|
@cache.loadArchive 'http://test'
|
||||||
|
|
||||||
|
@cache._ajax = makeTestAjax '#file=golf\nhotel india'
|
||||||
|
@cache.loadArchive 'http://test2'
|
||||||
|
.then =>
|
||||||
|
@cache.hasFile('alpha').should.equal true
|
||||||
|
@cache.getFile('alpha').should.equal 'bravo charlie'
|
||||||
|
@cache.hasFile('delta').should.equal true
|
||||||
|
@cache.getFile('delta').should.equal 'echo foxtrot'
|
||||||
|
@cache.hasFile('golf').should.equal true
|
||||||
|
@cache.getFile('golf').should.equal 'hotel india'
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
BaseController = require './base_controller'
|
BaseController = require './base_controller'
|
||||||
FeedbackController = require './feedback/feedback_controller'
|
FeedbackController = require './feedback/feedback_controller'
|
||||||
|
FileCache = require '../models/site/file_cache'
|
||||||
FooterController = require './footer/footer_controller'
|
FooterController = require './footer/footer_controller'
|
||||||
GitHubUser = require '../models/site/github_user'
|
GitHubUser = require '../models/site/github_user'
|
||||||
HeaderController = require './header/header_controller'
|
HeaderController = require './header/header_controller'
|
||||||
@@ -26,8 +27,9 @@ module.exports = class SiteController extends BaseController
|
|||||||
super options
|
super options
|
||||||
|
|
||||||
@client = options.client
|
@client = options.client
|
||||||
|
@fileCache = new FileCache c.url.modpackArchive()
|
||||||
@imageLoader = new ImageLoader defaultUrl:'/images/unknown.png'
|
@imageLoader = new ImageLoader defaultUrl:'/images/unknown.png'
|
||||||
@modPack = new ModPack
|
@modPack = new ModPack {}, fileCache:@fileCache
|
||||||
@router = new Router this
|
@router = new Router this
|
||||||
@storage = options.storage
|
@storage = options.storage
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ module.exports = class SiteController extends BaseController
|
|||||||
m.activeModVersion.fetch() if m.activeModVersion?
|
m.activeModVersion.fetch() if m.activeModVersion?
|
||||||
|
|
||||||
for modSlug, modData of c.defaultMods
|
for modSlug, modData of c.defaultMods
|
||||||
mod = new Mod slug:modSlug
|
mod = new Mod {slug:modSlug}, {fileCache:@fileCache}
|
||||||
mod.on c.event.change + ':activeModVersion', makeResponder mod
|
mod.on c.event.change + ':activeModVersion', makeResponder mod
|
||||||
@storage.register "mod:#{mod.slug}", mod, 'activeVersion', modData.defaultVersion
|
@storage.register "mod:#{mod.slug}", mod, 'activeVersion', modData.defaultVersion
|
||||||
mod.fetch()
|
mod.fetch()
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ url.login = _.template "/login"
|
|||||||
url.mod = _.template "/browse/<%= modSlug %>/"
|
url.mod = _.template "/browse/<%= modSlug %>/"
|
||||||
url.modData = _.template "/data/<%= modSlug %>/mod.cg"
|
url.modData = _.template "/data/<%= modSlug %>/mod.cg"
|
||||||
url.modIcon = _.template "/data/<%= modSlug %>/icon.png"
|
url.modIcon = _.template "/data/<%= modSlug %>/icon.png"
|
||||||
|
url.modpackArchive = _.template "/data/modpack.cg"
|
||||||
url.modVersionData = _.template "/data/<%= modSlug %>/versions/<%= modVersion %>/mod-version.cg"
|
url.modVersionData = _.template "/data/<%= modSlug %>/versions/<%= modVersion %>/mod-version.cg"
|
||||||
url.root = _.template "/"
|
url.root = _.template "/"
|
||||||
url.tutorial = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/"
|
url.tutorial = _.template "/browse/<%= modSlug %>/tutorials/<%= tutorialSlug %>/"
|
||||||
|
|||||||
Reference in New Issue
Block a user