FileItemList.coffee 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. class FileItemList extends Class
  2. constructor: (@inner_path) ->
  3. @items = []
  4. @updating = false
  5. @files_modified = {}
  6. @dirs_modified = {}
  7. @files_added = {}
  8. @dirs_added = {}
  9. @files_optional = {}
  10. @items_by_name = {}
  11. # Update item list
  12. update: (cb) ->
  13. @updating = true
  14. @logStart("Updating dirlist")
  15. Page.cmd "dirList", {inner_path: @inner_path, stats: true}, (res) =>
  16. if res.error
  17. @error = res.error
  18. else
  19. @error = null
  20. pattern_ignore = RegExp("^" + Page.site_info.content?.ignore)
  21. @items.splice(0, @items.length) # Remove all items
  22. @items_by_name = {}
  23. for row in res
  24. row.type = @getFileType(row)
  25. row.inner_path = @inner_path + row.name
  26. if Page.site_info.content?.ignore and row.inner_path.match(pattern_ignore)
  27. row.ignored = true
  28. @items.push(row)
  29. @items_by_name[row.name] = row
  30. @sort()
  31. if Page.site_info?.settings?.own
  32. @updateAddedFiles()
  33. @updateOptionalFiles =>
  34. @updating = false
  35. cb?()
  36. @logEnd("Updating dirlist", @inner_path)
  37. Page.projector.scheduleRender()
  38. @updateModifiedFiles =>
  39. Page.projector.scheduleRender()
  40. updateModifiedFiles: (cb) =>
  41. # Add modified attribute to changed files
  42. Page.cmd "siteListModifiedFiles", [], (res) =>
  43. @files_modified = {}
  44. @dirs_modified = {}
  45. for inner_path in res.modified_files
  46. @files_modified[inner_path] = true
  47. dir_inner_path = ""
  48. dir_parts = inner_path.split("/")
  49. for dir_part in dir_parts[..-2]
  50. if dir_inner_path
  51. dir_inner_path += "/#{dir_part}"
  52. else
  53. dir_inner_path = dir_part
  54. @dirs_modified[dir_inner_path] = true
  55. cb?()
  56. # Update newly added items list since last sign
  57. updateAddedFiles: =>
  58. Page.cmd "fileGet", "content.json", (res) =>
  59. if not res
  60. return false
  61. content = JSON.parse(res)
  62. # Check new files
  63. if not content.files?
  64. return false
  65. @files_added = {}
  66. for file in @items
  67. if file.name == "content.json" or file.is_dir
  68. continue
  69. if not content.files[@inner_path + file.name]
  70. @files_added[@inner_path + file.name] = true
  71. # Check new dirs
  72. @dirs_added = {}
  73. dirs_content = {}
  74. for file_name of Object.assign({}, content.files, content.files_optional)
  75. if not file_name.startsWith(@inner_path)
  76. continue
  77. pattern = new RegExp("#{@inner_path}(.*?)/")
  78. match = file_name.match(pattern)
  79. if not match
  80. continue
  81. dirs_content[match[1]] = true
  82. for file in @items
  83. if not file.is_dir
  84. continue
  85. if not dirs_content[file.name]
  86. @dirs_added[@inner_path + file.name] = true
  87. # Update optional files list
  88. updateOptionalFiles: (cb) =>
  89. Page.cmd "optionalFileList", {filter: ""}, (res) =>
  90. @files_optional = {}
  91. for optional_file in res
  92. @files_optional[optional_file.inner_path] = optional_file
  93. @addOptionalFilesToItems()
  94. cb?()
  95. # Add optional files to item list
  96. addOptionalFilesToItems: =>
  97. is_added = false
  98. for inner_path, optional_file of @files_optional
  99. if optional_file.inner_path.startsWith(@inner_path)
  100. if @getDirectory(optional_file.inner_path) == @inner_path
  101. # Add optional file to list
  102. file_name = @getFileName(optional_file.inner_path)
  103. if not @items_by_name[file_name]
  104. row = {
  105. "name": file_name, "type": "file", "optional_empty": true,
  106. "size": optional_file.size, "is_dir": false, "inner_path": optional_file.inner_path
  107. }
  108. @items.push(row)
  109. @items_by_name[file_name] = row
  110. is_added = true
  111. else
  112. # Add optional dir to list
  113. dir_name = optional_file.inner_path.replace(@inner_path, "").match(/(.*?)\//, "")?[1]
  114. if dir_name and not @items_by_name[dir_name]
  115. row = {
  116. "name": dir_name, "type": "dir", "optional_empty": true,
  117. "size": 0, "is_dir": true, "inner_path": optional_file.inner_path
  118. }
  119. @items.push(row)
  120. @items_by_name[dir_name] = row
  121. is_added = true
  122. if is_added
  123. @sort()
  124. getFileType: (file) =>
  125. if file.is_dir
  126. return "dir"
  127. else
  128. return "unknown"
  129. getDirectory: (inner_path) ->
  130. if inner_path.indexOf("/") != -1
  131. return inner_path.replace(/^(.*\/)(.*?)$/, "$1")
  132. else
  133. return ""
  134. getFileName: (inner_path) ->
  135. return inner_path.replace(/^(.*\/)(.*?)$/, "$2")
  136. isModified: (inner_path) =>
  137. return @files_modified[inner_path] or @dirs_modified[inner_path]
  138. isAdded: (inner_path) =>
  139. return @files_added[inner_path] or @dirs_added[inner_path]
  140. hasPermissionDelete: (file) =>
  141. if file.type in ["dir", "parent"]
  142. return false
  143. if file.inner_path == "content.json"
  144. return false
  145. optional_info = @getOptionalInfo(file.inner_path)
  146. if optional_info and optional_info.downloaded_percent > 0
  147. return true
  148. else
  149. return Page.site_info?.settings?.own
  150. getOptionalInfo: (inner_path) =>
  151. return @files_optional[inner_path]
  152. sort: =>
  153. @items.sort (a, b) ->
  154. return (b.is_dir - a.is_dir) || a.name.localeCompare(b.name)
  155. window.FileItemList = FileItemList