enigma-bbs/mods/file_area_list.js

229 lines
5.5 KiB
JavaScript

/* jslint node: true */
'use strict';
// ENiGMA½
const MenuModule = require('../core/menu_module.js').MenuModule;
const ViewController = require('../core/view_controller.js').ViewController;
const ansi = require('../core/ansi_term.js');
const theme = require('../core/theme.js');
const FileEntry = require('../core/file_entry.js');
const stringFormat = require('../core/string_format.js');
const FileArea = require('../core/file_area.js');
// deps
const async = require('async');
const _ = require('lodash');
const moment = require('moment');
/*
Misc TODO
* Allow rating to be user defined colors & characters/etc.
*
Well known file entry meta values:
* upload_by_username
* upload_by_user_id
* file_md5
* file_sha256
* file_crc32
* est_release_year
* dl_count
* byte_size
* user_rating
*
*/
exports.moduleInfo = {
name : 'File Area List',
desc : 'Lists contents of file an file area',
author : 'NuSkooler',
};
const FormIds = {
browse : 0,
details : 1,
};
const MciViewIds = {
browse : {
desc : 1,
navMenu : 2,
// 10+: customs
},
};
exports.getModule = class FileAreaList extends MenuModule {
constructor(options) {
super(options);
const config = this.menuConfig.config;
if(options.extraArgs) {
this.filterCriteria = options.extraArgs.filterCriteria;
}
this.filterCriteria = this.filterCriteria || {
// :TODO: set area tag - all in current area by default
};
this.currentFileEntry = new FileEntry();
}
enter() {
super.enter();
}
leave() {
super.leave();
}
initSequence() {
const self = this;
async.series(
[
function beforeArt(callback) {
return self.beforeArt(callback);
},
function display(callback) {
return self.displayBrowsePage(false, callback);
}
],
() => {
self.finishedLoading();
}
);
}
displayBrowsePage(clearScreen, cb) {
const self = this;
const config = this.menuConfig.config;
async.waterfall(
[
function clearAndDisplayArt(callback) {
if (clearScreen) {
self.client.term.rawWrite(ansi.resetScreen());
}
theme.displayThemedAsset(
config.art.browse,
self.client,
{ font : self.menuConfig.font, trailingLF : false },
(err, artData) => {
return callback(err, artData);
}
);
},
function prepeareViewController(artData, callback) {
if(_.isUndefined(self.viewControllers.browse)) {
const vc = self.addViewController(
'browse',
new ViewController( { client : self.client, formId : FormIds.browse } )
);
const loadOpts = {
callingMenu : self,
mciMap : artData.mciMap,
formId : FormIds.browse,
};
return vc.loadFromMenuConfig(loadOpts, callback);
}
self.viewControllers.view.setFocus(true);
self.viewControllers.view.getView(MciViewIds.view.BBSList).redraw();
return callback(null);
},
function fetchEntryData(callback) {
return self.loadFileIds(callback);
},
function loadCurrentFileInfo(callback) {
self.currentFileEntry.load( self.fileList[ self.fileListPosition ], err => {
return callback(err);
});
},
function populateViews(callback) {
if(_.isString(self.currentFileEntry.desc)) {
const descView = self.viewControllers.browse.getView(MciViewIds.browse.desc);
if(descView) {
descView.setText(self.currentFileEntry.desc);
}
}
const currEntry = self.currentFileEntry;
const uploadTimestampFormat = config.browseUploadTimestampFormat || config.uploadTimestampFormat || 'YYYY-MMM-DD';
const area = FileArea.getFileAreaByTag(currEntry.areaTag);
const hashTagsSep = config.hashTagsSep || ', ';
const entryInfo = {
fileId : currEntry.fileId,
areaTag : currEntry.areaTag,
areaName : area.name || 'N/A',
areaDesc : area.desc || 'N/A',
fileSha1 : currEntry.fileSha1,
fileName : currEntry.fileName,
desc : currEntry.desc,
descLong : currEntry.descLong,
uploadByUsername : currEntry.uploadByUsername,
uploadTimestamp : moment(currEntry.uploadTimestamp).format(uploadTimestampFormat),
hashTags : Array.from(currEntry.hashTags).join(hashTagsSep),
};
//
// We need the entry object to contain meta keys even if they are empty as
// consumers may very likely attempt to use them
//
const metaValues = FileEntry.getWellKnownMetaValues();
metaValues.forEach(name => {
const value = currEntry.meta[name] || '';
entryInfo[_.camelCase(name)] = value;
});
const userRatingChar = config.userRatingChar ? config.userRatingChar[0] : '*';
if(_.isNumber(entryInfo.userRating)) {
entryInfo.userRatingString = new Array(entryInfo.userRating).join(userRatingChar);
} else {
entryInfo.userRatingString = '';
}
// 10+ are custom textviews
let textView;
let customMciId = 10;
while( (textView = self.viewControllers.browse.getView(customMciId)) ) {
const key = `browseInfoFormat${customMciId}`;
const format = config[key];
if(format) {
textView.setText(stringFormat(format, entryInfo));
}
++customMciId;
}
return callback(null);
}
],
err => {
if(cb) {
return cb(err);
}
}
);
}
loadFileIds(cb) {
this.fileListPosition = 0;
FileEntry.findFiles(this.filterCriteria, (err, fileIds) => {
this.fileList = fileIds;
return cb(err);
});
}
};