parent
e53e69efcf
commit
60091a94b6
83
area.js
83
area.js
|
|
@ -1129,14 +1129,7 @@ var DrawingArea = new Lang.Class({
|
|||
}
|
||||
content += "\n</svg>";
|
||||
|
||||
let filename = `${Me.metadata['svg-file-name']} ${Files.getDateString()}.svg`;
|
||||
let dir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES);
|
||||
let path = GLib.build_filenamev([dir, filename]);
|
||||
if (GLib.file_test(path, GLib.FileTest.EXISTS))
|
||||
return false;
|
||||
let success = GLib.file_set_contents(path, content);
|
||||
|
||||
if (success) {
|
||||
if (Files.saveSvg(content)) {
|
||||
// pass the parent (bgContainer) to Flashspot because coords of this are relative
|
||||
let flashspot = new Screenshot.Flashspot(this.get_parent());
|
||||
flashspot.fire();
|
||||
|
|
@ -1149,7 +1142,7 @@ var DrawingArea = new Lang.Class({
|
|||
}
|
||||
},
|
||||
|
||||
_saveAsJson: function(name, notify, callback) {
|
||||
_saveAsJson: function(json, notify, callback) {
|
||||
// stop drawing or writing
|
||||
if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) {
|
||||
this._stopWriting();
|
||||
|
|
@ -1157,46 +1150,31 @@ var DrawingArea = new Lang.Class({
|
|||
this._stopDrawing();
|
||||
}
|
||||
|
||||
let json = new Files.Json({ name });
|
||||
let oldContents;
|
||||
|
||||
if (name == Me.metadata['persistent-file-name']) {
|
||||
let oldContents = json.contents;
|
||||
// do not create a file to write just an empty array
|
||||
if (!oldContents && this.elements.length == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// do not use "content = JSON.stringify(this.elements, null, 2);", neither "content = JSON.stringify(this.elements);"
|
||||
// do compromise between disk usage and human readability
|
||||
let contents = `[\n ` + new Array(...this.elements.map(element => JSON.stringify(element))).join(`,\n\n `) + `\n]`;
|
||||
|
||||
if (name == Me.metadata['persistent-file-name'] && contents == oldContents)
|
||||
return;
|
||||
let contents = this.elements.length ? `[\n ` + new Array(...this.elements.map(element => JSON.stringify(element))).join(`,\n\n `) + `\n]` : '[]';
|
||||
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
||||
json.contents = contents;
|
||||
if (notify)
|
||||
this.emit('show-osd', Files.Icons.SAVE, name, "", -1, false);
|
||||
if (name != Me.metadata['persistent-file-name']) {
|
||||
this.jsonName = name;
|
||||
this.lastJsonContents = contents;
|
||||
}
|
||||
this.emit('show-osd', Files.Icons.SAVE, json.name, "", -1, false);
|
||||
if (!json.isPersistent)
|
||||
this.currentJson = json;
|
||||
if (callback)
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
saveAsJsonWithName: function(name, callback) {
|
||||
this._saveAsJson(name, false, callback);
|
||||
this._saveAsJson(Files.Jsons.getNamed(name), false, callback);
|
||||
},
|
||||
|
||||
saveAsJson: function() {
|
||||
this._saveAsJson(Files.getDateString(), true);
|
||||
this._saveAsJson(Files.Jsons.getDated(), true);
|
||||
},
|
||||
|
||||
savePersistent: function() {
|
||||
this._saveAsJson(Me.metadata['persistent-file-name']);
|
||||
this._saveAsJson(Files.Jsons.getPersistent());
|
||||
},
|
||||
|
||||
syncPersistent: function() {
|
||||
|
|
@ -1208,7 +1186,7 @@ var DrawingArea = new Lang.Class({
|
|||
|
||||
},
|
||||
|
||||
_loadJson: function(name, notify) {
|
||||
_loadJson: function(json, notify) {
|
||||
// stop drawing or writing
|
||||
if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) {
|
||||
this._stopWriting();
|
||||
|
|
@ -1218,56 +1196,45 @@ var DrawingArea = new Lang.Class({
|
|||
this.elements = [];
|
||||
this.currentElement = null;
|
||||
|
||||
let contents = (new Files.Json({ name })).contents;
|
||||
if (!contents)
|
||||
if (!json.contents)
|
||||
return;
|
||||
|
||||
this.elements.push(...JSON.parse(contents).map(object => {
|
||||
this.elements.push(...JSON.parse(json.contents).map(object => {
|
||||
if (object.image)
|
||||
object.image = new Files.Image(object.image);
|
||||
return new Elements.DrawingElement(object);
|
||||
}));
|
||||
|
||||
if (notify)
|
||||
this.emit('show-osd', Files.Icons.OPEN, name, "", -1, false);
|
||||
if (name != Me.metadata['persistent-file-name']) {
|
||||
this.jsonName = name;
|
||||
this.lastJsonContents = contents;
|
||||
}
|
||||
this.emit('show-osd', Files.Icons.OPEN, json.name, "", -1, false);
|
||||
if (!json.isPersistent)
|
||||
this.currentJson = json;
|
||||
},
|
||||
|
||||
_loadPersistent: function() {
|
||||
this._loadJson(Me.metadata['persistent-file-name']);
|
||||
this._loadJson(Files.Jsons.getPersistent());
|
||||
},
|
||||
|
||||
loadJson: function(name, notify) {
|
||||
this._loadJson(name, notify);
|
||||
loadJson: function(json, notify) {
|
||||
this._loadJson(json, notify);
|
||||
this._redisplay();
|
||||
},
|
||||
|
||||
loadPreviousJson: function() {
|
||||
let names = Files.getJsons().map(json => json.name);
|
||||
|
||||
if (!names.length)
|
||||
return;
|
||||
|
||||
let previousName = names[this.jsonName && names.indexOf(this.jsonName) != names.length - 1 ? names.indexOf(this.jsonName) + 1 : 0];
|
||||
this.loadJson(previousName, true);
|
||||
let json = Files.Jsons.getPrevious(this.currentJson || null);
|
||||
if (json)
|
||||
this.loadJson(json, true);
|
||||
},
|
||||
|
||||
loadNextJson: function() {
|
||||
let names = Files.getJsons().map(json => json.name);
|
||||
|
||||
if (!names.length)
|
||||
return;
|
||||
|
||||
let nextName = names[this.jsonName && names.indexOf(this.jsonName) > 0 ? names.indexOf(this.jsonName) - 1 : names.length - 1];
|
||||
this.loadJson(nextName, true);
|
||||
let json = Files.Jsons.getNext(this.currentJson || null);
|
||||
if (json)
|
||||
this.loadJson(json, true);
|
||||
},
|
||||
|
||||
get drawingContentsHasChanged() {
|
||||
let contents = `[\n ` + new Array(...this.elements.map(element => JSON.stringify(element))).join(`,\n\n `) + `\n]`;
|
||||
return contents != this.lastJsonContents;
|
||||
return contents != (this.currentJson && this.currentJson.contents);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -524,6 +524,8 @@ const AreaManager = new Lang.Class({
|
|||
Main.wm.removeKeybinding('toggle-modal');
|
||||
Main.wm.removeKeybinding('erase-drawings');
|
||||
this.removeAreas();
|
||||
Files.Images.disable();
|
||||
Files.Jsons.disable();
|
||||
if (this.indicator)
|
||||
this.indicator.disable();
|
||||
}
|
||||
|
|
|
|||
199
files.js
199
files.js
|
|
@ -1,5 +1,5 @@
|
|||
/* jslint esversion: 6 */
|
||||
/* exported Icons, Image, Images, Json, getJsons, getDateString */
|
||||
/* exported Icons, Image, Images, Json, Jsons, getDateString, saveSvg */
|
||||
|
||||
/*
|
||||
* Copyright 2019 Abakkk
|
||||
|
|
@ -205,6 +205,12 @@ var Images = {
|
|||
_clipboardImages: [],
|
||||
_upToDate: false,
|
||||
|
||||
disable: function() {
|
||||
this._images = [];
|
||||
this._clipboardImages = [];
|
||||
this._upToDate = false;
|
||||
},
|
||||
|
||||
_clipboardImagesContains: function(file) {
|
||||
return this._clipboardImages.some(image => image.file.equal(file));
|
||||
},
|
||||
|
|
@ -265,7 +271,7 @@ var Images = {
|
|||
let file = this.enumerator.get_child(info);
|
||||
|
||||
if (info.get_content_type().indexOf('image') == 0 && !clipboardImagesContains(file)) {
|
||||
let image = oldImages.find(image => image.file.equal(file)) || new ImageWithGicon({ file, info });
|
||||
let image = oldImages.find(oldImage => oldImage.file.equal(file)) || new ImageWithGicon({ file, info });
|
||||
newImages.push(image);
|
||||
return { value: image, done: false };
|
||||
} else {
|
||||
|
|
@ -287,7 +293,7 @@ var Images = {
|
|||
|
||||
getPrevious: function(currentImage) {
|
||||
let images = this.getSorted();
|
||||
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0;
|
||||
let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : -1;
|
||||
return images[index <= 0 ? images.length - 1 : index - 1] || null;
|
||||
},
|
||||
|
||||
|
|
@ -333,6 +339,10 @@ var Json = new Lang.Class({
|
|||
this[key] = params[key];
|
||||
},
|
||||
|
||||
get isPersistent() {
|
||||
return this.name == Me.metadata['persistent-file-name'];
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return this.displayName || this.name;
|
||||
},
|
||||
|
|
@ -342,10 +352,10 @@ var Json = new Lang.Class({
|
|||
},
|
||||
|
||||
get file() {
|
||||
if (!this._file && this.name)
|
||||
if (!this._file)
|
||||
this._file = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir'], `${this.name}.json`]));
|
||||
|
||||
return this._file || null;
|
||||
return this._file;
|
||||
},
|
||||
|
||||
set file(file) {
|
||||
|
|
@ -353,62 +363,167 @@ var Json = new Lang.Class({
|
|||
},
|
||||
|
||||
get contents() {
|
||||
let success_, contents;
|
||||
try {
|
||||
[success_, contents] = this.file.load_contents(null);
|
||||
if (contents instanceof Uint8Array)
|
||||
contents = ByteArray.toString(contents);
|
||||
} catch(e) {
|
||||
return null;
|
||||
if (this._contents === undefined) {
|
||||
try {
|
||||
[, this._contents] = this.file.load_contents(null);
|
||||
if (this._contents instanceof Uint8Array)
|
||||
this._contents = ByteArray.toString(this._contents);
|
||||
} catch(e) {
|
||||
this._contents = null;
|
||||
}
|
||||
}
|
||||
return contents;
|
||||
|
||||
return this._contents;
|
||||
},
|
||||
|
||||
set contents(contents) {
|
||||
if (this.isPersistent && (this.contents == contents || !this.contents && contents == '[]'))
|
||||
return;
|
||||
|
||||
try {
|
||||
this.file.replace_contents(contents, null, false, Gio.FileCreateFlags.NONE, null);
|
||||
} catch(e) {
|
||||
this.file.get_parent().make_directory_with_parents(null);
|
||||
this.file.replace_contents(contents, null, false, Gio.FileCreateFlags.NONE, null);
|
||||
}
|
||||
|
||||
this._contents = contents;
|
||||
}
|
||||
});
|
||||
|
||||
var getJsons = function() {
|
||||
let directory = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir']]));
|
||||
var Jsons = {
|
||||
_jsons: [],
|
||||
_upToDate: false,
|
||||
|
||||
let enumerator;
|
||||
try {
|
||||
enumerator = directory.enumerate_children('standard::name,standard::display-name,standard::content-type,time::modified', Gio.FileQueryInfoFlags.NONE, null);
|
||||
} catch(e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let jsons = [];
|
||||
let fileInfo = enumerator.next_file(null);
|
||||
while (fileInfo) {
|
||||
if (fileInfo.get_content_type().indexOf('json') != -1 && fileInfo.get_name() != `${Me.metadata['persistent-file-name']}.json`) {
|
||||
let file = enumerator.get_child(fileInfo);
|
||||
jsons.push(new Json({
|
||||
file,
|
||||
name: fileInfo.get_name().slice(0, -5),
|
||||
displayName: fileInfo.get_display_name().slice(0, -5),
|
||||
// fileInfo.get_modification_date_time: Gio 2.62+
|
||||
modificationUnixTime: fileInfo.get_attribute_uint64('time::modified')
|
||||
}));
|
||||
disable: function() {
|
||||
if (this._monitor) {
|
||||
this._monitor.disconnect(this._monitorHandler);
|
||||
this._monitor.cancel();
|
||||
}
|
||||
fileInfo = enumerator.next_file(null);
|
||||
|
||||
delete this._monitor;
|
||||
delete this._persistent;
|
||||
|
||||
this._jsons = [];
|
||||
this._upToDate = false;
|
||||
},
|
||||
|
||||
_updateMonitor: function() {
|
||||
if (this._monitor)
|
||||
return;
|
||||
|
||||
let directory = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir']]));
|
||||
this._monitor = directory.monitor(Gio.FileMonitorFlags.NONE, null);
|
||||
this._monitorHandler = this._monitor.connect('changed', (monitor, file) => {
|
||||
if (file.get_basename() != `${Me.metadata['persistent-file-name']}.json` && file.get_basename().indexOf('.goutputstream'))
|
||||
this.reset();
|
||||
});
|
||||
},
|
||||
|
||||
[Symbol.iterator]: function() {
|
||||
if (this._upToDate)
|
||||
return this._jsons[Symbol.iterator]();
|
||||
|
||||
this._updateMonitor();
|
||||
this._upToDate = true;
|
||||
let newJsons = this._jsons = [];
|
||||
|
||||
return {
|
||||
get enumerator() {
|
||||
if (this._enumerator === undefined) {
|
||||
try {
|
||||
let directory = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir']]));
|
||||
this._enumerator = directory.enumerate_children('standard::name,standard::display-name,standard::content-type,time::modified', Gio.FileQueryInfoFlags.NONE, null);
|
||||
} catch(e) {
|
||||
this._enumerator = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this._enumerator;
|
||||
},
|
||||
|
||||
next: function() {
|
||||
if (!this.enumerator || this.enumerator.is_closed())
|
||||
return { done: true };
|
||||
|
||||
let info = this.enumerator.next_file(null);
|
||||
if (!info) {
|
||||
this.enumerator.close(null);
|
||||
return this.next();
|
||||
}
|
||||
|
||||
let file = this.enumerator.get_child(info);
|
||||
|
||||
if (info.get_content_type().indexOf('json') != -1 && info.get_name() != `${Me.metadata['persistent-file-name']}.json`) {
|
||||
let json = new Json({
|
||||
file, name: info.get_name().slice(0, -5),
|
||||
displayName: info.get_display_name().slice(0, -5),
|
||||
// info.get_modification_date_time: Gio 2.62+
|
||||
modificationUnixTime: info.get_attribute_uint64('time::modified')
|
||||
});
|
||||
|
||||
newJsons.push(json);
|
||||
return { value: json, done: false };
|
||||
} else {
|
||||
return this.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getSorted: function() {
|
||||
return [...this].sort((a, b) => b.modificationUnixTime - a.modificationUnixTime);
|
||||
},
|
||||
|
||||
getNext: function(currentJson) {
|
||||
let jsons = this.getSorted();
|
||||
let index = currentJson ? jsons.findIndex(json => json.name == currentJson.name) : -1;
|
||||
return jsons[index == jsons.length - 1 ? 0 : index + 1] || null;
|
||||
},
|
||||
|
||||
getPrevious: function(currentJson) {
|
||||
let jsons = this.getSorted();
|
||||
let index = currentJson ? jsons.findIndex(json => json.name == currentJson.name) : -1;
|
||||
return jsons[index <= 0 ? jsons.length - 1 : index - 1] || null;
|
||||
},
|
||||
|
||||
getPersistent: function() {
|
||||
if (!this._persistent)
|
||||
this._persistent = new Json({ name: Me.metadata['persistent-file-name'] });
|
||||
|
||||
return this._persistent;
|
||||
},
|
||||
|
||||
getDated: function() {
|
||||
return new Json({ name: getDateString() });
|
||||
},
|
||||
|
||||
getNamed: function(name) {
|
||||
return [...this].find(json => json.name == name) || new Json({ name });
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this._upToDate = false;
|
||||
}
|
||||
enumerator.close(null);
|
||||
|
||||
jsons.sort((a, b) => {
|
||||
return b.modificationUnixTime - a.modificationUnixTime;
|
||||
});
|
||||
|
||||
return jsons;
|
||||
};
|
||||
|
||||
var getDateString = function() {
|
||||
let date = GLib.DateTime.new_now_local();
|
||||
return `${date.format("%F")} ${date.format("%X")}`;
|
||||
};
|
||||
|
||||
var saveSvg = function(content) {
|
||||
let filename = `${Me.metadata['svg-file-name']} ${getDateString()}.svg`;
|
||||
let dir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES);
|
||||
let path = GLib.build_filenamev([dir, filename]);
|
||||
let file = Gio.File.new_for_path(path);
|
||||
if (file.query_exists(null))
|
||||
return false;
|
||||
|
||||
try {
|
||||
return file.replace_contents(content, null, false, Gio.FileCreateFlags.NONE, null);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
12
menu.js
12
menu.js
|
|
@ -562,10 +562,10 @@ var DrawingMenu = new Lang.Class({
|
|||
},
|
||||
|
||||
_updateDrawingNameMenuItem: function() {
|
||||
getActor(this.drawingNameMenuItem).visible = this.area.jsonName ? true : false;
|
||||
if (this.area.jsonName) {
|
||||
getActor(this.drawingNameMenuItem).visible = this.area.currentJson ? true : false;
|
||||
if (this.area.currentJson) {
|
||||
let prefix = this.area.drawingContentsHasChanged ? "* " : "";
|
||||
this.drawingNameMenuItem.label.set_text(`<i>${prefix}${this.area.jsonName}</i>`);
|
||||
this.drawingNameMenuItem.label.set_text(`<i>${prefix}${this.area.currentJson.name}</i>`);
|
||||
this.drawingNameMenuItem.label.get_clutter_text().set_use_markup(true);
|
||||
}
|
||||
},
|
||||
|
|
@ -574,7 +574,7 @@ var DrawingMenu = new Lang.Class({
|
|||
let item = new PopupMenu.PopupSubMenuMenuItem(_("Open drawing"), true);
|
||||
this.openDrawingSubMenuItem = item;
|
||||
this.openDrawingSubMenu = item.menu;
|
||||
item.setSensitive(Boolean(Files.getJsons().length));
|
||||
item.setSensitive(Boolean(Files.Jsons.getSorted().length));
|
||||
item.icon.set_gicon(icon);
|
||||
|
||||
item.menu.itemActivated = item.menu.close;
|
||||
|
|
@ -591,10 +591,10 @@ var DrawingMenu = new Lang.Class({
|
|||
|
||||
_populateOpenDrawingSubMenu: function() {
|
||||
this.openDrawingSubMenu.removeAll();
|
||||
let jsons = Files.getJsons();
|
||||
let jsons = Files.Jsons.getSorted();
|
||||
jsons.forEach(json => {
|
||||
let subItem = this.openDrawingSubMenu.addAction(`<i>${String(json)}</i>`, () => {
|
||||
this.area.loadJson(json.name);
|
||||
this.area.loadJson(json);
|
||||
this._updateDrawingNameMenuItem();
|
||||
this._updateSaveDrawingSubMenuItemSensitivity();
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue