[gnome-sound-recorder] recording list: split into a ListModel & UI



commit 9dd7da5eed1432d8999df1f3cfa02d60951ee449
Author: Kavan Mevada <kavanmevada gmail com>
Date:   Wed Apr 8 22:04:40 2020 +0000

    recording list: split into a ListModel & UI

 data/ui/infodialog.ui                            |   6 +-
 data/ui/window.ui                                | 120 +++++++-
 src/info.js                                      |  21 +-
 src/listview.js                                  | 338 -----------------------
 src/mainWindow.js                                | 191 ++++---------
 src/org.gnome.SoundRecorder.src.gresource.xml.in |   3 +-
 src/record.js                                    |   3 +-
 src/recording.js                                 |  82 ++++++
 src/recordingList.js                             |  78 ++++++
 src/row.js                                       |  22 +-
 src/utils.js                                     |  44 ++-
 src/waveform.js                                  |   5 +-
 12 files changed, 374 insertions(+), 539 deletions(-)
---
diff --git a/data/ui/infodialog.ui b/data/ui/infodialog.ui
index e94f1c4..2e38829 100644
--- a/data/ui/infodialog.ui
+++ b/data/ui/infodialog.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Generated with glade 3.22.0 -->
 <interface>
-  <requires lib="gtk+" version="3.10"/>
+  <requires lib="gtk+" version="3.12"/>
   <template class="Gjs_InfoDialog" parent="GtkWindow">
     <property name="can_focus">False</property>
     <property name="modal">True</property>
@@ -72,7 +72,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkLabel">
+              <object class="GtkLabel" id="dateCreatedLabel">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="halign">end</property>
@@ -136,7 +136,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkLabel" id="dateCreatedLabel">
+              <object class="GtkLabel" id="dateCreatedValueLabel">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="halign">start</property>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 098d6b7..ffda6ff 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -15,16 +15,119 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <child>
-          <object class="GtkGrid" id="mainView">
+          <object class="GtkGrid">
+            <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkListBox" id="listBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="recordGrid">
+                <property name="can_focus">False</property>
+                <property name="margin_start">18</property>
+                <property name="margin_end">18</property>
+                <property name="margin_top">18</property>
+                <property name="margin_bottom">18</property>
+                <property name="hexpand">True</property>
+                <child>
+                  <object class="GtkButton" id="recordStopButton">
+                    <property name="label" translatable="yes">Done</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="halign">center</property>
+                    <property name="valign">center</property>
+                    <property name="margin_left">6</property>
+                    <property name="margin_start">18</property>
+                    <property name="margin_top">6</property>
+                    <property name="margin_bottom">4</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="box-record">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="valign">center</property>
+                    <property name="margin_end">18</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_bottom">8</property>
+                        <property name="label" translatable="yes">Recording</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="recordTimeLabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
           </object>
           <packing>
-            <property name="position">0</property>
+            <property name="name">mainView</property>
           </packing>
         </child>
         <child>
-          <object class="GtkGrid" id="emptyView">
+          <object class="GtkGrid">
+            <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="hexpand">True</property>
             <property name="vexpand">True</property>
@@ -38,6 +141,7 @@
                 <property name="vexpand">True</property>
                 <child>
                   <object class="GtkImage">
+                    <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="halign">center</property>
                     <property name="valign">center</property>
@@ -54,6 +158,7 @@
                 </child>
                 <child>
                   <object class="GtkLabel">
+                    <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label" translatable="yes">Use the &lt;b&gt;Record&lt;/b&gt; button to 
make sound recordings</property>
                     <property name="use_markup">True</property>
@@ -69,6 +174,7 @@
                 </child>
                 <child>
                   <object class="GtkLabel">
+                    <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label" translatable="yes">Add Recordings</property>
                     <style>
@@ -88,18 +194,20 @@
             </child>
           </object>
           <packing>
+            <property name="name">emptyView</property>
             <property name="position">1</property>
           </packing>
         </child>
-    </object>
-  </child>
+      </object>
+    </child>
     <child type="titlebar">
       <object class="GtkHeaderBar" id="headerBar">
+        <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="title" translatable="yes">Sound Recorder</property>
         <property name="show_close_button">True</property>
         <child>
-          <object class="GtkButton" id="recordButton">
+          <object class="GtkButton" id="recordStartButton">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
diff --git a/src/info.js b/src/info.js
index 025a0ad..90dc799 100644
--- a/src/info.js
+++ b/src/info.js
@@ -23,31 +23,32 @@ const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
 const GObject = imports.gi.GObject;
+const Utils = imports.utils;
 
 
 var InfoDialog = GObject.registerClass({ // eslint-disable-line no-unused-vars
     Template: 'resource:///org/gnome/SoundRecorder/ui/infodialog.ui',
-    InternalChildren: ['cancelBtn', 'doneBtn', 'fileNameEntry', 'sourceLabel', 'dateModifiedLabel', 
'dateModifiedValueLabel', 'dateCreatedLabel', 'mediaTypeLabel'],
+    InternalChildren: ['cancelBtn', 'doneBtn', 'fileNameEntry', 'sourceLabel', 'dateModifiedValueLabel', 
'dateCreatedLabel', 'dateCreatedValueLabel', 'mediaTypeLabel'],
 }, class InfoDialog extends Gtk.Window {
-    _init(file) {
-        this._file = Gio.File.new_for_uri(file.uri);
+    _init(recording) {
+        this._file = Gio.File.new_for_uri(recording.uri);
 
         super._init({ transient_for: Gio.Application.get_default().get_active_window() });
 
-        this._fileNameEntry.text = file.fileName;
+        this._fileNameEntry.text = recording.name;
 
         // Source value
         this._sourceLabel.label = this._file.get_parent().get_path();
 
-        if (file.dateModified !== null) {
-            this._dateModifiedValueLabel.label = file.dateModified;
+        if (recording.timeCreated > 0) {
+            this._dateCreatedValueLabel.label = Utils.Time.getDisplayTime(recording.timeCreated);
         } else {
-            this._dateModifiedValueLabel.destroy();
-            this._dateModifiedLabel.destroy();
+            this._dateCreatedValueLabel.destroy();
+            this._dateCreatedLabel.destroy();
         }
 
-        this._dateCreatedLabel.label = file.dateCreated;
-        this._mediaTypeLabel.label = file.mediaType || _('Unknown');
+        this._dateModifiedValueLabel.label = Utils.Time.getDisplayTime(recording.timeModified);
+        this._mediaTypeLabel.label = recording.mimeType || _('Unknown');
 
         this._cancelBtn.connect('clicked', () => {
             this.destroy();
diff --git a/src/mainWindow.js b/src/mainWindow.js
index ba57453..5929964 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -25,10 +25,10 @@ const Gio = imports.gi.Gio;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 
-const Settings = imports.preferences.settings;
 const AudioProfile = imports.audioProfile;
 const Utils = imports.utils;
-const Listview = imports.listview;
+const RecordingList = imports.recordingList.RecordingList;
+const Recording = imports.recording.Recording;
 const Row = imports.row.Row;
 const RowState = imports.row.RowState;
 const Player = imports.player.Player;
@@ -38,7 +38,6 @@ const Waveform = imports.waveform;
 let activeProfile = null;
 var audioProfile = null;
 var displayTime = null;
-var list = null;
 var player = null;
 var recordPipeline = null;
 var view = null;
@@ -51,23 +50,43 @@ var ActiveArea = {
 
 var MainWindow = GObject.registerClass({
     Template: 'resource:///org/gnome/SoundRecorder/ui/window.ui',
-    InternalChildren: ['recordButton', 'appMenuButton', 'mainStack', 'mainView', 'emptyView'],
+    InternalChildren: ['recordStartButton', 'recordStopButton', 'recordTimeLabel', 'appMenuButton', 
'mainStack', 'recordGrid', 'listBox'],
 }, class MainWindow extends Gtk.ApplicationWindow {
 
     _init(params) {
-        audioProfile = new AudioProfile.AudioProfile();
-        displayTime = new Utils.DisplayTime();
-        view = this;
-        this._addListviewPage();
-        player = new Player();
-
         super._init(Object.assign({
             icon_name: pkg.name,
         }, params));
 
-        this._recordButton.connect('clicked', () => this._onRecord());
+        audioProfile = new AudioProfile.AudioProfile();
+        this._record = new Record.Record(audioProfile);
+        player = new Player();
+        view = this;
+
+        this._recordingList = new RecordingList();
+        this._refreshView();
+        this._recordingList.connect('items-changed', this._refreshView.bind(this));
+
+        this._listBox.bind_model(this._recordingList, recording => {
+            let row = new Row(recording);
+            row.connect('play', currentRow => {
+                this._listBox.get_children().forEach(_row => {
+                    if (_row !== currentRow)
+                        _row.setState(RowState.PAUSED);
+                });
+                player.startPlaying(recording.uri);
+            });
+
+            row.connect('pause', () => player.pausePlaying());
+            row.connect('deleted', () => this._recordingList.remove(row.get_index()));
+
+            return row;
+        });
+
+        this._recordStartButton.connect('clicked', () => this._onRecordStart());
+        this._recordStopButton.connect('clicked', () => this._onRecordStop());
         this._addAppMenu();
-        this.show_all();
+        this.show();
     }
 
     _addAppMenu() {
@@ -77,150 +96,42 @@ var MainWindow = GObject.registerClass({
         this._appMenuButton.set_menu_model(menu);
     }
 
-    _onRecord() {
-        if (view.listBox)
-            view.listBox.set_selection_mode(Gtk.SelectionMode.NONE);
-        else
-            this._mainStack.set_visible_child(this._mainView);
-
-        this._recordButton.set_sensitive(false);
-        view.recordGrid.show_all();
+    _onRecordStart() {
+        player.stopPlaying();
+        this._mainStack.set_visible_child_name('mainView');
+        this._recordGrid.show();
 
         if (activeProfile === null)
             activeProfile = 0;
 
         audioProfile.profile(activeProfile);
-        view._record.startRecording(activeProfile);
-        wave = new Waveform.WaveForm(view.recordGrid, null);
-    }
+        this._record.startRecording(activeProfile);
 
-    _addListviewPage() {
-        list = new Listview.Listview();
-        list.setListTypeNew();
-        list.enumerateDirectory();
-        this._record = new Record.Record(audioProfile);
+        wave = new Waveform.WaveForm(this._recordGrid, null);
     }
 
-    onRecordStopClicked() {
+    _onRecordStop() {
         Record.pipeState = Record.PipelineStates.STOPPED;
         this._record.stopRecording();
-        this.recordGrid.hide();
-        this._recordButton.set_sensitive(true);
-        wave = null;
-    }
-
-    _updatePositionCallback() {
-        let position = player.queryPosition();
-
-        if (position >= 0)
-            this.progressScale.set_value(position);
-
-        return true;
-    }
-
-    listBoxAdd() {
-        activeProfile = Settings.mediaCodec;
-
-        this.recordGrid = new Gtk.Grid({ name: 'recordGrid',
-            orientation: Gtk.Orientation.HORIZONTAL });
-        this._mainView.add(this.recordGrid);
-
-        this.widgetRecord = new Gtk.Toolbar({ show_arrow: false,
-            halign: Gtk.Align.END,
-            valign: Gtk.Align.FILL,
-            icon_size: Gtk.IconSize.BUTTON,
-            opacity: 1 });
-        this.recordGrid.attach(this.widgetRecord, 0, 0, 2, 2);
-
-        this._boxRecord = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
-        this._groupRecord = new Gtk.ToolItem({ child: this._boxRecord });
-        this.widgetRecord.insert(this._groupRecord, -1);
-
-        this.recordTextLabel = new Gtk.Label({ margin_bottom: 4,
-            margin_end: 6,
-            margin_start: 6,
-            margin_top: 6 });
-        this.recordTextLabel.label = _('Recording…');
-        this._boxRecord.pack_start(this.recordTextLabel, false, true, 0);
-
-        this.recordTimeLabel = new Gtk.Label({ margin_bottom: 4,
-            margin_end: 6,
-            margin_start: 6,
-            margin_top: 6 });
-
-        this._boxRecord.pack_start(this.recordTimeLabel, false, true, 0);
-
-        this.toolbarStart = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, expand: false });
-        this.toolbarStart.get_style_context().add_class(Gtk.STYLE_CLASS_LINKED);
-
-        // finish button (stop recording)
-        let stopRecord = new Gtk.Button({ label: _('Done'),
-            halign: Gtk.Align.FILL,
-            valign: Gtk.Align.CENTER,
-            hexpand: true,
-            margin_bottom: 4,
-            margin_end: 6,
-            margin_start: 6,
-            margin_top: 6 });
-        stopRecord.get_style_context().add_class('text-button');
-        stopRecord.connect('clicked', () => this.onRecordStopClicked());
-        this.toolbarStart.pack_start(stopRecord, true, true, 0);
-        this.recordGrid.attach(this.toolbarStart, 5, 1, 2, 2);
-    }
+        this._recordGrid.hide();
 
-    scrolledWinAdd() {
-        this._scrolledWin = new Gtk.ScrolledWindow({ vexpand: true });
-        this._scrolledWin.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
-        this.scrollbar = this._scrolledWin.get_vadjustment();
-
-        this._mainView.add(this._scrolledWin);
-        this._scrolledWin.show();
-
-        this.listBox = null;
-
-        if (list.getItemCount() === 0) {
-            this._scrolledWin.get_style_context().add_class('emptyGrid');
-            this._mainStack.set_visible_child(this._emptyView);
-        } else {
-            this.listBox = new Gtk.ListBox({ vexpand: true });
-            this._scrolledWin.add(this.listBox);
-            this.listBox.set_selection_mode(Gtk.SelectionMode.SINGLE);
-            this.listBox.set_header_func(null);
-            this.listBox.set_activate_on_single_click(true);
-            this.listBox.show();
-
-            this._files = [];
-            this._files = list.getFilesInfoForList();
-
-            this._files.forEach(file => {
-                let row = new Row(file);
-                row.connect('play', (playingRow, fileUri) => {
-                    this.listBox.get_children().forEach(_row => {
-                        if (_row !== playingRow)
-                            _row.setState(RowState.PAUSED);
-                    });
-                    player.startPlaying(fileUri);
-                });
-                row.connect('pause', () => player.pausePlaying());
-                this.listBox.add(row);
-            });
-        }
-        list.monitorListview();
-    }
+        let fileUri = this._record.initialFileName;
+        let recordedFile = Gio.file_new_for_path(fileUri);
+        let recording = new Recording(recordedFile);
+        this._recordingList.insert(0, recording);
 
-    listBoxRefresh() {
-        list.setListTypeRefresh();
-        list.enumerateDirectory();
+        wave = null;
     }
 
-    scrolledWinDelete() {
-        this._scrolledWin.destroy();
-        this.scrolledWinAdd();
+    _refreshView() {
+        if (this._recordingList.get_n_items() === 0)
+            this._mainStack.set_visible_child_name('emptyView');
+        else
+            this._mainStack.set_visible_child_name('mainView');
     }
 
     setRecordTimeLabel(time) {
-        this.timeLabelString = Utils.StringUtils.formatTime(time);
-        this.recordTimeLabel.label = this.timeLabelString;
-        this.recordTimeLabel.get_style_context().add_class('dim-label');
+        let timeLabelString = Utils.Time.formatTime(time);
+        this._recordTimeLabel.label = timeLabelString;
     }
 });
diff --git a/src/org.gnome.SoundRecorder.src.gresource.xml.in 
b/src/org.gnome.SoundRecorder.src.gresource.xml.in
index 32ce3fe..988ddb7 100644
--- a/src/org.gnome.SoundRecorder.src.gresource.xml.in
+++ b/src/org.gnome.SoundRecorder.src.gresource.xml.in
@@ -5,7 +5,8 @@
     <file>audioProfile.js</file>
     <file>utils.js</file>
     <file>info.js</file>
-    <file>listview.js</file>
+    <file>recordingList.js</file>
+    <file>recording.js</file>
     <file>row.js</file>
     <file>main.js</file>
     <file>mainWindow.js</file>
diff --git a/src/record.js b/src/record.js
index cc547c5..8903b95 100644
--- a/src/record.js
+++ b/src/record.js
@@ -54,7 +54,6 @@ var Record = class Record {
     _recordPipeline() {
         errorDialogState = ErrState.OFF;
         this.baseTime = 0;
-        this._view = MainWindow.view;
         this._buildFileName = new BuildFileName();
         this.initialFileName = this._buildFileName.buildInitialFilename();
         let localDateTime = this._buildFileName.getOrigin();
@@ -148,7 +147,7 @@ var Record = class Record {
         let time = this.pipeline.query_position(Gst.Format.TIME)[1] / Gst.SECOND;
 
         if (time >= 0)
-            this._view.setRecordTimeLabel(time, 0);
+            MainWindow.view.setRecordTimeLabel(time, 0);
 
 
         return true;
diff --git a/src/recording.js b/src/recording.js
new file mode 100644
index 0000000..988da51
--- /dev/null
+++ b/src/recording.js
@@ -0,0 +1,82 @@
+const GLib = imports.gi.GLib;
+const Gst = imports.gi.Gst;
+const GObject = imports.gi.GObject;
+const GstPbutils = imports.gi.GstPbutils;
+
+
+var Recording = new GObject.registerClass({  // eslint-disable-line no-unused-vars
+    Properties: {
+        'duration': GObject.ParamSpec.int(
+            'duration',
+            'Recording Duration', 'Recording duration in seconds',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+            0, GLib.MAXINT, 0),
+
+        'mime-type': GObject.ParamSpec.string(
+            'mime-type',
+            'Recording Audio Codec', 'Recording audio codec type',
+            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, ''),
+    },
+}, class Recording extends GObject.Object {
+    _init(file) {
+        super._init({});
+        this._file = file;
+
+        this._name = file.get_basename();
+
+        let info = file.query_info('time::created,time::modified', 0, null);
+
+        let timeModified = info.get_attribute_uint64('time::modified');
+        let timeCreated = info.get_attribute_uint64('time::created');
+        this._timeModified = GLib.DateTime.new_from_unix_local(timeModified);
+        this._timeCreated = GLib.DateTime.new_from_unix_local(timeCreated);
+
+        var discoverer = new GstPbutils.Discoverer();
+        discoverer.start();
+        discoverer.connect('discovered', (_discoverer, audioInfo) => {
+            this._duration = audioInfo.get_duration()  / Gst.SECOND;
+            this.notify('duration');
+
+            let stream = audioInfo.get_audio_streams()[0];
+            if (stream) {
+                this._mimeType = stream.get_caps().to_string().split(', ')[0];
+                this.notify('mime-type');
+            }
+        });
+
+        discoverer.discover_uri_async(this.uri);
+    }
+
+    get name() {
+        return this._name;
+    }
+
+    get timeModified() {
+        return this._timeModified;
+    }
+
+    get timeCreated() {
+        return this._timeCreated;
+    }
+
+    get duration() {
+        return this._duration;
+    }
+
+    get mimeType() {
+        return this._mimeType;
+    }
+
+    get file() {
+        return this._file;
+    }
+
+    get uri() {
+        return this._file.get_uri();
+    }
+
+    delete() {
+        return this._file.trash_async(GLib.PRIORITY_DEFAULT, null, null);
+    }
+
+});
diff --git a/src/recordingList.js b/src/recordingList.js
new file mode 100644
index 0000000..2cfde79
--- /dev/null
+++ b/src/recordingList.js
@@ -0,0 +1,78 @@
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+
+const Recording = imports.recording.Recording;
+
+
+var RecordingList = new GObject.registerClass(class RecordingList extends Gio.ListStore {  // 
eslint-disable-line no-unused-vars
+    _init() {
+        super._init({ });
+        this._saveDir = Gio.Application.get_default().saveDir;
+
+        // Monitor Direcotry actions
+        let dirMonitor = this._saveDir.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null);
+        dirMonitor.connect('changed', (_dirMonitor, file1, file2, eventType) => {
+            // Monitor if file action done on _saveDir
+            let index = this.getIndex(file1);
+
+            switch (eventType) {
+            case Gio.FileMonitorEvent.DELETED:
+                if (Gio.Application.get_default().saveDir.equal(file1)) {
+                    Gio.Application.get_default().ensureDirectory();
+                    this._saveDir = Gio.Application.get_default().saveDir;
+                }
+                break;
+            case Gio.FileMonitorEvent.MOVED_OUT:
+                if (index >= 0)
+                    this.remove(index);
+                break;
+            case Gio.FileMonitorEvent.MOVED_IN:
+                if (index === -1)
+                    this.insert(0, new Recording(file1));
+                break;
+            }
+
+        });
+        this._watchDir();
+    }
+
+    _watchDir() {
+        this._saveDir.enumerate_children_async('standard::name',
+            Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+            GLib.PRIORITY_LOW,
+            null,
+            (obj, res) => this._enumerateDirectory(obj, res));
+    }
+
+
+    _enumerateDirectory(obj, res) {
+        this._enumerator = obj.enumerate_children_finish(res);
+
+        if (this._enumerator === null) {
+            log('The contents of the Recordings directory were not indexed.');
+        } else {
+            this._enumerator.next_files_async(20, GLib.PRIORITY_DEFAULT, null, (_obj, _res) => {
+                let fileInfos = _obj.next_files_finish(_res);
+                if (fileInfos.length > 0) {
+                    fileInfos.forEach(info => {
+                        let path = GLib.build_filenamev([this._saveDir.get_path(), info.get_name()]);
+                        let file = Gio.file_new_for_path(path);
+                        let recording = new Recording(file);
+                        this.append(recording);
+                    });
+                } else {
+                    this._enumerator.close(null);
+                }
+            });
+        }
+    }
+
+    getIndex(file) {
+        for (var i = 0; i < this.get_n_items(); i++) {
+            if (this.get_item(i).uri === file.get_uri())
+                return i;
+        }
+        return -1;
+    }
+});
diff --git a/src/row.js b/src/row.js
index 7d071d7..eabb151 100644
--- a/src/row.js
+++ b/src/row.js
@@ -1,8 +1,5 @@
-const Gst = imports.gi.Gst;
 const Gtk = imports.gi.Gtk;
 const GObject = imports.gi.GObject;
-const GLib = imports.gi.GLib;
-const Gio = imports.gi.Gio;
 
 var Info = imports.info;
 var Utils = imports.utils;
@@ -18,18 +15,21 @@ var Row = GObject.registerClass({ // eslint-disable-line no-unused-vars
     Signals: {
         'play': { param_types: [GObject.TYPE_STRING] },
         'pause': {},
+        'deleted': {},
     },
 }, class Row extends Gtk.ListBoxRow {
-    _init(file) {
+    _init(recording) {
         super._init({});
-        this.file = file;
 
-        this._fileNameLabel.label = file.fileName;
-        this._fileDurationLabel.label = Utils.StringUtils.formatTime(file.duration / Gst.SECOND);
+        this._fileNameLabel.label = recording.name;
+
+        recording.connect('notify::duration', () => {
+            this._fileDurationLabel.label = Utils.Time.formatTime(recording.duration);
+        });
 
         this._playButton.connect('clicked', () => {
             this.setState(RowState.PLAYING);
-            this.emit('play', this.file.uri);
+            this.emit('play', recording.uri);
         });
 
         this._pauseButton.connect('clicked', () => {
@@ -37,10 +37,10 @@ var Row = GObject.registerClass({ // eslint-disable-line no-unused-vars
             this.emit('pause');
         });
 
-        this._infoButton.connect('clicked', () => (new Info.InfoDialog(file)).show());
+        this._infoButton.connect('clicked', () => (new Info.InfoDialog(recording)).show());
         this._deleteButton.connect('clicked', () => {
-            let gioFile = Gio.File.new_for_uri(file.uri);
-            gioFile.trash_async(GLib.PRIORITY_DEFAULT, null, null);
+            recording.delete();
+            this.emit('deleted');
         });
     }
 
diff --git a/src/utils.js b/src/utils.js
index f17103f..66529a9 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -24,8 +24,26 @@ const GLib = imports.gi.GLib;
 const _TIME_DIVISOR = 60;
 
 
-var DisplayTime = class DisplayTime {
-    getDisplayTime(mtime) {
+var Time = { // eslint-disable-line no-unused-vars
+    formatTime: unformattedTime => {
+        this.unformattedTime = unformattedTime;
+        let seconds = Math.floor(this.unformattedTime);
+        let hours = parseInt(seconds / Math.pow(_TIME_DIVISOR, 2));
+        let hoursString = '';
+
+        if (hours > 10)
+            hoursString = `${hours}:`;
+        else if (hours < 10 && hours > 0)
+            hoursString = `0${hours}:`;
+
+        let minuteString = parseInt(seconds / _TIME_DIVISOR) % _TIME_DIVISOR;
+        let secondString = parseInt(seconds % _TIME_DIVISOR);
+        let timeString = `${hoursString + (minuteString < 10 ? `0${minuteString}` : 
minuteString)}:${secondString < 10 ? `0${secondString}` : secondString}`;
+
+        return timeString;
+    },
+
+    getDisplayTime: mtime => {
         let text = '';
         let DAY = 86400000000;
         let now = GLib.DateTime.new_now_local();
@@ -63,27 +81,5 @@ var DisplayTime = class DisplayTime {
                 years).format(years);
         }
         return text;
-    }
-
-};
-
-
-var StringUtils = { // eslint-disable-line no-unused-vars
-    formatTime: unformattedTime => {
-        this.unformattedTime = unformattedTime;
-        let seconds = Math.floor(this.unformattedTime);
-        let hours = parseInt(seconds / Math.pow(_TIME_DIVISOR, 2));
-        let hoursString = '';
-
-        if (hours > 10)
-            hoursString = `${hours}:`;
-        else if (hours < 10 && hours > 0)
-            hoursString = `0${hours}:`;
-
-        let minuteString = parseInt(seconds / _TIME_DIVISOR) % _TIME_DIVISOR;
-        let secondString = parseInt(seconds % _TIME_DIVISOR);
-        let timeString = `${hoursString + (minuteString < 10 ? `0${minuteString}` : 
minuteString)}:${secondString < 10 ? `0${secondString}` : secondString}`;
-
-        return timeString;
     },
 };
diff --git a/src/waveform.js b/src/waveform.js
index 68bc92e..d88c954 100644
--- a/src/waveform.js
+++ b/src/waveform.js
@@ -54,13 +54,10 @@ var WaveForm = class WaveForm {
             this.waveType = WaveType.RECORD;
         }
 
-
-
         this.drawing = Gtk.DrawingArea.new();
         if (this.waveType === WaveType.RECORD) {
-            this.drawing.set_property('valign', Gtk.Align.FILL);
             this.drawing.set_property('hexpand', true);
-            this._grid.attach(this.drawing, 2, 0, 3, 2);
+            this._grid.attach(this.drawing, 1, 0, 1, 1);
         } else {
             this.drawing.set_property('valign', Gtk.Align.FILL);
             this.drawing.set_property('hexpand', true);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]