feat: lockscreen closes #1490
This commit is contained in:
@@ -34,6 +34,12 @@ The options listed here are not editable from within the user interface.
|
|||||||
# Define one or more moonraker power devices that turn on/off with the screensaver (CSV list)
|
# Define one or more moonraker power devices that turn on/off with the screensaver (CSV list)
|
||||||
# screen_on_devices: example1, example2
|
# screen_on_devices: example1, example2
|
||||||
# screen_off_devices: example1, example2
|
# screen_off_devices: example1, example2
|
||||||
|
|
||||||
|
# Define the password to use when locking the screen, this is not secure
|
||||||
|
# it's saved as plain text, it's meant to be a deterrent for kids or people at shows
|
||||||
|
# it will be redacted from the logs.
|
||||||
|
# default is no password
|
||||||
|
# lock_password: example_password
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tip
|
!!! tip
|
||||||
|
@@ -168,6 +168,7 @@ class KlipperScreenConfig:
|
|||||||
strs = (
|
strs = (
|
||||||
'default_printer', 'language', 'print_sort_dir', 'theme', 'screen_blanking_printing', 'font_size',
|
'default_printer', 'language', 'print_sort_dir', 'theme', 'screen_blanking_printing', 'font_size',
|
||||||
'print_estimate_method', 'screen_blanking', "screen_on_devices", "screen_off_devices", 'print_view',
|
'print_estimate_method', 'screen_blanking', "screen_on_devices", "screen_off_devices", 'print_view',
|
||||||
|
"lock_password"
|
||||||
)
|
)
|
||||||
numbers = (
|
numbers = (
|
||||||
'job_complete_timeout', 'job_error_timeout', 'move_speed_xy', 'move_speed_z',
|
'job_complete_timeout', 'job_error_timeout', 'move_speed_xy', 'move_speed_z',
|
||||||
@@ -584,14 +585,16 @@ class KlipperScreenConfig:
|
|||||||
self.config.set(section, name, value)
|
self.config.set(section, name, value)
|
||||||
|
|
||||||
def log_config(self, config):
|
def log_config(self, config):
|
||||||
|
sensitive_keys = [
|
||||||
|
r'(moonraker_api_key\s*(?:=|:)\s*)\S+',
|
||||||
|
r'(lock_password\s*(?:=|:)\s*)\S+',
|
||||||
|
]
|
||||||
|
config_str = self._build_config_string(config)
|
||||||
|
for pattern in sensitive_keys:
|
||||||
|
config_str = re.sub(pattern, r'\1[redacted]', config_str)
|
||||||
lines = [
|
lines = [
|
||||||
" "
|
|
||||||
"===== Config File =====",
|
"===== Config File =====",
|
||||||
re.sub(
|
config_str,
|
||||||
r'(moonraker_api_key\s*=\s*\S+)',
|
|
||||||
'moonraker_api_key = [redacted]',
|
|
||||||
self._build_config_string(config)
|
|
||||||
),
|
|
||||||
"======================="
|
"======================="
|
||||||
]
|
]
|
||||||
logging.info("\n".join(lines))
|
logging.info("\n".join(lines))
|
||||||
|
@@ -10,7 +10,7 @@ from gi.repository import Gtk, GLib
|
|||||||
class Keyboard(Gtk.Box):
|
class Keyboard(Gtk.Box):
|
||||||
langs = ["de", "en", "fr", "es"]
|
langs = ["de", "en", "fr", "es"]
|
||||||
|
|
||||||
def __init__(self, screen, close_cb, entry=None):
|
def __init__(self, screen, close_cb, entry=None, box=None):
|
||||||
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
||||||
self.shift = []
|
self.shift = []
|
||||||
self.shift_active = False
|
self.shift_active = False
|
||||||
@@ -20,6 +20,7 @@ class Keyboard(Gtk.Box):
|
|||||||
self.timeout = self.clear_timeout = None
|
self.timeout = self.clear_timeout = None
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
self.purpose = self.entry.get_input_purpose()
|
self.purpose = self.entry.get_input_purpose()
|
||||||
|
self.box = box or None
|
||||||
|
|
||||||
language = self.detect_language(screen._config.get_main_config().get("language", None))
|
language = self.detect_language(screen._config.get_main_config().get("language", None))
|
||||||
|
|
||||||
@@ -218,7 +219,7 @@ class Keyboard(Gtk.Box):
|
|||||||
if key == "⌫":
|
if key == "⌫":
|
||||||
Gtk.Entry.do_backspace(self.entry)
|
Gtk.Entry.do_backspace(self.entry)
|
||||||
elif key == "↓":
|
elif key == "↓":
|
||||||
self.close_cb(entry=self.entry)
|
self.close_cb(entry=self.entry, box=self.box)
|
||||||
return
|
return
|
||||||
elif key == "↑":
|
elif key == "↑":
|
||||||
self.toggle_shift()
|
self.toggle_shift()
|
||||||
|
96
ks_includes/widgets/lockscreen.py
Normal file
96
ks_includes/widgets/lockscreen.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import logging
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
|
||||||
|
class LockScreen:
|
||||||
|
def __init__(self, screen):
|
||||||
|
self.screen = screen
|
||||||
|
self.lock_box = None
|
||||||
|
self.unlock_box = None
|
||||||
|
|
||||||
|
def lock(self, widget):
|
||||||
|
self.screen._menu_go_back(None, True)
|
||||||
|
logging.info("Locked the screen")
|
||||||
|
close = Gtk.Button()
|
||||||
|
close.connect("clicked", self.unlock)
|
||||||
|
self.lock_box = Gtk.Box(
|
||||||
|
width_request=self.screen.width, height_request=self.screen.height,
|
||||||
|
halign=Gtk.Align.CENTER
|
||||||
|
)
|
||||||
|
self.lock_box.pack_start(close, True, True, 0)
|
||||||
|
self.lock_box.get_style_context().add_class("lock")
|
||||||
|
self.screen.overlay.add_overlay(self.lock_box)
|
||||||
|
close.grab_focus()
|
||||||
|
self.lock_box.show_all()
|
||||||
|
|
||||||
|
def unlock(self, widget):
|
||||||
|
if not self.unlock_box:
|
||||||
|
self.unlock_box = self.create_unlock_box()
|
||||||
|
self.screen.overlay.add_overlay(self.unlock_box)
|
||||||
|
self.unlock_box.show_all()
|
||||||
|
self.screen.overlay.get_children()[0].hide()
|
||||||
|
|
||||||
|
def create_unlock_box(self):
|
||||||
|
box = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL,
|
||||||
|
width_request=self.screen.width, height_request=self.screen.height,
|
||||||
|
valign=Gtk.Align.CENTER
|
||||||
|
)
|
||||||
|
entry = Gtk.Entry(hexpand=True, vexpand=False, placeholder_text=_("Password"))
|
||||||
|
entry.set_input_purpose(Gtk.InputPurpose.PASSWORD)
|
||||||
|
entry.set_visibility(False)
|
||||||
|
entry.connect("focus-in-event", self.screen.show_keyboard, box, self.relock)
|
||||||
|
entry.connect("activate", self.unlock_attempt, entry)
|
||||||
|
entry.get_style_context().add_class("lockscreen_entry")
|
||||||
|
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "view-reveal-symbolic")
|
||||||
|
entry.connect("icon-press", self.show_pass)
|
||||||
|
ok = Gtk.Button(label=_("Unlock"))
|
||||||
|
ok.connect("clicked", self.unlock_attempt, entry)
|
||||||
|
ok.get_style_context().add_class("lockscreen_button")
|
||||||
|
entry_row = Gtk.Box(hexpand=True, vexpand=True, valign=Gtk.Align.CENTER)
|
||||||
|
entry_row.pack_start(entry, True, True, 0)
|
||||||
|
entry_row.pack_start(ok, False, True, 0)
|
||||||
|
box.pack_start(entry_row, True, True, 0)
|
||||||
|
return box
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def show_pass(entry, icon_pos, event):
|
||||||
|
entry.grab_focus()
|
||||||
|
visible = not entry.get_visibility()
|
||||||
|
entry.set_visibility(visible)
|
||||||
|
if visible:
|
||||||
|
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "view-conceal-symbolic")
|
||||||
|
entry.get_style_context().add_class("active")
|
||||||
|
else:
|
||||||
|
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "view-reveal-symbolic")
|
||||||
|
entry.get_style_context().remove_class("active")
|
||||||
|
|
||||||
|
def relock(self, entry=None, box=None):
|
||||||
|
if not self.lock_box:
|
||||||
|
return
|
||||||
|
if self.unlock_box:
|
||||||
|
self.screen.overlay.remove(self.unlock_box)
|
||||||
|
self.unlock_box = None
|
||||||
|
self.lock_box.get_children()[0].grab_focus()
|
||||||
|
self.screen.overlay.get_children()[0].show_all()
|
||||||
|
|
||||||
|
def unlock_attempt(self, widget, entry):
|
||||||
|
if entry.get_text() != self.screen._config.get_main_config().get("lock_password", ""):
|
||||||
|
logging.info("Failed unlock")
|
||||||
|
self.screen.show_popup_message(_("Unlock failed"))
|
||||||
|
return
|
||||||
|
self.clear_lock()
|
||||||
|
|
||||||
|
def clear_lock(self):
|
||||||
|
if self.lock_box:
|
||||||
|
self.screen.overlay.remove(self.lock_box)
|
||||||
|
if self.unlock_box:
|
||||||
|
self.screen.overlay.remove(self.unlock_box)
|
||||||
|
self.lock_box = None
|
||||||
|
self.unlock_box = None
|
||||||
|
self.screen.remove_keyboard()
|
||||||
|
self.screen.overlay.get_children()[0].show()
|
||||||
|
logging.info("Unlocked")
|
@@ -24,12 +24,16 @@ class Panel(ScreenPanel):
|
|||||||
restart_ks = self._gtk.Button("refresh", _("Restart") + " KlipperScreen", "color3")
|
restart_ks = self._gtk.Button("refresh", _("Restart") + " KlipperScreen", "color3")
|
||||||
restart_ks.connect("clicked", self._screen.restart_ks)
|
restart_ks.connect("clicked", self._screen.restart_ks)
|
||||||
|
|
||||||
|
lock_screen = self._gtk.Button("lock", _("Lock"), "color3")
|
||||||
|
lock_screen.connect("clicked", self._screen.lock_screen.lock)
|
||||||
|
|
||||||
self.main = Gtk.Grid(row_homogeneous=True, column_homogeneous=True)
|
self.main = Gtk.Grid(row_homogeneous=True, column_homogeneous=True)
|
||||||
if self._printer and self._printer.state not in {'disconnected', 'startup', 'shutdown', 'error'}:
|
if self._printer and self._printer.state not in {'disconnected', 'startup', 'shutdown', 'error'}:
|
||||||
self.main.attach(estop, 0, 0, 1, 1)
|
self.main.attach(estop, 0, 0, 1, 2)
|
||||||
self.main.attach(restart_ks, 1, 0, 1, 1)
|
self.main.attach(restart_ks, 1, 0, 1, 1)
|
||||||
self.main.attach(poweroff, 0, 1, 1, 1)
|
self.main.attach(lock_screen, 2, 0, 1, 1)
|
||||||
self.main.attach(restart, 1, 1, 1, 1)
|
self.main.attach(poweroff, 1, 1, 1, 1)
|
||||||
|
self.main.attach(restart, 2, 1, 1, 1)
|
||||||
self.content.add(self.main)
|
self.content.add(self.main)
|
||||||
|
|
||||||
def reboot_poweroff(self, widget, method):
|
def reboot_poweroff(self, widget, method):
|
||||||
|
37
screen.py
37
screen.py
@@ -29,9 +29,11 @@ from ks_includes.KlippyGtk import KlippyGtk
|
|||||||
from ks_includes.printer import Printer
|
from ks_includes.printer import Printer
|
||||||
from ks_includes.widgets.keyboard import Keyboard
|
from ks_includes.widgets.keyboard import Keyboard
|
||||||
from ks_includes.widgets.prompts import Prompt
|
from ks_includes.widgets.prompts import Prompt
|
||||||
|
from ks_includes.widgets.lockscreen import LockScreen
|
||||||
from ks_includes.config import KlipperScreenConfig
|
from ks_includes.config import KlipperScreenConfig
|
||||||
from panels.base_panel import BasePanel
|
from panels.base_panel import BasePanel
|
||||||
|
|
||||||
|
|
||||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||||
|
|
||||||
klipperscreendir = pathlib.Path(__file__).parent.resolve()
|
klipperscreendir = pathlib.Path(__file__).parent.resolve()
|
||||||
@@ -77,6 +79,7 @@ class KlipperScreen(Gtk.Window):
|
|||||||
prompt = None
|
prompt = None
|
||||||
tempstore_timeout = None
|
tempstore_timeout = None
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
self.server_info = None
|
self.server_info = None
|
||||||
try:
|
try:
|
||||||
@@ -150,7 +153,9 @@ class KlipperScreen(Gtk.Window):
|
|||||||
self.set_icon_from_file(os.path.join(klipperscreendir, "styles", "icon.svg"))
|
self.set_icon_from_file(os.path.join(klipperscreendir, "styles", "icon.svg"))
|
||||||
self.base_panel = BasePanel(self)
|
self.base_panel = BasePanel(self)
|
||||||
self.change_theme(self.theme)
|
self.change_theme(self.theme)
|
||||||
self.add(self.base_panel.main_grid)
|
self.overlay = Gtk.Overlay()
|
||||||
|
self.add(self.overlay)
|
||||||
|
self.overlay.add_overlay(self.base_panel.main_grid)
|
||||||
self.show_all()
|
self.show_all()
|
||||||
self.update_cursor(self.show_cursor)
|
self.update_cursor(self.show_cursor)
|
||||||
min_ver = (3, 8)
|
min_ver = (3, 8)
|
||||||
@@ -167,6 +172,7 @@ class KlipperScreen(Gtk.Window):
|
|||||||
return
|
return
|
||||||
self.base_panel.activate()
|
self.base_panel.activate()
|
||||||
self.set_screenblanking_timeout(self._config.get_main_config().get('screen_blanking'))
|
self.set_screenblanking_timeout(self._config.get_main_config().get('screen_blanking'))
|
||||||
|
self.lock_screen = LockScreen(self)
|
||||||
self.log_notification("KlipperScreen Started", 1)
|
self.log_notification("KlipperScreen Started", 1)
|
||||||
self.initial_connection()
|
self.initial_connection()
|
||||||
|
|
||||||
@@ -639,8 +645,7 @@ class KlipperScreen(Gtk.Window):
|
|||||||
box = Gtk.Box(halign=Gtk.Align.CENTER, width_request=self.width, height_request=self.height)
|
box = Gtk.Box(halign=Gtk.Align.CENTER, width_request=self.width, height_request=self.height)
|
||||||
box.pack_start(close, True, True, 0)
|
box.pack_start(close, True, True, 0)
|
||||||
box.get_style_context().add_class("screensaver")
|
box.get_style_context().add_class("screensaver")
|
||||||
self.remove(self.base_panel.main_grid)
|
self.overlay.add_overlay(box)
|
||||||
self.add(box)
|
|
||||||
|
|
||||||
# Avoid leaving a cursor-handle
|
# Avoid leaving a cursor-handle
|
||||||
close.grab_focus()
|
close.grab_focus()
|
||||||
@@ -655,9 +660,8 @@ class KlipperScreen(Gtk.Window):
|
|||||||
if self.screensaver is None:
|
if self.screensaver is None:
|
||||||
return False
|
return False
|
||||||
logging.debug("Closing Screensaver")
|
logging.debug("Closing Screensaver")
|
||||||
self.remove(self.screensaver)
|
self.overlay.remove(self.screensaver)
|
||||||
self.screensaver = None
|
self.screensaver = None
|
||||||
self.add(self.base_panel.main_grid)
|
|
||||||
if self.use_dpms:
|
if self.use_dpms:
|
||||||
self.wake_screen()
|
self.wake_screen()
|
||||||
else:
|
else:
|
||||||
@@ -666,8 +670,8 @@ class KlipperScreen(Gtk.Window):
|
|||||||
logging.info(f"Restoring Dialog {dialog}")
|
logging.info(f"Restoring Dialog {dialog}")
|
||||||
dialog.show()
|
dialog.show()
|
||||||
self.gtk.set_cursor(self.show_cursor, window=self.get_window())
|
self.gtk.set_cursor(self.show_cursor, window=self.get_window())
|
||||||
self.show_all()
|
|
||||||
self.power_devices(None, self._config.get_main_config().get("screen_on_devices", ""), on=True)
|
self.power_devices(None, self._config.get_main_config().get("screen_on_devices", ""), on=True)
|
||||||
|
self.lock_screen.relock()
|
||||||
|
|
||||||
def check_dpms_state(self):
|
def check_dpms_state(self):
|
||||||
if not self.use_dpms:
|
if not self.use_dpms:
|
||||||
@@ -1187,12 +1191,16 @@ class KlipperScreen(Gtk.Window):
|
|||||||
self.remove_tempstore_timeout()
|
self.remove_tempstore_timeout()
|
||||||
return self.init_tempstore()
|
return self.init_tempstore()
|
||||||
|
|
||||||
def show_keyboard(self, entry=None, event=None):
|
def show_keyboard(self, entry=None, event=None, box=None, close_cb=None):
|
||||||
if entry is None:
|
if entry is None:
|
||||||
logging.debug("Error: no entry provided for keyboard")
|
logging.debug("Error: no entry provided for keyboard")
|
||||||
return
|
return
|
||||||
|
if box is None:
|
||||||
|
box = self.base_panel.content
|
||||||
|
if close_cb is None:
|
||||||
|
close_cb = self.remove_keyboard
|
||||||
if self.keyboard is not None:
|
if self.keyboard is not None:
|
||||||
self.remove_keyboard()
|
self.remove_keyboard(box=box)
|
||||||
entry.grab_focus()
|
entry.grab_focus()
|
||||||
kbd_grid = Gtk.Grid()
|
kbd_grid = Gtk.Grid()
|
||||||
kbd_grid.set_size_request(self.gtk.content_width, self.gtk.keyboard_height)
|
kbd_grid.set_size_request(self.gtk.content_width, self.gtk.keyboard_height)
|
||||||
@@ -1206,11 +1214,12 @@ class KlipperScreen(Gtk.Window):
|
|||||||
kbd_grid.set_column_homogeneous(True)
|
kbd_grid.set_column_homogeneous(True)
|
||||||
kbd_width = 2 if purpose == Gtk.InputPurpose.DIGITS else 3
|
kbd_width = 2 if purpose == Gtk.InputPurpose.DIGITS else 3
|
||||||
kbd_grid.attach(Gtk.Box(), 0, 0, 1, 1)
|
kbd_grid.attach(Gtk.Box(), 0, 0, 1, 1)
|
||||||
kbd_grid.attach(Keyboard(self, self.remove_keyboard, entry=entry), 1, 0, kbd_width, 1)
|
kbd = Keyboard(self, close_cb, entry=entry, box=box)
|
||||||
|
kbd_grid.attach(kbd, 1, 0, kbd_width, 1)
|
||||||
kbd_grid.attach(Gtk.Box(), kbd_width + 1, 0, 1, 1)
|
kbd_grid.attach(Gtk.Box(), kbd_width + 1, 0, 1, 1)
|
||||||
self.keyboard = {"box": kbd_grid}
|
self.keyboard = {"box": kbd_grid}
|
||||||
self.base_panel.content.pack_end(kbd_grid, False, False, 0)
|
box.pack_end(kbd_grid, False, False, 0)
|
||||||
self.base_panel.content.show_all()
|
box.show_all()
|
||||||
|
|
||||||
def _show_matchbox_keyboard(self, kbd_grid):
|
def _show_matchbox_keyboard(self, kbd_grid):
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
@@ -1240,12 +1249,14 @@ class KlipperScreen(Gtk.Window):
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
def remove_keyboard(self, entry=None, event=None):
|
def remove_keyboard(self, entry=None, event=None, box=None):
|
||||||
if self.keyboard is None:
|
if self.keyboard is None:
|
||||||
return
|
return
|
||||||
|
if box is None:
|
||||||
|
box = self.base_panel.content
|
||||||
if 'process' in self.keyboard:
|
if 'process' in self.keyboard:
|
||||||
os.kill(self.keyboard['process'].pid, SIGTERM)
|
os.kill(self.keyboard['process'].pid, SIGTERM)
|
||||||
self.base_panel.content.remove(self.keyboard['box'])
|
box.remove(self.keyboard['box'])
|
||||||
self.keyboard = None
|
self.keyboard = None
|
||||||
if entry:
|
if entry:
|
||||||
entry.set_sensitive(False) # Move the focus
|
entry.set_sensitive(False) # Move the focus
|
||||||
|
@@ -563,6 +563,24 @@ popover button {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lock
|
||||||
|
.lock button
|
||||||
|
.lock button:hover,
|
||||||
|
.lock button:focus,
|
||||||
|
.lock button:active {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: Transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lockscreen_entry {
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lockscreen_button {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
.screensaver,
|
.screensaver,
|
||||||
.screensaver button,
|
.screensaver button,
|
||||||
.screensaver button:hover,
|
.screensaver button:hover,
|
||||||
|
93
styles/colorized/images/lock.svg
Normal file
93
styles/colorized/images/lock.svg
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
id="svg957"
|
||||||
|
sodipodi:docname="lock.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs961" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview959"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13"
|
||||||
|
inkscape:cx="9.5384615"
|
||||||
|
inkscape:cy="10.692308"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="828"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg957"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
showguides="true">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="7.5334069,21.1875"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide1503"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="11.15053,22.721769"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide1505"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<path
|
||||||
|
d="M 7.625,12.125 V 8.3750002 C 7.625,7.1645835 8.0515627,6.1328127 8.904688,5.2796878 9.757812,4.4265626 10.789582,4 11.999998,4 13.210416,4 14.242188,4.4265626 15.095313,5.2796878 15.948438,6.1328127 16.375,7.1645835 16.375,8.3750002 V 12.125 Z m 1.75,0 h 5.25 V 8.3750002 C 14.625,7.6458336 14.369792,7.0260419 13.859375,6.5156251 13.348958,6.0052084 12.729166,5.75 11.999998,5.75 11.270833,5.75 10.651041,6.0052084 10.140624,6.5156251 9.630208,7.0260419 9.375,7.6458336 9.375,8.3750002 Z"
|
||||||
|
id="path233"
|
||||||
|
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#839496;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
sodipodi:nodetypes="csssssccccsssssc" />
|
||||||
|
<rect
|
||||||
|
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#839496;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="rect676"
|
||||||
|
width="12.25"
|
||||||
|
height="10.208334"
|
||||||
|
x="5.875"
|
||||||
|
y="10.895833" />
|
||||||
|
<rect
|
||||||
|
style="opacity:0.998;fill:#657b83;fill-opacity:1;stroke:none;stroke-width:2.00001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000000"
|
||||||
|
id="rect1039-5"
|
||||||
|
width="12.25"
|
||||||
|
height="3.0625"
|
||||||
|
x="5.875"
|
||||||
|
y="10.895833" />
|
||||||
|
<rect
|
||||||
|
style="opacity:0.998;fill:#657b83;fill-opacity:1;stroke:none;stroke-width:2.00001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000000"
|
||||||
|
id="rect1039-5-6"
|
||||||
|
width="12.25"
|
||||||
|
height="3.0625"
|
||||||
|
x="5.875"
|
||||||
|
y="18.041666" />
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#93a1a1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path1722"
|
||||||
|
cx="12"
|
||||||
|
cy="16"
|
||||||
|
r="3" />
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#839496;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path1722-0"
|
||||||
|
cx="12"
|
||||||
|
cy="16"
|
||||||
|
r="2" />
|
||||||
|
<rect
|
||||||
|
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#073642;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="rect1965"
|
||||||
|
width="1"
|
||||||
|
height="3"
|
||||||
|
x="11.5"
|
||||||
|
y="14.5" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
40
styles/material-dark/images/lock.svg
Normal file
40
styles/material-dark/images/lock.svg
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
id="svg957"
|
||||||
|
sodipodi:docname="lock.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs961" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview959"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13"
|
||||||
|
inkscape:cx="8.4230769"
|
||||||
|
inkscape:cy="13.615385"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="828"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg957"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:deskcolor="#505050" />
|
||||||
|
<path
|
||||||
|
d="m 6.75,21.1875 q -0.721876,0 -1.235938,-0.514062 Q 5,20.159375 5,19.4375 v -8.75 Q 5,9.9656252 5.514062,9.4515625 6.028124,8.9375001 6.75,8.9375001 H 7.625 V 7.1875002 Q 7.625,5.3718751 8.904688,4.0921878 10.184374,2.8125 11.999998,2.8125 q 1.815627,0 3.095315,1.2796878 Q 16.375,5.3718751 16.375,7.1875002 v 1.7499999 h 0.875 q 0.721875,0 1.235938,0.5140624 Q 19,9.9656252 19,10.6875 v 8.75 q 0,0.721875 -0.514062,1.235938 Q 17.971875,21.1875 17.25,21.1875 Z m 0,-1.75 h 10.5 v -8.75 H 6.75 Z m 5.249998,-2.625 q 0.721875,0 1.23594,-0.514062 Q 13.75,15.784375 13.75,15.062501 q 0,-0.721875 -0.514062,-1.235939 -0.514065,-0.514061 -1.23594,-0.514061 -0.721875,0 -1.235935,0.514061 Q 10.25,14.340626 10.25,15.062501 q 0,0.721874 0.514063,1.235937 0.51406,0.514062 1.235935,0.514062 z M 9.375,8.9375001 h 5.25 V 7.1875002 q 0,-1.0937499 -0.765625,-1.8593751 Q 13.09375,4.5625 11.999998,4.5625 10.90625,4.5625 10.140624,5.3281251 9.375,6.0937503 9.375,7.1875002 Z M 6.75,19.4375 v -8.75 z"
|
||||||
|
id="path233"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#e2e2e2;fill-opacity:1;stroke-width:0.999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
41
styles/material-darker/images/lock.svg
Normal file
41
styles/material-darker/images/lock.svg
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
id="svg957"
|
||||||
|
sodipodi:docname="lock.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs961" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview959"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13"
|
||||||
|
inkscape:cx="-1.6923077"
|
||||||
|
inkscape:cy="13.615385"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="828"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg957"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:deskcolor="#505050" />
|
||||||
|
<path
|
||||||
|
d="m 6.75,21.1875 c -0.4812507,0 -0.89323,-0.171354 -1.235938,-0.514062 C 5.171354,20.330729 5,19.91875 5,19.4375 v -8.75 C 5,10.20625 5.171354,9.794271 5.514062,9.4515625 5.85677,9.1088542 6.2687493,8.9375001 6.75,8.9375001 H 7.625 V 7.1875002 C 7.625,5.9770835 8.0515627,4.9453127 8.904688,4.0921878 9.757812,3.2390626 10.789582,2.8125 11.999998,2.8125 c 1.210418,0 2.24219,0.4265626 3.095315,1.2796878 C 15.948438,4.9453127 16.375,5.9770835 16.375,7.1875002 v 1.7499999 h 0.875 c 0.48125,0 0.893229,0.1713541 1.235938,0.5140624 C 18.828646,9.794271 19,10.20625 19,10.6875 v 8.75 c 0,0.48125 -0.171354,0.893229 -0.514062,1.235938 C 18.143229,21.016146 17.73125,21.1875 17.25,21.1875 Z m 5.249998,-4.375 c 0.48125,0 0.89323,-0.171354 1.23594,-0.514062 C 13.578646,15.955729 13.75,15.54375 13.75,15.062501 c 0,-0.48125 -0.171354,-0.89323 -0.514062,-1.235939 -0.34271,-0.342707 -0.75469,-0.514061 -1.23594,-0.514061 -0.48125,0 -0.893228,0.171354 -1.235935,0.514061 C 10.421354,14.169271 10.25,14.581251 10.25,15.062501 c 0,0.481249 0.171354,0.893228 0.514063,1.235937 0.342707,0.342708 0.754685,0.514062 1.235935,0.514062 z M 9.375,8.9375001 h 5.25 V 7.1875002 C 14.625,6.4583336 14.369792,5.8385419 13.859375,5.3281251 13.348958,4.8177084 12.729166,4.5625 11.999998,4.5625 c -0.729165,0 -1.348957,0.2552084 -1.859374,0.7656251 C 9.630208,5.8385419 9.375,6.4583336 9.375,7.1875002 Z"
|
||||||
|
id="path233"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#e2e2e2;fill-opacity:1;stroke-width:0.999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
sodipodi:nodetypes="sssssscssssscssssssssssssssssccsssssc" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
40
styles/material-light/images/lock.svg
Normal file
40
styles/material-light/images/lock.svg
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
id="svg957"
|
||||||
|
sodipodi:docname="lock.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs961" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview959"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13"
|
||||||
|
inkscape:cx="-1.6923077"
|
||||||
|
inkscape:cy="13.615385"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="828"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg957"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:deskcolor="#505050" />
|
||||||
|
<path
|
||||||
|
d="m 6.75,21.1875 q -0.721876,0 -1.235938,-0.514062 Q 5,20.159375 5,19.4375 v -8.75 Q 5,9.9656252 5.514062,9.4515625 6.028124,8.9375001 6.75,8.9375001 H 7.625 V 7.1875002 Q 7.625,5.3718751 8.904688,4.0921878 10.184374,2.8125 11.999998,2.8125 q 1.815627,0 3.095315,1.2796878 Q 16.375,5.3718751 16.375,7.1875002 v 1.7499999 h 0.875 q 0.721875,0 1.235938,0.5140624 Q 19,9.9656252 19,10.6875 v 8.75 q 0,0.721875 -0.514062,1.235938 Q 17.971875,21.1875 17.25,21.1875 Z m 0,-1.75 h 10.5 v -8.75 H 6.75 Z m 5.249998,-2.625 q 0.721875,0 1.23594,-0.514062 Q 13.75,15.784375 13.75,15.062501 q 0,-0.721875 -0.514062,-1.235939 -0.514065,-0.514061 -1.23594,-0.514061 -0.721875,0 -1.235935,0.514061 Q 10.25,14.340626 10.25,15.062501 q 0,0.721874 0.514063,1.235937 0.51406,0.514062 1.235935,0.514062 z M 9.375,8.9375001 h 5.25 V 7.1875002 q 0,-1.0937499 -0.765625,-1.8593751 Q 13.09375,4.5625 11.999998,4.5625 10.90625,4.5625 10.140624,5.3281251 9.375,6.0937503 9.375,7.1875002 Z M 6.75,19.4375 v -8.75 z"
|
||||||
|
id="path233"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
97
styles/z-bolt/images/lock.svg
Normal file
97
styles/z-bolt/images/lock.svg
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="64"
|
||||||
|
height="64"
|
||||||
|
viewBox="0 0 64 64"
|
||||||
|
version="1.1"
|
||||||
|
id="svg10"
|
||||||
|
sodipodi:docname="lock.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<metadata
|
||||||
|
id="metadata16">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title>folder</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs14" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#bfbfbf"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="828"
|
||||||
|
id="namedview12"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:pagecheckerboard="false"
|
||||||
|
inkscape:zoom="10.827586"
|
||||||
|
inkscape:cx="26.229299"
|
||||||
|
inkscape:cy="44.423567"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg10"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:deskcolor="#bfbfbf" />
|
||||||
|
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title
|
||||||
|
id="title2">folder</title>
|
||||||
|
<desc
|
||||||
|
id="desc4">Created with Sketch.</desc>
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path5114"
|
||||||
|
cx="31.929701"
|
||||||
|
cy="41.06234"
|
||||||
|
rx="4.3648357"
|
||||||
|
ry="4.4511104" />
|
||||||
|
<rect
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="rect602"
|
||||||
|
width="32"
|
||||||
|
height="27"
|
||||||
|
x="16"
|
||||||
|
y="27.5" />
|
||||||
|
<g
|
||||||
|
id="g745"
|
||||||
|
transform="translate(0,1)">
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path680"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="32"
|
||||||
|
sodipodi:cy="18"
|
||||||
|
sodipodi:rx="11"
|
||||||
|
sodipodi:ry="11"
|
||||||
|
sodipodi:start="3.1415927"
|
||||||
|
sodipodi:end="0"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="M 21,18 A 11,11 0 0 1 32,7 11,11 0 0 1 43,18"
|
||||||
|
sodipodi:open="true" />
|
||||||
|
<path
|
||||||
|
id="path738"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 43,18 v 8.5 M 21,18 v 8.5 h 22" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
Reference in New Issue
Block a user