[gnome-sound-recorder] undo delete recording
- From: Bilal Elmoussaoui <bilelmoussaoui src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-sound-recorder] undo delete recording
- Date: Mon, 10 Aug 2020 14:13:34 +0000 (UTC)
commit 6411a90f4e5340e05c43eed9c7c80f2124db9c60
Author: Kavan Mevada <kavanmevada gmail com>
Date: Mon Aug 10 09:23:47 2020 +0530
undo delete recording
fixes #10
data/ui/window.ui | 427 +++++++++++++++++++++++++++--------------------
src/recordingsListBox.js | 9 +-
src/row.js | 8 +-
src/window.js | 43 ++++-
4 files changed, 293 insertions(+), 194 deletions(-)
---
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 1750d038..7dcd6750 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -109,127 +109,193 @@
</packing>
</child>
<child>
- <object class="GtkStack" id="mainStack">
+ <object class="GtkOverlay">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
<child>
- <object class="GtkScrolledWindow" id="scrolledWindow">
+ <object class="GtkStack" id="mainStack">
<property name="visible">True</property>
- <property name="can_focus">True</property>
+ <property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
- <property name="hscrollbar_policy">never</property>
<child>
- <object class="HdyClamp" id="column">
+ <object class="GtkScrolledWindow" id="scrolledWindow">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="maximum_size">650</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="HdyClamp" id="column">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="maximum_size">650</property>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="name">recordings</property>
+ </packing>
</child>
- </object>
- <packing>
- <property name="name">recordings</property>
- </packing>
- </child>
- <child>
- <object class="HdyWindowHandle">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<child>
- <object class="GtkBox">
+ <object class="HdyWindowHandle">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_left">8</property>
- <property name="margin_right">8</property>
- <property name="margin_top">24</property>
- <property name="margin_bottom">24</property>
- <property name="orientation">vertical</property>
<child>
- <object class="GtkBox" id="recorderBox">
- <property name="height_request">230</property>
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="valign">center</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">24</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="recorderTime">
+ <object class="GtkBox" id="recorderBox">
+ <property name="height_request">230</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_top">18</property>
- <style>
- <class name="dim-label"/>
- <class name="recorder-time-label"/>
- </style>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="recorderTime">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">18</property>
+ <style>
+ <class name="dim-label"/>
+ <class name="recorder-time-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="margin_top">8</property>
- <property name="spacing">18</property>
<child>
- <object class="GtkStack" id="playbackStack">
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">start</property>
+ <property name="halign">center</property>
<property name="valign">center</property>
+ <property name="margin_top">8</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkStack" id="playbackStack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkButton" id="playButton">
+ <property name="name">playButton</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Resume
Recording</property>
+ <property name="halign">center</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="onRecorderResume" swapped="no"/>
+ <child>
+ <object class="GtkImage" id="playIcon">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">media-playback-start-symbolic</property>
+ </object>
+ </child>
+ <style>
+ <class name="pill-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="name">recorder-start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="pauseButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Pause
Recording</property>
+ <property name="halign">center</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="onRecorderPause" swapped="no"/>
+ <child>
+ <object class="GtkImage" id="pauseIcon">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">media-playback-pause-symbolic</property>
+ </object>
+ </child>
+ <style>
+ <class name="pill-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="name">recorder-pause</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
- <object class="GtkButton" id="playButton">
- <property name="name">playButton</property>
+ <object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Resume Recording</property>
+ <property name="tooltip_text" translatable="yes">Stop Recording</property>
<property name="halign">center</property>
- <property name="always_show_image">True</property>
- <signal name="clicked" handler="onRecorderResume" swapped="no"/>
+ <property name="valign">center</property>
+ <signal name="clicked" handler="onRecorderStop" swapped="no"/>
<child>
- <object class="GtkImage" id="playIcon">
+ <object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon_name">media-playback-start-symbolic</property>
+ <property name="icon_name">media-playback-stop-symbolic</property>
+ <property name="icon_size">3</property>
</object>
</child>
<style>
<class name="pill-button"/>
+ <class name="destructive-action"/>
+ <class name="large-button"/>
</style>
</object>
<packing>
- <property name="name">recorder-start</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
- <object class="GtkButton" id="pauseButton">
+ <object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Pause Recording</property>
+ <property name="tooltip_text" translatable="yes">Cancel Recording</property>
<property name="halign">center</property>
+ <property name="valign">center</property>
<property name="always_show_image">True</property>
- <signal name="clicked" handler="onRecorderPause" swapped="no"/>
+ <signal name="clicked" handler="onRecorderCancel" swapped="no"/>
<child>
- <object class="GtkImage" id="pauseIcon">
+ <object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon_name">media-playback-pause-symbolic</property>
+ <property name="icon_name">user-trash-symbolic</property>
</object>
</child>
<style>
@@ -237,160 +303,153 @@
</style>
</object>
<packing>
- <property name="name">recorder-pause</property>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Stop Recording</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <signal name="clicked" handler="onRecorderStop" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">media-playback-stop-symbolic</property>
- <property name="icon_size">3</property>
- </object>
- </child>
- <style>
- <class name="pill-button"/>
- <class name="destructive-action"/>
- <class name="large-button"/>
- </style>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Cancel Recording</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="always_show_image">True</property>
- <signal name="clicked" handler="onRecorderCancel" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">user-trash-symbolic</property>
- </object>
- </child>
- <style>
- <class name="pill-button"/>
- </style>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">recorder</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage" id="emptyIcon">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="pixel_size">96</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">Add Recordings</property>
+ <style>
+ <class name="dim-label"/>
+ <class name="title-1"/>
+ </style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">4</property>
+ <property name="label" translatable="yes">Use the <b>Record</b> button
to make sound recordings</property>
+ <property name="use_markup">True</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">50</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
+ <packing>
+ <property name="name">empty</property>
+ <property name="position">2</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="name">recorder</property>
- <property name="position">1</property>
- </packing>
</child>
- <child>
- <object class="GtkBox">
+ <child type="overlay">
+ <object class="GtkRevealer" id="notificationRevealer">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
- <property name="valign">center</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkImage" id="emptyIcon">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="pixel_size">96</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
+ <property name="valign">start</property>
<child>
- <object class="GtkLabel">
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_top">8</property>
- <property name="label" translatable="yes">Add Recordings</property>
- <style>
- <class name="dim-label"/>
- <class name="title-1"/>
- </style>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_top">4</property>
- <property name="label" translatable="yes">Use the <b>Record</b> button to
make sound recordings</property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- <property name="wrap">True</property>
- <property name="max_width_chars">50</property>
+ <child>
+ <object class="GtkLabel" id="notificationMessage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="notificationUndoBtn">
+ <property name="label" translatable="yes">Undo</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <property name="margin_start">18</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="notificationCancelBtn">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <property name="margin_start">8</property>
+ <property name="relief">none</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">window-close-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
<style>
- <class name="dim-label"/>
+ <class name="app-notification"/>
</style>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
</child>
</object>
- <packing>
- <property name="name">empty</property>
- <property name="position">2</property>
- </packing>
</child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
</child>
diff --git a/src/recordingsListBox.js b/src/recordingsListBox.js
index f248858a..c21d8d34 100644
--- a/src/recordingsListBox.js
+++ b/src/recordingsListBox.js
@@ -2,7 +2,11 @@
const { GObject, GstPlayer, Gtk, Gst } = imports.gi;
const { Row, RowState } = imports.row;
-var RecordingsListBox = new GObject.registerClass(class RecordingsListBox extends Gtk.ListBox {
+var RecordingsListBox = new GObject.registerClass({
+ Signals: {
+ 'row-deleted': { param_types: [GObject.TYPE_OBJECT, GObject.TYPE_INT] },
+ },
+}, class RecordingsListBox extends Gtk.ListBox {
_init(model, player) {
this._player = player;
super._init({
@@ -76,7 +80,7 @@ var RecordingsListBox = new GObject.registerClass(class RecordingsListBox extend
const index = row.get_index();
this.isolateAt(index, false);
- model.remove(index);
+ this.emit('row-deleted', row._recording, index);
});
return row;
@@ -99,7 +103,6 @@ var RecordingsListBox = new GObject.registerClass(class RecordingsListBox extend
this.activeRow = row;
}
-
isolateAt(index, expanded) {
const before = this.get_row_at_index(index - 1);
const current = this.get_row_at_index(index);
diff --git a/src/row.js b/src/row.js
index 8e281182..5bc9c8b9 100644
--- a/src/row.js
+++ b/src/row.js
@@ -98,6 +98,8 @@ var Row = GObject.registerClass({
this._waveformStack.visible_child_name = 'loading';
});
+
+ this._duration.label = formatTime(recording.duration / Gst.SECOND);
recording.connect('notify::duration', () => {
this._duration.label = formatTime(recording.duration / Gst.SECOND);
});
@@ -119,11 +121,7 @@ var Row = GObject.registerClass({
this._seekBackward.connect('clicked', _ => this.emit('seek-backward'));
this._seekForward.connect('clicked', _ => this.emit('seek-forward'));
-
- this._deleteBtn.connect('clicked', () => {
- recording.delete();
- this.emit('deleted');
- });
+ this._deleteBtn.connect('clicked', () => this.emit('deleted'));
}
onSaveRecording() {
diff --git a/src/window.js b/src/window.js
index 930f5712..f04105ea 100644
--- a/src/window.js
+++ b/src/window.js
@@ -18,7 +18,7 @@
*
*/
-const { GObject, GstPlayer, Gtk, Handy } = imports.gi;
+const { GLib, GObject, GstPlayer, Gtk, Handy } = imports.gi;
const { Recorder } = imports.recorder;
const { RecordingList } = imports.recordingList;
@@ -29,7 +29,7 @@ const { WaveForm, WaveType } = imports.waveform;
var Window = GObject.registerClass({
Template: 'resource:///org/gnome/SoundRecorder/ui/window.ui',
- InternalChildren: ['recorderTime', 'mainStack', 'recorderBox', 'emptyIcon', 'playbackStack',
'headerRevealer', 'column'],
+ InternalChildren: ['recorderTime', 'mainStack', 'recorderBox', 'emptyIcon', 'playbackStack',
'headerRevealer', 'notificationRevealer', 'notificationMessage', 'notificationUndoBtn',
'notificationCancelBtn', 'column'],
}, class Window extends Handy.ApplicationWindow {
_init(params) {
@@ -64,6 +64,25 @@ var Window = GObject.registerClass({
this._recordingList.connect('items-changed', this._refreshView.bind(this));
this._recordingListBox = new RecordingsListBox(this._recordingList, this.player);
+
+ this._recordingListBox.connect('row-deleted', (_listBox, recording, index) => {
+ this._recordingList.remove(index);
+ this.notify(_('"%s" deleted').format(recording.name),
+ _ => recording.delete(),
+ _ => this._recordingList.insert(index, recording),
+ );
+ });
+
+ this._notificationCancelBtn.connect('clicked', _ => {
+ this._notificationRevealer.reveal_child = false;
+ if (this.deleteSignalId && this.deleteSignalId > 0) {
+ GLib.source_remove(this.deleteSignalId);
+ this.deleteSignalId = 0;
+ }
+ this._notificationUndoBtn.disconnect(this.cancelSignalId);
+ });
+
+
this._column.add(this._recordingListBox);
this._emptyIcon.icon_name = `${pkg.name}-symbolic`;
@@ -120,4 +139,24 @@ var Window = GObject.registerClass({
else
this._mainStack.visible_child_name = 'recordings';
}
+
+ notify(message, callback, cancelCallback) {
+ this._notificationMessage.label = message;
+ this._notificationRevealer.reveal_child = true;
+ this.deleteSignalId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 3, () => {
+ callback();
+ this._notificationRevealer.reveal_child = false;
+ this._notificationUndoBtn.disconnect(this.cancelSignalId);
+ });
+
+ this.cancelSignalId = this._notificationUndoBtn.connect('clicked', _ => {
+ cancelCallback();
+ this._notificationRevealer.reveal_child = false;
+ if (this.deleteSignalId && this.deleteSignalId > 0) {
+ GLib.source_remove(this.deleteSignalId);
+ this.deleteSignalId = 0;
+ }
+ this._notificationUndoBtn.disconnect(this.cancelSignalId);
+ });
+ }
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]