diff --git a/docs/HELP.md b/docs/HELP.md
new file mode 100644
index 0000000..c09348c
--- /dev/null
+++ b/docs/HELP.md
@@ -0,0 +1,74 @@
+
+
+
+
+
+# Recoder — Help Guide
+
+Recoder is a minimal, user-friendly tool for batch video transcoding. This quick guide walks you through using the app.
+
+---
+
+## 🚀 Getting Started
+
+When you open Recoder, you’ll see a prompt inviting you to drop a video file or folder:
+
+
+
+### 📂 Dropping Files or Folders
+
+- You can drop **one video file** or **one folder** containing video files onto the app.
+- The folder can have subdirectories, but Recoder will **not** process files recursively. Only files in the dropped folder itself will be processed.
+- Non-video files will be ignored.
+
+### 🔧 Preparing to Transcode
+
+After you drop a folder into Recoder, it will list all the video files it found:
+
+
+
+- A blue **Transcode** button appears once the files are ready to process.
+- The **Clear icon** is always available — click it to cancel everything and reset the app if you're done or need to start over.
+- The **menu button** gives access to Preferences and Help.
+
+---
+
+## 🎬 Transcoding
+
+Click the Transcode button to start processing. While transcoding:
+
+
+
+- The blue **Transcode** button is replaced by a **Pause** button, allowing you to temporarily stop the process.
+- If paused, the button changes to **Resume**, so you can continue when you're ready.
+- The **Clear button** can also be used during transcoding to cancel the process entirely and clear the current session.
+
+By default:
+
+- Transcoded files are saved into the same directory as the source, inside a subfolder named `{{source_folder_name}}-transcoded`.
+- File names remain the same as the originals but with a `.mov` extension.
+
+---
+
+### ⚙️ Preferences
+
+In Preferences, you can customize the single **output folder path** where transcoded files will be saved. This path controls both the folder’s location and name. You can use:
+
+- `{{source_folder_name}}` to reuse the original folder name
+- Relative paths like `../done/`
+- Absolute paths like `/mnt/Export/`
+- `~` to refer to your home directory
+- Simple names like `output` to create a folder inside the source folder
+- Any combination of the above, e.g. `../{{source_folder_name}}-dnxhd`
+
+
+
+---
+
+## 💡 Notes
+
+- Make sure you have enough free space on your drive because both the original and transcoded files are kept, and transcoded files may be larger.
+
+---
+
+If you need more help, check the [GitHub repository](https://github.com/jeena/recoder) or open an issue.
\ No newline at end of file
diff --git a/docs/screenshot-1.png b/docs/screenshot-1.png
new file mode 100644
index 0000000..9e57506
Binary files /dev/null and b/docs/screenshot-1.png differ
diff --git a/docs/screenshot-2.png b/docs/screenshot-2.png
new file mode 100644
index 0000000..9cb59e5
Binary files /dev/null and b/docs/screenshot-2.png differ
diff --git a/docs/screenshot-3.png b/docs/screenshot-3.png
new file mode 100644
index 0000000..ae4fe73
Binary files /dev/null and b/docs/screenshot-3.png differ
diff --git a/docs/screenshot-4.png b/docs/screenshot-4.png
new file mode 100644
index 0000000..4d3b35c
Binary files /dev/null and b/docs/screenshot-4.png differ
diff --git a/src/recoder/app.py b/src/recoder/app.py
index 5436a5a..67f6fc0 100755
--- a/src/recoder/app.py
+++ b/src/recoder/app.py
@@ -55,6 +55,11 @@ def main():
self.add_action(preferences_action)
self.set_accels_for_action("app.preferences", ["comma"])
+ help_action = Gio.SimpleAction.new("help", None)
+ help_action.connect("activate", self.on_help_activated)
+ self.add_action(help_action)
+ self.set_accels_for_action("app.help", ["F1"])
+
about_action = Gio.SimpleAction.new("about", None)
about_action.connect("activate", self.on_about_activate)
self.add_action(about_action)
@@ -89,6 +94,9 @@ def main():
def on_preferences_close(self, window):
window.set_visible(False)
+ if window.prefs_changed:
+ window.prefs_changed = False
+ self.window.toast_overlay.add_toast(Adw.Toast.new("Preferences saved"))
# Don't destroy, just hide
return True # stops further handlers, prevents default destruction
@@ -96,6 +104,16 @@ def main():
self.quit()
return False # allow default handler to proceed
+ def on_help_activated(self, action, param):
+ uri = "https://github.com/jeena/recoder/blob/master/docs/HELP.md"
+ try:
+ Gio.AppInfo.launch_default_for_uri(uri, None)
+ self.window.toast_overlay.add_toast(Adw.Toast.new("Opening help in browser…"))
+ except GLib.Error as e:
+ self.window.toast_overlay.add_toast(Adw.Toast.new(f"Failed to open help: {e.message}"))
+
+
+
app = RecoderApp()
return app.run(sys.argv)
diff --git a/src/recoder/preferences.py b/src/recoder/preferences.py
index 01a685e..09ed941 100644
--- a/src/recoder/preferences.py
+++ b/src/recoder/preferences.py
@@ -13,6 +13,7 @@ class RecoderPreferences(Adw.PreferencesWindow):
def __init__(self):
super().__init__()
+ self.prefs_changed = False
self.settings = Gio.Settings.new("net.jeena.recoder.preferences")
current_value = self.settings.get_string("output-folder-template")
@@ -44,13 +45,11 @@ class RecoderPreferences(Adw.PreferencesWindow):
if self.validate_template(text):
self.settings.set_string("output-folder-template", text)
+ self.prefs_changed = True
entry.remove_css_class("error")
else:
entry.add_css_class("error")
-
-
-
def on_setting_changed(self, settings, key):
if key == "output-folder-template":
new_val = settings.get_string(key)
diff --git a/src/recoder/window.py b/src/recoder/window.py
index f5fbb00..d614acd 100644
--- a/src/recoder/window.py
+++ b/src/recoder/window.py
@@ -22,6 +22,7 @@ from recoder.app import APP_NAME
class RecoderWindow(Adw.ApplicationWindow):
__gtype_name__ = "RecoderWindow"
+ toast_overlay = Gtk.Template.Child()
overlay = Gtk.Template.Child()
drop_hint = Gtk.Template.Child()
listbox = Gtk.Template.Child()
@@ -96,6 +97,10 @@ class RecoderWindow(Adw.ApplicationWindow):
self.file_items_to_process = file_items
self.app_state_manager.state = AppState.FILES_LOADED
+
+ count = len(self.file_items_to_process)
+ toast = Adw.Toast.new(f"{count} video file{'s' if count != 1 else ''} added")
+ self.toast_overlay.add_toast(toast)
return False
def clear_listbox(self):
@@ -122,26 +127,30 @@ class RecoderWindow(Adw.ApplicationWindow):
self.transcoder.connect("notify::batch-progress", self.on_transcoder_progress)
self.transcoder.connect("notify::batch-status", self.on_transcoder_status)
self.transcoder.start()
-
self.app_state_manager.state = AppState.TRANSCODING
+ self.toast_overlay.add_toast(Adw.Toast.new("Starting transcoding"))
def pause_transcoding(self):
if self.transcoder:
self.transcoder.pause()
self.is_paused = True
self.app_state_manager.state = AppState.PAUSED
+ self.toast_overlay.add_toast(Adw.Toast.new("Transcoding paused"))
def resume_transcoding(self):
if self.transcoder:
self.transcoder.resume()
self.is_paused = False
self.app_state_manager.state = AppState.TRANSCODING
+ self.toast_overlay.add_toast(Adw.Toast.new("Resuming transcoding"))
def on_clear_clicked(self, button):
if self.transcoder and self.transcoder.is_processing:
self.transcoder.stop()
self.transcoder = None
+ self.clear_listbox()
self.app_state_manager.state = AppState.STOPPED
+ self.toast_overlay.add_toast(Adw.Toast.new("File list cleared"))
def on_transcoder_progress(self, transcoder, param):
self.progress_bar.set_fraction(transcoder.batch_progress / 100.0)
@@ -150,6 +159,7 @@ class RecoderWindow(Adw.ApplicationWindow):
if transcoder.batch_status == BatchStatus.DONE:
play_complete_sound()
notify_done(APP_NAME, "Transcoding finished!")
+ self.toast_overlay.add_toast(Adw.Toast.new("Transcoding finished!"))
self.app_state_manager.state = AppState.DONE
elif transcoder.batch_status == BatchStatus.STOPPED:
@@ -157,4 +167,5 @@ class RecoderWindow(Adw.ApplicationWindow):
elif transcoder.batch_status == BatchStatus.ERROR:
notify_done(APP_NAME, "An error occurred during transcoding.")
+ self.toast_overlay.add_toast(Adw.Toast.new("An error occurred during transcoding"))
self.app_state_manager.state = AppState.ERROR
diff --git a/src/resources/resources.xml b/src/resources/resources.xml
index f4ae0d6..dad3728 100644
--- a/src/resources/resources.xml
+++ b/src/resources/resources.xml
@@ -4,6 +4,5 @@
preferences.uifile_entry_row.uistyle.css
- ../resources/net.jeena.Recoder.svg
diff --git a/src/resources/window.ui b/src/resources/window.ui
index 4a72557..0e4a030 100644
--- a/src/resources/window.ui
+++ b/src/resources/window.ui
@@ -8,6 +8,10 @@
Preferencesapp.preferences
+
+ Help
+ app.help
+ About Recoderapp.about
@@ -24,143 +28,145 @@
400
-