blob: ef584a6dbbb856d6c9291728f6c51f587f6e66ea [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as pathutil;
import '../models/all.dart' as model;
import '../stores/store.dart';
import '../stores/utils/key.dart' as keyutil;
import '../utils/uuid.dart' as uuidutil;
final Logger log = new Logger('loader');
const String _baseDecksPath = '/sdcard/syncslides/decks';
Directory _baseDecksDir = new Directory(_baseDecksPath);
// Loader is responsible for importing existing decks and slides into the store.
class Loader {
final Store _store = new Store.singleton();
static Loader _singletonLoader = new Loader._internal();
factory Loader.singleton() {
return _singletonLoader;
}
Loader._internal();
// Loads all the decks in /sdcard/syncslides/decks
// Name of each deck is the name of its directory.
// Slide image files must be numbered.
// First slide is used as the thumbnail.
// Example:
// /sdcard/syncslides/decks/Foo
// /sdcard/syncslides/decks/Foo/1.png
// /sdcard/syncslides/decks/Foo/2.png
// /sdcard/syncslides/decks/Bar
// /sdcard/syncslides/decks/Bar/1.gif
//
// TODO(aghassemi): Replace with a Path Selector dialog.
Future loadDeck() async {
if (!await _baseDecksDir.exists()) {
log.warning('Default $_baseDecksPath directory does not exist.');
return;
}
Stream allDecksDir = _baseDecksDir.list();
await for (FileSystemEntity fsEntity in allDecksDir) {
if (!(fsEntity is Directory)) {
log.warning(
'Ignoring non-directory ${pathutil.basename(fsEntity.path)} in $_baseDecksPath');
continue;
}
_loadDeck(fsEntity.path);
}
}
Future _loadDeck(String path) async {
var deckName = pathutil.basename(path);
var deckId = uuidutil.createUuid();
Directory deckDir = new Directory(path);
List<model.Slide> slides = new List();
await for (FileSystemEntity fsEntity in deckDir.list()) {
if (!(fsEntity is File)) {
log.warning(
'Ignoring non-file ${pathutil.basename(fsEntity.path)} in $path');
continue;
}
File slideFile = fsEntity as File;
var slideNum;
try {
String slideName = pathutil.basenameWithoutExtension(slideFile.path);
slideNum = int.parse(slideName);
slideNum--; // Zero based index.
} catch (e) {
throw new ArgumentError(
"Filename ${pathutil.basename(slideFile.path)} for a slide must be a number.");
}
// Create the slide object.
List<int> slideBytes = await slideFile.readAsBytes();
var blobRef = new model.BlobRef(
keyutil.getDeckBlobKey(deckId, uuidutil.createUuid()));
await _store.actions.putBlob(blobRef.key, slideBytes);
model.Slide slide = new model.Slide(slideNum, blobRef);
slides.add(slide);
}
if (slides.isEmpty) {
log.warning('No image files found in $path.');
return;
}
slides.sort((model.Slide s1, model.Slide s2) => s1.num.compareTo(s2.num));
// Use the first slide as thumbnail.
model.BlobRef thumbnailBlobRef = slides.first.image;
var deck = new model.Deck(deckId, deckName, thumbnailBlobRef);
await _store.actions.addDeck(deck);
await _store.actions.setSlides(deck.key, slides);
}
}