Merge pull request #20 from TheColorman/master
Add Catbox upload support
This commit is contained in:
commit
579e28c5f9
|
@ -113,6 +113,14 @@ video_fps=auto
|
||||||
audio_format=opus
|
audio_format=opus
|
||||||
# Opus sounds good at low bitrates 32-64k, but aac requires 128-256k.
|
# Opus sounds good at low bitrates 32-64k, but aac requires 128-256k.
|
||||||
audio_bitrate=32k
|
audio_bitrate=32k
|
||||||
|
|
||||||
|
# Catbox.moe upload settings
|
||||||
|
# Whether uploads should go to litterbox instead of catbox.
|
||||||
|
# catbox files are stored permanently, while litterbox is temporary
|
||||||
|
litterbox=yes
|
||||||
|
# If using litterbox, time until video expires
|
||||||
|
# Available values: 1h, 12h, 24h, 72h
|
||||||
|
litterbox_expire=72h
|
||||||
```
|
```
|
||||||
|
|
||||||
### Key bindings
|
### Key bindings
|
||||||
|
|
53
helpers.lua
Normal file
53
helpers.lua
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
--[[
|
||||||
|
Copyright: Ren Tatsumoto and contributors
|
||||||
|
License: GNU GPL, version 3 or later; http://www.gnu.org/licenses/gpl.html
|
||||||
|
|
||||||
|
Various helper functions.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local mp = require('mp')
|
||||||
|
local this = {}
|
||||||
|
|
||||||
|
this.is_wayland = function()
|
||||||
|
return os.getenv('WAYLAND_DISPLAY') ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
this.is_win = function()
|
||||||
|
return mp.get_property('options/vo-mmcss-profile') ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
this.is_mac = function()
|
||||||
|
return mp.get_property('options/macos-force-dedicated-gpu') ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
this.notify = function(message, level, duration)
|
||||||
|
level = level or 'info'
|
||||||
|
duration = duration or 1
|
||||||
|
mp.msg[level](message)
|
||||||
|
mp.osd_message(message, duration)
|
||||||
|
end
|
||||||
|
|
||||||
|
this.subprocess = function(args, stdin)
|
||||||
|
local command_table = {
|
||||||
|
name = "subprocess",
|
||||||
|
playback_only = false,
|
||||||
|
capture_stdout = true,
|
||||||
|
capture_stderr = true,
|
||||||
|
args = args,
|
||||||
|
stdin_data = (stdin or ""),
|
||||||
|
}
|
||||||
|
return mp.command_native(command_table)
|
||||||
|
end
|
||||||
|
|
||||||
|
this.subprocess_async = function(args, on_complete)
|
||||||
|
local command_table = {
|
||||||
|
name = "subprocess",
|
||||||
|
playback_only = false,
|
||||||
|
capture_stdout = true,
|
||||||
|
capture_stderr = true,
|
||||||
|
args = args
|
||||||
|
}
|
||||||
|
return mp.command_native_async(command_table, on_complete)
|
||||||
|
end
|
||||||
|
|
||||||
|
return this
|
87
platform.lua
Normal file
87
platform.lua
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
--[[
|
||||||
|
Copyright: Ren Tatsumoto and contributors
|
||||||
|
License: GNU GPL, version 3 or later; http://www.gnu.org/licenses/gpl.html
|
||||||
|
|
||||||
|
OS-related constants and functions.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local h = require('helpers')
|
||||||
|
local mp = require('mp')
|
||||||
|
local utils = require('mp.utils')
|
||||||
|
local this = {}
|
||||||
|
|
||||||
|
this.Platform = {
|
||||||
|
gnu_linux = "gnu_linux",
|
||||||
|
macos = "macos",
|
||||||
|
windows = "windows",
|
||||||
|
}
|
||||||
|
this.platform = (
|
||||||
|
h.is_win() and this.Platform.windows
|
||||||
|
or h.is_mac() and this.Platform.macos
|
||||||
|
or this.Platform.gnu_linux
|
||||||
|
)
|
||||||
|
this.default_video_folder = utils.join_path(
|
||||||
|
(os.getenv("HOME") or os.getenv("USERPROFILE")),
|
||||||
|
(this.platform == this.Platform.macos and "Movies" or "Videos")
|
||||||
|
)
|
||||||
|
this.default_audio_folder = utils.join_path(
|
||||||
|
(os.getenv("HOME") or os.getenv('USERPROFILE')),
|
||||||
|
"Music"
|
||||||
|
)
|
||||||
|
this.curl_exe = (this.platform == this.Platform.windows and 'curl.exe' or 'curl')
|
||||||
|
this.open_utility = (
|
||||||
|
this.platform == this.Platform.windows and 'explorer.exe'
|
||||||
|
or this.platform == this.Platform.macos and 'open'
|
||||||
|
or this.platform == this.Platform.gnu_linux and 'xdg-open'
|
||||||
|
)
|
||||||
|
this.open = function(file_or_url)
|
||||||
|
return mp.commandv('run', this.open_utility, file_or_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
this.clipboard = (function()
|
||||||
|
local self = {}
|
||||||
|
if this.platform == this.Platform.windows then
|
||||||
|
self.clip_exe = "powershell.exe"
|
||||||
|
self.copy = function(text)
|
||||||
|
return h.subprocess({ self.clip_exe, '-command', 'Set-Clipboard -Value ' .. text })
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if this.platform == this.Platform.macos then
|
||||||
|
self.clip_exe = "pbcopy"
|
||||||
|
self.clip_cmd = "LANG=en_US.UTF-8 pbcopy"
|
||||||
|
elseif h.is_wayland() then
|
||||||
|
self.clip_exe = "wl-copy"
|
||||||
|
self.clip_cmd = "wl-copy"
|
||||||
|
else
|
||||||
|
self.clip_exe = "xclip"
|
||||||
|
self.clip_cmd = "xclip -i -selection clipboard"
|
||||||
|
end
|
||||||
|
self.copy = function(text)
|
||||||
|
local handle = io.popen(self.clip_cmd, 'w')
|
||||||
|
if handle then
|
||||||
|
handle:write(text)
|
||||||
|
local suc, exit, code = handle:close()
|
||||||
|
return { status = code }
|
||||||
|
else
|
||||||
|
return { status = 1 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end)()
|
||||||
|
|
||||||
|
this.copy_or_open_url = function(url)
|
||||||
|
local cb = this.clipboard.copy(url)
|
||||||
|
if cb.status ~= 0 then
|
||||||
|
local msg = string.format(
|
||||||
|
"Failed to copy URL to clipboard, trying to open in browser instead. Make sure %s is installed.",
|
||||||
|
this.clipboard.clip_exe
|
||||||
|
)
|
||||||
|
h.notify(msg, "warn", 4)
|
||||||
|
this.open(url)
|
||||||
|
else
|
||||||
|
h.notify("Done! Copied URL to clipboard.", "info", 2)
|
||||||
|
end
|
||||||
|
return cb
|
||||||
|
end
|
||||||
|
return this
|
130
videoclip.lua
130
videoclip.lua
|
@ -22,16 +22,19 @@ local mp = require('mp')
|
||||||
local mpopt = require('mp.options')
|
local mpopt = require('mp.options')
|
||||||
local utils = require('mp.utils')
|
local utils = require('mp.utils')
|
||||||
local OSD = require('osd_styler')
|
local OSD = require('osd_styler')
|
||||||
|
local p = require('platform')
|
||||||
|
local h = require('helpers')
|
||||||
|
|
||||||
local is_macos = io.popen("uname"):read("*a") == "Darwin\n"
|
------------------------------------------------------------
|
||||||
|
-- System-dependent variables
|
||||||
|
|
||||||
-- Options can be changed here or in a separate config file.
|
-- Options can be changed here or in a separate config file.
|
||||||
-- Config path: ~/.config/mpv/script-opts/videoclip.conf
|
-- Config path: ~/.config/mpv/script-opts/videoclip.conf
|
||||||
local config = {
|
local config = {
|
||||||
-- absolute paths
|
-- absolute paths
|
||||||
-- relative paths (e.g. ~ for home dir) do NOT work.
|
-- relative paths (e.g. ~ for home dir) do NOT work.
|
||||||
video_folder_path = string.format(is_macos and '%s/Movies/' or '%s/Videos/', os.getenv("HOME") or os.getenv('USERPROFILE')),
|
video_folder_path = p.default_video_folder,
|
||||||
audio_folder_path = string.format('%s/Music/', os.getenv("HOME") or os.getenv('USERPROFILE')),
|
audio_folder_path = p.default_audio_folder,
|
||||||
-- The range of the CRF scale is 0–51, where 0 is lossless,
|
-- The range of the CRF scale is 0–51, where 0 is lossless,
|
||||||
-- 23 is the default, and 51 is worst quality possible.
|
-- 23 is the default, and 51 is worst quality possible.
|
||||||
-- Insane values like 9999 still work but produce the worst quality.
|
-- Insane values like 9999 still work but produce the worst quality.
|
||||||
|
@ -48,6 +51,10 @@ local config = {
|
||||||
audio_bitrate = '32k', -- 32k, 64k, 128k, 256k. aac requires higher bitrates.
|
audio_bitrate = '32k', -- 32k, 64k, 128k, 256k. aac requires higher bitrates.
|
||||||
font_size = 24,
|
font_size = 24,
|
||||||
clean_filename = true,
|
clean_filename = true,
|
||||||
|
-- Whether to upload to catbox (permanent) or litterbox (temporary)
|
||||||
|
litterbox = true,
|
||||||
|
-- Determines expire time of files uploaded to litterbox
|
||||||
|
litterbox_expire = '72h', -- 1h, 12h, 24h, 72h
|
||||||
}
|
}
|
||||||
|
|
||||||
mpopt.read_options(config, NAME)
|
mpopt.read_options(config, NAME)
|
||||||
|
@ -124,17 +131,6 @@ local function construct_filename()
|
||||||
return filename
|
return filename
|
||||||
end
|
end
|
||||||
|
|
||||||
local function subprocess_async(args, on_complete)
|
|
||||||
local command_table = {
|
|
||||||
name = "subprocess",
|
|
||||||
playback_only = false,
|
|
||||||
capture_stdout = true,
|
|
||||||
capture_stderr = true,
|
|
||||||
args = args
|
|
||||||
}
|
|
||||||
return mp.command_native_async(command_table, on_complete)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function force_resolution(width, height, clip_fn, ...)
|
local function force_resolution(width, height, clip_fn, ...)
|
||||||
local cached_prefs = {
|
local cached_prefs = {
|
||||||
video_width = config.video_width,
|
video_width = config.video_width,
|
||||||
|
@ -184,11 +180,34 @@ local function validate_config()
|
||||||
set_encoding_settings()
|
set_encoding_settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function notify(message, level, duration)
|
local function upload_to_catbox(outfile)
|
||||||
level = level or 'info'
|
local endpoint = config.litterbox and 'https://litterbox.catbox.moe/resources/internals/api.php' or 'https://catbox.moe/user/api.php'
|
||||||
duration = duration or 1
|
h.notify("Uploading to " .. (config.litterbox and "litterbox.catbox.moe..." or "catbox.moe..."), "info", 9999)
|
||||||
mp.msg[level](message)
|
|
||||||
mp.osd_message(message, duration)
|
-- This uses cURL to send a request to the cat-/litterbox API.
|
||||||
|
-- cURL is included on Windows 10 and up, most Linux distributions and macOS.
|
||||||
|
|
||||||
|
local r = h.subprocess({ -- This is technically blocking, but I don't think it has any real consequences ..?
|
||||||
|
p.curl_exe, '-s',
|
||||||
|
'-F', 'reqtype=fileupload',
|
||||||
|
'-F', 'time=' .. config['litterbox_expire'],
|
||||||
|
'-F', 'fileToUpload=@"' .. outfile .. '"',
|
||||||
|
endpoint
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Exit codes in the range [0, 99] are returned by cURL itself.
|
||||||
|
-- Any other exit code means the shell failed to execute cURL.
|
||||||
|
if r.status < 0 or r.status > 99 then
|
||||||
|
h.notify("Error: Failed to upload. Make sure cURL is installed and in your PATH.", "error", 3)
|
||||||
|
return
|
||||||
|
elseif r.status ~= 0 then
|
||||||
|
h.notify("Error: Failed to upload to " .. (config.litterbox and "litterbox.catbox.moe" or "catbox.moe"), "error", 2)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
mp.msg.info("Catbox URL: " .. r.stdout)
|
||||||
|
-- Copy to clipboard
|
||||||
|
p.copy_or_open_url(r.stdout)
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
@ -282,19 +301,19 @@ encoder.mkargs_audio = function(clip_filename)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
encoder.create_clip = function(clip_type)
|
encoder.create_clip = function(clip_type, on_complete)
|
||||||
main_menu:close();
|
main_menu:close();
|
||||||
if clip_type == nil then
|
if clip_type == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not main_menu.timings:validate() then
|
if not main_menu.timings:validate() then
|
||||||
notify("Wrong timings. Aborting.", "warn", 2)
|
h.notify("Wrong timings. Aborting.", "warn", 2)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local clip_filename = construct_filename()
|
local clip_filename = construct_filename()
|
||||||
notify("Please wait...", "info", 9999)
|
h.notify("Please wait...", "info", 9999)
|
||||||
|
|
||||||
local args
|
local args
|
||||||
local location
|
local location
|
||||||
|
@ -309,13 +328,16 @@ encoder.create_clip = function(clip_type)
|
||||||
|
|
||||||
local process_result = function(_, ret, _)
|
local process_result = function(_, ret, _)
|
||||||
if ret.status ~= 0 or string.match(ret.stdout, "could not open") then
|
if ret.status ~= 0 or string.match(ret.stdout, "could not open") then
|
||||||
notify(string.format("Error: couldn't create the clip.\nDoes %s exist?", location), "error", 5)
|
h.notify(string.format("Error: couldn't create the clip.\nDoes %s exist?", location), "error", 5)
|
||||||
else
|
else
|
||||||
notify(string.format("Clip saved to %s.", location), "info", 2)
|
h.notify(string.format("Clip saved to %s.", location), "info", 2)
|
||||||
|
if on_complete then
|
||||||
|
on_complete(utils.join_path(config.video_folder_path, clip_filename .. config.video_extension))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subprocess_async(args, process_result)
|
h.subprocess_async(args, process_result)
|
||||||
main_menu.timings:reset()
|
main_menu.timings:reset()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -380,8 +402,10 @@ main_menu.keybindings = {
|
||||||
{ key = 'c', fn = function() encoder.create_clip('video') end },
|
{ key = 'c', fn = function() encoder.create_clip('video') end },
|
||||||
{ key = 'C', fn = function() force_resolution(1920, -2, encoder.create_clip, 'video') end },
|
{ key = 'C', fn = function() force_resolution(1920, -2, encoder.create_clip, 'video') end },
|
||||||
{ key = 'a', fn = function() encoder.create_clip('audio') end },
|
{ key = 'a', fn = function() encoder.create_clip('audio') end },
|
||||||
|
{ key = 'x', fn = function() main_menu:create_clip_and_upload_to_catbox() end },
|
||||||
|
{ key = 'X', fn = function() force_resolution(1920, -2, main_menu.create_clip_and_upload_to_catbox) end },
|
||||||
{ key = 'p', fn = function() pref_menu:open() end },
|
{ key = 'p', fn = function() pref_menu:open() end },
|
||||||
{ key = 'o', fn = function() mp.commandv('run', is_macos and "open" or "xdg-open", 'https://streamable.com/') end },
|
{ key = 'o', fn = function() p.open('https://streamable.com/') end },
|
||||||
{ key = 'ESC', fn = function() main_menu:close() end },
|
{ key = 'ESC', fn = function() main_menu:close() end },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +419,7 @@ function main_menu:set_time_sub(property)
|
||||||
local time_pos = mp.get_property_number(string.format("sub-%s", property))
|
local time_pos = mp.get_property_number(string.format("sub-%s", property))
|
||||||
|
|
||||||
if time_pos == nil then
|
if time_pos == nil then
|
||||||
notify("Warning: No subtitles visible.", "warn", 2)
|
h.notify("Warning: No subtitles visible.", "warn", 2)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -425,6 +449,7 @@ function main_menu:update()
|
||||||
osd:submenu('Create clip '):italics('(+shift to force fullHD preset)'):newline()
|
osd:submenu('Create clip '):italics('(+shift to force fullHD preset)'):newline()
|
||||||
osd:tab():item('c: '):append('video clip'):newline()
|
osd:tab():item('c: '):append('video clip'):newline()
|
||||||
osd:tab():item('a: '):append('audio clip'):newline()
|
osd:tab():item('a: '):append('audio clip'):newline()
|
||||||
|
osd:tab():item('x: '):append('video clip to ' .. (config.litterbox and 'litterbox.catbox.moe (' .. config.litterbox_expire .. ')' or 'catbox.moe')):newline()
|
||||||
osd:submenu('Options '):newline()
|
osd:submenu('Options '):newline()
|
||||||
osd:tab():item('p: '):append('Open preferences'):newline()
|
osd:tab():item('p: '):append('Open preferences'):newline()
|
||||||
osd:tab():item('o: '):append('Open streamable.com'):newline()
|
osd:tab():item('o: '):append('Open streamable.com'):newline()
|
||||||
|
@ -433,6 +458,10 @@ function main_menu:update()
|
||||||
self:overlay_draw(osd:get_text())
|
self:overlay_draw(osd:get_text())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function main_menu:create_clip_and_upload_to_catbox()
|
||||||
|
encoder.create_clip('video', upload_to_catbox)
|
||||||
|
end
|
||||||
|
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
-- Preferences
|
-- Preferences
|
||||||
|
|
||||||
|
@ -445,6 +474,8 @@ pref_menu.keybindings = {
|
||||||
{ key = 'r', fn = function() pref_menu:cycle_resolutions() end },
|
{ key = 'r', fn = function() pref_menu:cycle_resolutions() end },
|
||||||
{ key = 'b', fn = function() pref_menu:cycle_audio_bitrates() end },
|
{ key = 'b', fn = function() pref_menu:cycle_audio_bitrates() end },
|
||||||
{ key = 'e', fn = function() pref_menu:toggle_embed_subtitles() end },
|
{ key = 'e', fn = function() pref_menu:toggle_embed_subtitles() end },
|
||||||
|
{ key = 'x', fn = function() pref_menu:toggle_catbox() end },
|
||||||
|
{ key = 'z', fn = function() pref_menu:cycle_litterbox_expiration() end },
|
||||||
{ key = 's', fn = function() pref_menu:save() end },
|
{ key = 's', fn = function() pref_menu:save() end },
|
||||||
{ key = 'c', fn = function() end },
|
{ key = 'c', fn = function() end },
|
||||||
{ key = 'ESC', fn = function() pref_menu:close() end },
|
{ key = 'ESC', fn = function() pref_menu:close() end },
|
||||||
|
@ -475,13 +506,14 @@ pref_menu.audio_bitrates = {
|
||||||
|
|
||||||
pref_menu.vid_formats = { 'mp4', 'vp9', 'vp8', }
|
pref_menu.vid_formats = { 'mp4', 'vp9', 'vp8', }
|
||||||
pref_menu.aud_formats = { 'aac', 'opus', }
|
pref_menu.aud_formats = { 'aac', 'opus', }
|
||||||
|
pref_menu.litterbox_expirations = { '1h', '12h', '24h', '72h', }
|
||||||
|
|
||||||
function pref_menu:get_selected_resolution()
|
function pref_menu:get_selected_resolution()
|
||||||
local w = config.video_width
|
return string.format(
|
||||||
local h = config.video_height
|
'%s x %s',
|
||||||
w = w == -2 and 'auto' or w
|
config.video_width == -2 and 'auto' or config.video_width,
|
||||||
h = h == -2 and 'auto' or h
|
config.video_height == -2 and 'auto' or config.video_height
|
||||||
return string.format('%s x %s', w, h)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function pref_menu:cycle_resolutions()
|
function pref_menu:cycle_resolutions()
|
||||||
|
@ -536,6 +568,28 @@ function pref_menu:toggle_embed_subtitles()
|
||||||
self:update()
|
self:update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function pref_menu:toggle_catbox()
|
||||||
|
config['litterbox'] = not config['litterbox']
|
||||||
|
self:update()
|
||||||
|
end
|
||||||
|
|
||||||
|
function pref_menu:cycle_litterbox_expiration()
|
||||||
|
if not config['litterbox'] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local expirations = pref_menu.litterbox_expirations
|
||||||
|
|
||||||
|
local selected = 1
|
||||||
|
for i, expiration in ipairs(expirations) do
|
||||||
|
if config['litterbox_expire'] == expiration then
|
||||||
|
selected = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
config['litterbox_expire'] = expirations[selected + 1] or expirations[1]
|
||||||
|
self:update()
|
||||||
|
end
|
||||||
|
|
||||||
function pref_menu:update()
|
function pref_menu:update()
|
||||||
local osd = OSD:new():size(config.font_size):align(4)
|
local osd = OSD:new():size(config.font_size):align(4)
|
||||||
osd:submenu('Preferences'):newline()
|
osd:submenu('Preferences'):newline()
|
||||||
|
@ -545,6 +599,14 @@ function pref_menu:update()
|
||||||
osd:tab():item('b: Audio bitrate: '):append(config.audio_bitrate):newline()
|
osd:tab():item('b: Audio bitrate: '):append(config.audio_bitrate):newline()
|
||||||
osd:tab():item('m: Mute audio: '):append(mp.get_property("mute")):newline()
|
osd:tab():item('m: Mute audio: '):append(mp.get_property("mute")):newline()
|
||||||
osd:tab():item('e: Embed subtitles: '):append(mp.get_property("sub-visibility")):newline()
|
osd:tab():item('e: Embed subtitles: '):append(mp.get_property("sub-visibility")):newline()
|
||||||
|
osd:submenu('Catbox'):newline()
|
||||||
|
osd:tab():item('x: Using: '):append(config.litterbox and 'Litterbox (temporary)' or 'Catbox (permanent)'):newline()
|
||||||
|
if config.litterbox then
|
||||||
|
osd:tab():item('z: Litterbox expires after: '):append(config.litterbox_expire):newline()
|
||||||
|
else
|
||||||
|
osd:tab():color("b0b0b0"):text('x: Litterbox expires after: '):append("N/A"):newline()
|
||||||
|
end
|
||||||
|
osd:submenu('Save'):newline()
|
||||||
osd:tab():item('s: Save preferences'):newline()
|
osd:tab():item('s: Save preferences'):newline()
|
||||||
self:overlay_draw(osd:get_text())
|
self:overlay_draw(osd:get_text())
|
||||||
end
|
end
|
||||||
|
@ -574,9 +636,9 @@ function pref_menu:save()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
handle:close()
|
handle:close()
|
||||||
notify("Settings saved.", "info", 2)
|
h.notify("Settings saved.", "info", 2)
|
||||||
else
|
else
|
||||||
notify(string.format("Couldn't open %s.", config_filepath), "error", 4)
|
h.notify(string.format("Couldn't open %s.", config_filepath), "error", 4)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue