From 11b90ecc0aefbec3a6d2c262d3bb80578d688642 Mon Sep 17 00:00:00 2001 From: abakkk Date: Wed, 5 Aug 2020 02:00:20 +0200 Subject: [PATCH] put json file stuff in files.js In the same way than image files. --- area.js | 75 +++++++--------------------------------------- files.js | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ menu.js | 13 ++++---- 3 files changed, 109 insertions(+), 70 deletions(-) diff --git a/area.js b/area.js index 0a65586..0b3ad26 100644 --- a/area.js +++ b/area.js @@ -20,7 +20,6 @@ * along with this program. If not, see . */ -const ByteArray = imports.byteArray; const Cairo = imports.cairo; const Clutter = imports.gi.Clutter; const Gio = imports.gi.Gio; @@ -57,43 +56,6 @@ var ToolNames = Object.assign({}, ShapeNames, ManipulationNames); var FontGenericNames = { 0: 'Theme', 1: 'Sans-Serif', 2: 'Serif', 3: 'Monospace', 4: 'Cursive', 5: 'Fantasy' }; -var getDateString = function() { - let date = GLib.DateTime.new_now_local(); - return `${date.format("%F")} ${date.format("%X")}`; -}; - -var getJsonFiles = function() { - let directory = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir']])); - - 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 jsonFiles = []; - 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); - jsonFiles.push({ 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'), - delete: () => file.delete(null) }); - } - fileInfo = enumerator.next_file(null); - } - enumerator.close(null); - - jsonFiles.sort((a, b) => { - return b.modificationUnixTime - a.modificationUnixTime; - }); - - return jsonFiles; -}; - // DrawingArea is the widget in which we draw, thanks to Cairo. // It creates and manages a DrawingElement for each "brushstroke". // It handles pointer/mouse/(touch?) events and some keyboard events. @@ -1092,7 +1054,7 @@ var DrawingArea = new Lang.Class({ } content += "\n"; - let filename = `${Me.metadata['svg-file-name']} ${getDateString()}.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)) @@ -1120,34 +1082,25 @@ var DrawingArea = new Lang.Class({ this._stopDrawing(); } - let dir = GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir']]); - if (!GLib.file_test(dir, GLib.FileTest.EXISTS)) - GLib.mkdir_with_parents(dir, 0o700); - let path = GLib.build_filenamev([dir, `${name}.json`]); - + let json = new Files.Json({ name }); let oldContents; if (name == Me.metadata['persistent-file-name']) { - if (GLib.file_test(path, GLib.FileTest.EXISTS)) { - oldContents = GLib.file_get_contents(path)[1]; - if (oldContents instanceof Uint8Array) - oldContents = ByteArray.toString(oldContents); - } - + 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);" - // because of compromise between disk usage and human readability + // 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; GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - GLib.file_set_contents(path, contents); + json.contents = contents; if (notify) this.emit('show-osd', 'document-save-symbolic', name, "", -1, false); if (name != Me.metadata['persistent-file-name']) { @@ -1162,7 +1115,7 @@ var DrawingArea = new Lang.Class({ }, saveAsJson: function() { - this._saveAsJson(getDateString(), true); + this._saveAsJson(Files.getDateString(), true); }, savePersistent: function() { @@ -1188,16 +1141,10 @@ var DrawingArea = new Lang.Class({ this.elements = []; this.currentElement = null; - let dir = GLib.get_user_data_dir(); - let path = GLib.build_filenamev([dir, Me.metadata['data-dir'], `${name}.json`]); + let contents = (new Files.Json({ name })).contents; + if (!contents) + return; - if (!GLib.file_test(path, GLib.FileTest.EXISTS)) - return; - let [success, contents] = GLib.file_get_contents(path); - if (!success) - return; - if (contents instanceof Uint8Array) - contents = ByteArray.toString(contents); this.elements.push(...JSON.parse(contents).map(object => { if (object.image) object.image = new Files.Image(object.image); @@ -1222,7 +1169,7 @@ var DrawingArea = new Lang.Class({ }, loadNextJson: function() { - let names = getJsonFiles().map(file => file.name); + let names = Files.getJsons().map(json => json.name); if (!names.length) return; @@ -1232,7 +1179,7 @@ var DrawingArea = new Lang.Class({ }, loadPreviousJson: function() { - let names = getJsonFiles().map(file => file.name); + let names = Files.getJsons().map(json => json.name); if (!names.length) return; diff --git a/files.js b/files.js index ec55aa7..c7bef27 100644 --- a/files.js +++ b/files.js @@ -20,6 +20,7 @@ * along with this program. If not, see . */ +const ByteArray = imports.byteArray; const Gdk = imports.gi.Gdk; const GdkPixbuf = imports.gi.GdkPixbuf; const Gio = imports.gi.Gio; @@ -31,6 +32,7 @@ const Me = ExtensionUtils.getCurrentExtension(); const EXAMPLE_IMAGES = Me.dir.get_child('data').get_child('images'); const USER_IMAGES = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir'], 'images'])); +// wrapper around an image file var Image = new Lang.Class({ Name: 'DrawOnYourScreenImage', @@ -130,3 +132,92 @@ var getImages = function() { return images; }; + +// wrapper around a json file +var Json = new Lang.Class({ + Name: 'DrawOnYourScreenJson', + + _init: function(params) { + for (let key in params) + this[key] = params[key]; + }, + + toString: function() { + return this.displayName || this.name; + }, + + delete: function() { + this.file.delete(null); + }, + + get file() { + if (!this._file && this.name) + 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; + }, + + set file(file) { + this._file = file; + }, + + 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; + } + return contents; + }, + + set contents(contents) { + 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); + } + } +}); + +var getJsons = function() { + let directory = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir']])); + + 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') + })); + } + fileInfo = enumerator.next_file(null); + } + 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")}`; +}; diff --git a/menu.js b/menu.js index a8ccba0..0a09f03 100644 --- a/menu.js +++ b/menu.js @@ -39,6 +39,7 @@ const Me = ExtensionUtils.getCurrentExtension(); const Area = Me.imports.area; const Elements = Me.imports.elements; const Extension = Me.imports.extension; +const Files = Me.imports.files; const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext; const GS_VERSION = Config.PACKAGE_VERSION; @@ -438,10 +439,10 @@ var DrawingMenu = new Lang.Class({ _populateOpenDrawingSubMenu: function() { this.openDrawingSubMenu.removeAll(); - let jsonFiles = Area.getJsonFiles(); - jsonFiles.forEach(file => { - let item = this.openDrawingSubMenu.addAction(`${file.displayName}`, () => { - this.area.loadJson(file.name); + let jsons = Files.getJsons(); + jsons.forEach(json => { + let item = this.openDrawingSubMenu.addAction(`${String(json)}`, () => { + this.area.loadJson(json.name); this._updateDrawingNameMenuItem(); this._updateSaveDrawingSubMenuItemSensitivity(); }); @@ -460,7 +461,7 @@ var DrawingMenu = new Lang.Class({ getActor(item).add_child(deleteButton); deleteButton.connect('clicked', () => { - file.delete(); + json.delete(); item.destroy(); }); }); @@ -494,7 +495,7 @@ var DrawingMenu = new Lang.Class({ _populateSaveDrawingSubMenu: function() { this.saveDrawingSubMenu.removeAll(); - let saveEntry = new DrawingMenuEntry({ initialTextGetter: Area.getDateString, + let saveEntry = new DrawingMenuEntry({ initialTextGetter: Files.getDateString, entryActivateCallback: (text) => { this.area.saveAsJsonWithName(text); this.saveDrawingSubMenu.toggle();