From e9bf2fe161ed12843eb26068369a65b20610d36a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Apr 2013 08:23:35 -0700 Subject: [PATCH] Add initial archive viewer --- package.json | 2 + .../lib/archive-edit-session.coffee | 41 +++++++++++++++ .../archive-view/lib/archive-view.coffee | 44 ++++++++++++++++ .../archive-view/lib/directory-view.coffee | 14 +++++ .../archive-view/lib/file-view.coffee | 30 +++++++++++ src/packages/archive-view/package.cson | 3 ++ .../stylesheets/archive-view.less | 52 +++++++++++++++++++ themes/atom-dark-ui/archive-view.less | 9 ++++ themes/atom-dark-ui/package.cson | 1 + 9 files changed, 196 insertions(+) create mode 100644 src/packages/archive-view/lib/archive-edit-session.coffee create mode 100644 src/packages/archive-view/lib/archive-view.coffee create mode 100644 src/packages/archive-view/lib/directory-view.coffee create mode 100644 src/packages/archive-view/lib/file-view.coffee create mode 100644 src/packages/archive-view/package.cson create mode 100644 src/packages/archive-view/stylesheets/archive-view.less create mode 100644 themes/atom-dark-ui/archive-view.less diff --git a/package.json b/package.json index 517a365b4..7b3f33cc2 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "spellchecker": "0.3.0", "pathwatcher": "0.3.0", "keytar": "0.4.0", + "ls-archive": "0.8.0", + "temp": "0.5.0", "plist": "git://github.com/nathansobo/node-plist.git", "space-pen": "1.0.0", "less": "git://github.com/nathansobo/less.js.git", diff --git a/src/packages/archive-view/lib/archive-edit-session.coffee b/src/packages/archive-view/lib/archive-edit-session.coffee new file mode 100644 index 000000000..3f5cd83fc --- /dev/null +++ b/src/packages/archive-view/lib/archive-edit-session.coffee @@ -0,0 +1,41 @@ +fsUtils = require 'fs-utils' +path = require 'path' +_ = require 'underscore' +archive = require 'ls-archive' + +module.exports= +class ArchiveEditSession + registerDeserializer(this) + + @activate: -> + Project = require 'project' + Project.registerOpener (filePath) -> + new ArchiveEditSession(filePath) if archive.isPathSupported(filePath) + + @deserialize: ({path}={}) -> + if fsUtils.exists(path) + new ArchiveEditSession(path) + else + console.warn "Could not build edit session for path '#{path}' because that file no longer exists" + + constructor: (@path) -> + + serialize: -> + deserializer: 'ArchiveEditSession' + path: @path + + getViewClass: -> + require './archive-view' + + getTitle: -> + if archivePath = @getPath() + path.basename(archivePath) + else + 'untitled' + + getUri: -> @path + + getPath: -> @path + + isEqual: (other) -> + other instanceof ArchiveEditSession and @getUri() is other.getUri() diff --git a/src/packages/archive-view/lib/archive-view.coffee b/src/packages/archive-view/lib/archive-view.coffee new file mode 100644 index 000000000..4617eaf07 --- /dev/null +++ b/src/packages/archive-view/lib/archive-view.coffee @@ -0,0 +1,44 @@ +ScrollView = require 'scroll-view' +archive = require 'ls-archive' +{$$} = require 'space-pen' +FileView = require './file-view' +DirectoryView = require './directory-view' + +module.exports = +class ArchiveView extends ScrollView + @content: -> + @div class: 'archive-view', tabindex: -1, => + @div class: 'archive-container', => + @span outlet: 'loadingMessage', class: 'loading-message', 'Loading archive\u2026' + @div outlet: 'tree', class: 'archive-tree' + + initialize: (editSession) -> + super + + @setModel(editSession) + + setPath: (@path) -> + return unless @path? + + @tree.hide() + @loadingMessage.show() + archive.list @path, tree: true, (error, entries) => + console.log @path, error, entries + if error? + console.error("Error listing archive file: #{@path}", error.stack ? error) + else + console.log entries + @loadingMessage.hide() + @tree.empty() + + for entry in entries + if entry.isDirectory() + @tree.append(new DirectoryView(@path, entry)) + else + @tree.append(new FileView(@path, entry)) + + @tree.find('.entry.file:first').addClass('selected') + @tree.show() + + setModel: (editSession) -> + @setPath(editSession?.getPath()) diff --git a/src/packages/archive-view/lib/directory-view.coffee b/src/packages/archive-view/lib/directory-view.coffee new file mode 100644 index 000000000..493580b18 --- /dev/null +++ b/src/packages/archive-view/lib/directory-view.coffee @@ -0,0 +1,14 @@ +{View} = require 'space-pen' +FileView = require './file-view' + +module.exports = +class DirectoryView extends View + @content: (archivePath, entry) -> + @div entry.getName(), class: 'entry directory' + + initialize: (archivePath, entry) -> + for child in entry.children + if child.isDirectory() + @append(new DirectoryView(archivePath, child)) + else + @append(new FileView(archivePath, child)) diff --git a/src/packages/archive-view/lib/file-view.coffee b/src/packages/archive-view/lib/file-view.coffee new file mode 100644 index 000000000..c80719425 --- /dev/null +++ b/src/packages/archive-view/lib/file-view.coffee @@ -0,0 +1,30 @@ +{View} = require 'space-pen' +fs = require 'fs' +path = require 'path' +temp = require 'temp' +archive = require 'ls-archive' + +module.exports = +class FileView extends View + @content: (archivePath, entry) -> + @div => + @span entry.getName(), class: 'entry file' + + initialize: (archivePath, entry) -> + @on 'click', => + @closest('.archive-view').find('.entry').removeClass('selected') + @addClass('selected') + archive.readFile archivePath, entry.getPath(), (error, contents) -> + if error? + console.error("Error reading: #{entry.getPath()} from #{archivePath}", error.stack ? error) + else + temp.mkdir path.basename(archivePath), (error, tempDirPath) -> + if error? + console.error("Error creating temp directory: #{tempDirPath}") + else + tempFilePath = path.join(tempDirPath, entry.getName()) + fs.writeFile tempFilePath, contents, (error) -> + if error? + console.error("Error writing to #{tempFilePath}") + else + rootView.open(tempFilePath) diff --git a/src/packages/archive-view/package.cson b/src/packages/archive-view/package.cson new file mode 100644 index 000000000..3ba8e9fe4 --- /dev/null +++ b/src/packages/archive-view/package.cson @@ -0,0 +1,3 @@ +'description': 'View the files and folders inside archive files' +'main': './lib/archive-edit-session' +'deferredDeserializers': ['ArchiveEditSession'] diff --git a/src/packages/archive-view/stylesheets/archive-view.less b/src/packages/archive-view/stylesheets/archive-view.less new file mode 100644 index 000000000..b1fd922eb --- /dev/null +++ b/src/packages/archive-view/stylesheets/archive-view.less @@ -0,0 +1,52 @@ +@import "bootstrap/less/variables.less"; +@import "octicon-mixins.less"; + +.archive-view { + margin: 0; + padding: 0; + overflow: auto; + position: relative; + display: -webkit-flex; + @icon-margin: @line-height-base / 4; + + .archive-container { + height:100%; + width: 100%; + padding: 5px; + + .loading-message { + .mini-icon(hourglass); + + &:before { + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 5px; + } + } + + .entry { + padding: 5px; + + > .entry { + margin-left: 5px; + } + + &:before { + margin-right: @icon-margin; + } + + &.file { + .mini-icon(text-file); + } + + &.directory { + .mini-icon(directory); + } + + &.symlink { + .mini-icon(symlink); + } + } + } +} diff --git a/themes/atom-dark-ui/archive-view.less b/themes/atom-dark-ui/archive-view.less new file mode 100644 index 000000000..2acf2eb5e --- /dev/null +++ b/themes/atom-dark-ui/archive-view.less @@ -0,0 +1,9 @@ +.archive-view { + background-color: #1d1f21; + color: #7d7d7d; + + .selected { + background-color: #434343; + color: #bdbdbd; + } +} diff --git a/themes/atom-dark-ui/package.cson b/themes/atom-dark-ui/package.cson index 5f72c350d..bf65ab7d7 100644 --- a/themes/atom-dark-ui/package.cson +++ b/themes/atom-dark-ui/package.cson @@ -9,4 +9,5 @@ 'command-logger' 'blurred' 'image-view' + 'archive-view' ]