feat: settings as separate window
This commit is contained in:
+12
-6
@@ -116,13 +116,19 @@ HTML-макеты → PNG: **headless Edge** (`--headless --screenshot`), он
|
||||
домена в конфиг; переключение галочек персистится
|
||||
- [x] URL-бар привязан к свойству (был захардкожен), метка чекбокса — домен
|
||||
|
||||
### E2 — страница настроек — ГОТОВО (базовая версия)
|
||||
### E2 — страница настроек — ГОТОВО (отдельное окно)
|
||||
|
||||
- [x] Переключение вид/настройки по кнопке cog; Esc в настройках = назад;
|
||||
env `BP_VIEW=settings` для скриншотов
|
||||
- [x] Список браузеров: иконка + имя + путь (elide), удаление корзиной
|
||||
- [x] Кнопка «Автодетект»: мерж найденных по пути, без дублей
|
||||
- [x] Запомненные домены (domain → browser) с удалением
|
||||
- [x] Настройки = **отдельное окно** `SettingsWindow` (760×560, обычная рамка,
|
||||
resizable; в маленьком пикере редактировать неудобно). То же событийное
|
||||
кольцо; Theme-глобал красит оба окна; модели шарятся (ModelRc один на оба)
|
||||
- [x] cog в пикере → показать окно (центрирование через invoke_from_event_loop —
|
||||
winit-окно реализуется лениво, как и у пикера)
|
||||
- [x] Две панели: браузеры (иконка/имя/путь/корзина) + запомненные домены
|
||||
(domain → browser/корзина); кнопка «Автодетект» (мерж по пути)
|
||||
- [x] Esc в настройках = закрыть окно; X работает по умолчанию
|
||||
- [x] env `BP_VIEW=settings` — запуск сразу с окном настроек (без пикера);
|
||||
нюанс: `run()` авто-показывает своё окно, поэтому в этом режиме цикл
|
||||
крутится на settings_window
|
||||
- [ ] Редактирование браузера (имя/путь/флаги через LineEdit) — следующий шаг
|
||||
- [ ] Чтение флагов из .lnk ярлыков (крейс `lnk`) — по желанию
|
||||
- [ ] Добавить логотипы Edge/Zen в logos/ (пересоздать набор из alrrr/browser-logos)
|
||||
|
||||
+58
-34
@@ -76,9 +76,9 @@ fn init(cfg: Config, url: Option<String>) -> State {
|
||||
|
||||
refresh_models(&browser_model, &remembered_model, &cfg.borrow());
|
||||
|
||||
if std::env::var("BP_VIEW").as_deref() == Ok("settings") {
|
||||
main_window.set_settings_open(true);
|
||||
}
|
||||
let settings_window = SettingsWindow::new().unwrap();
|
||||
settings_window.set_browsers(browser_model.clone().into());
|
||||
settings_window.set_remembered(remembered_model.clone().into());
|
||||
|
||||
main_window.set_current_url(
|
||||
url.clone().unwrap_or_else(|| "ku6epxboctuk.github.io".into()).into(),
|
||||
@@ -202,24 +202,20 @@ fn init(cfg: Config, url: Option<String>) -> State {
|
||||
});
|
||||
|
||||
main_window.on_settings_clicked({
|
||||
let main_window = main_window.clone_strong();
|
||||
let browser_model = browser_model.clone();
|
||||
let remembered_model = remembered_model.clone();
|
||||
let cfg = cfg.clone();
|
||||
let settings_window = settings_window.clone_strong();
|
||||
move || {
|
||||
refresh_models(&browser_model, &remembered_model, &cfg.borrow());
|
||||
main_window.set_settings_open(true);
|
||||
settings_window.show().unwrap();
|
||||
let weak = settings_window.as_weak();
|
||||
let _ = slint::invoke_from_event_loop(move || {
|
||||
if let Some(sw) = weak.upgrade() {
|
||||
winit::center_window(sw.window());
|
||||
sw.invoke_restore_focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
main_window.on_settings_closed({
|
||||
let main_window = main_window.clone_strong();
|
||||
move || {
|
||||
main_window.set_settings_open(false);
|
||||
}
|
||||
});
|
||||
|
||||
main_window.on_remove_browser({
|
||||
settings_window.on_remove_browser({
|
||||
let browser_model = browser_model.clone();
|
||||
let remembered_model = remembered_model.clone();
|
||||
let cfg = cfg.clone();
|
||||
@@ -232,7 +228,7 @@ fn init(cfg: Config, url: Option<String>) -> State {
|
||||
}
|
||||
});
|
||||
|
||||
main_window.on_remove_remembered({
|
||||
settings_window.on_remove_remembered({
|
||||
let browser_model = browser_model.clone();
|
||||
let remembered_model = remembered_model.clone();
|
||||
let cfg = cfg.clone();
|
||||
@@ -245,7 +241,7 @@ fn init(cfg: Config, url: Option<String>) -> State {
|
||||
}
|
||||
});
|
||||
|
||||
main_window.on_redetect_browsers({
|
||||
settings_window.on_redetect({
|
||||
let browser_model = browser_model.clone();
|
||||
let remembered_model = remembered_model.clone();
|
||||
let cfg = cfg.clone();
|
||||
@@ -268,21 +264,34 @@ fn init(cfg: Config, url: Option<String>) -> State {
|
||||
}
|
||||
});
|
||||
|
||||
settings_window.on_esc_pressed({
|
||||
let settings_window = settings_window.clone_strong();
|
||||
let main_window = main_window.clone_strong();
|
||||
move || {
|
||||
let _ = settings_window.window().hide();
|
||||
main_window.invoke_restore_focus();
|
||||
}
|
||||
});
|
||||
|
||||
main_window.on_esc_pressed({
|
||||
let main_window = main_window.clone_strong();
|
||||
move || {
|
||||
if main_window.get_settings_open() {
|
||||
main_window.set_settings_open(false);
|
||||
} else {
|
||||
let _ = main_window.window().hide();
|
||||
}
|
||||
let _ = main_window.window().hide();
|
||||
}
|
||||
});
|
||||
|
||||
settings_window.window().on_close_requested({
|
||||
let main_window = main_window.clone_strong();
|
||||
move || {
|
||||
main_window.invoke_restore_focus();
|
||||
slint::CloseRequestResponse::HideWindow
|
||||
}
|
||||
});
|
||||
|
||||
main_window.set_browser_model(browser_model.clone().into());
|
||||
main_window.set_remembered_list(remembered_model.clone().into());
|
||||
State {
|
||||
main_window,
|
||||
settings_window,
|
||||
browser_model,
|
||||
remembered_model,
|
||||
config: cfg,
|
||||
@@ -291,6 +300,7 @@ fn init(cfg: Config, url: Option<String>) -> State {
|
||||
|
||||
pub struct State {
|
||||
pub main_window: MainWindow,
|
||||
pub settings_window: SettingsWindow,
|
||||
pub browser_model: Rc<slint::VecModel<BrowserConfig>>,
|
||||
pub remembered_model: Rc<slint::VecModel<RememberedEntry>>,
|
||||
pub config: Rc<RefCell<Config>>,
|
||||
@@ -316,15 +326,29 @@ pub fn main() {
|
||||
}
|
||||
|
||||
let state = init(cfg, url);
|
||||
let main_window = state.main_window.clone_strong();
|
||||
main_window.show().unwrap();
|
||||
|
||||
let weak = main_window.as_weak();
|
||||
let _ = slint::invoke_from_event_loop(move || {
|
||||
if let Some(mw) = weak.upgrade() {
|
||||
winit::center_window(mw.window());
|
||||
}
|
||||
});
|
||||
if std::env::var("BP_VIEW").as_deref() == Ok("settings") {
|
||||
state.settings_window.show().unwrap();
|
||||
let weak = state.settings_window.as_weak();
|
||||
let _ = slint::invoke_from_event_loop(move || {
|
||||
if let Some(sw) = weak.upgrade() {
|
||||
winit::center_window(sw.window());
|
||||
sw.invoke_restore_focus();
|
||||
}
|
||||
});
|
||||
state.settings_window.run().unwrap();
|
||||
} else {
|
||||
let main_window = state.main_window.clone_strong();
|
||||
main_window.show().unwrap();
|
||||
|
||||
main_window.run().unwrap();
|
||||
let weak = main_window.as_weak();
|
||||
let _ = slint::invoke_from_event_loop(move || {
|
||||
if let Some(mw) = weak.upgrade() {
|
||||
winit::center_window(mw.window());
|
||||
mw.invoke_restore_focus();
|
||||
}
|
||||
});
|
||||
|
||||
state.main_window.run().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
+12
-29
@@ -2,11 +2,12 @@ import { Button, CheckBox, ListView } from "std-widgets.slint";
|
||||
import { BrowserItem } from "./browser_item.slint";
|
||||
import { Header } from "./header.slint";
|
||||
import { Footer } from "./footer.slint";
|
||||
import { SettingsView } from "./settings.slint";
|
||||
import { BrowserConfig, RememberedEntry } from "./types.slint";
|
||||
import { BrowserConfig } from "./types.slint";
|
||||
import { Theme } from "theme.slint";
|
||||
|
||||
export { Theme }
|
||||
export { SettingsWindow } from "./settings.slint";
|
||||
export { RememberedEntry } from "./types.slint";
|
||||
|
||||
component CheckRow inherits Rectangle {
|
||||
in property <string> label;
|
||||
@@ -63,17 +64,11 @@ export component MainWindow inherits Window {
|
||||
in-out property <bool> remember-choice: false;
|
||||
in-out property <bool> always-ask: true;
|
||||
in property <int> selected-index: 0;
|
||||
in property <[RememberedEntry]> remembered-list: [];
|
||||
in-out property <bool> settings-open: false;
|
||||
|
||||
callback launch-browser(BrowserConfig);
|
||||
callback toggle-remember(bool);
|
||||
callback toggle-always-ask(bool);
|
||||
callback settings-clicked();
|
||||
callback settings-closed();
|
||||
callback remove-browser(string);
|
||||
callback remove-remembered(string);
|
||||
callback redetect-browsers();
|
||||
callback open-clicked();
|
||||
callback request-drag();
|
||||
callback esc-pressed();
|
||||
@@ -83,9 +78,10 @@ export component MainWindow inherits Window {
|
||||
width: 488px;
|
||||
height: 800px;
|
||||
default-font-family: "Segoe UI";
|
||||
|
||||
FocusScope {
|
||||
init => { self.focus(); }
|
||||
scope := FocusScope {
|
||||
init => {
|
||||
self.focus();
|
||||
}
|
||||
key-pressed(event) => {
|
||||
if (event.text == Key.Escape) {
|
||||
root.esc-pressed();
|
||||
@@ -96,6 +92,10 @@ export component MainWindow inherits Window {
|
||||
}
|
||||
}
|
||||
|
||||
callback restore-focus();
|
||||
restore-focus => {
|
||||
scope.focus();
|
||||
}
|
||||
VerticalLayout {
|
||||
alignment: start;
|
||||
width: 488px;
|
||||
@@ -113,24 +113,7 @@ export component MainWindow inherits Window {
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-main;
|
||||
|
||||
if root.settings-open: SettingsView {
|
||||
browsers: root.browser-model;
|
||||
remembered: root.remembered-list;
|
||||
back => {
|
||||
root.settings-closed();
|
||||
}
|
||||
remove-browser(name) => {
|
||||
root.remove-browser(name);
|
||||
}
|
||||
remove-remembered(domain) => {
|
||||
root.remove-remembered(domain);
|
||||
}
|
||||
redetect => {
|
||||
root.redetect-browsers();
|
||||
}
|
||||
}
|
||||
|
||||
if !root.settings-open: VerticalLayout {
|
||||
VerticalLayout {
|
||||
|
||||
Header {
|
||||
url: current-url;
|
||||
|
||||
+195
-193
@@ -2,231 +2,233 @@ import { ListView } from "std-widgets.slint";
|
||||
import { Theme } from "./theme.slint";
|
||||
import { BrowserConfig, RememberedEntry } from "./types.slint";
|
||||
|
||||
export component SettingsView inherits Rectangle {
|
||||
export component SettingsWindow inherits Window {
|
||||
title: "bropicker — настройки";
|
||||
width: 760px;
|
||||
height: 560px;
|
||||
background: Theme.surface-main;
|
||||
default-font-family: "Segoe UI";
|
||||
|
||||
in property <[BrowserConfig]> browsers;
|
||||
in property <[RememberedEntry]> remembered;
|
||||
callback back();
|
||||
callback remove-browser(string);
|
||||
callback remove-remembered(string);
|
||||
callback redetect();
|
||||
callback esc-pressed();
|
||||
|
||||
background: transparent;
|
||||
scope := FocusScope {
|
||||
init => {
|
||||
self.focus();
|
||||
}
|
||||
key-pressed(event) => {
|
||||
if (event.text == Key.Escape) {
|
||||
root.esc-pressed();
|
||||
accept
|
||||
} else {
|
||||
reject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback restore-focus();
|
||||
restore-focus => {
|
||||
scope.focus();
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
padding: 16px;
|
||||
spacing: 12px;
|
||||
padding: 20px;
|
||||
spacing: 14px;
|
||||
|
||||
Text {
|
||||
text: "Настройки";
|
||||
color: Theme.text-main;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 8px;
|
||||
spacing: 14px;
|
||||
|
||||
Rectangle {
|
||||
width: 32px;
|
||||
border-radius: 8px;
|
||||
background: back-touch.has-hover ? Theme.surface-hover : transparent;
|
||||
VerticalLayout {
|
||||
spacing: 8px;
|
||||
|
||||
back-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.back();
|
||||
HorizontalLayout {
|
||||
spacing: 8px;
|
||||
|
||||
Text {
|
||||
text: "Браузеры";
|
||||
color: Theme.text-muted;
|
||||
font-size: 13px;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
Rectangle {}
|
||||
|
||||
Rectangle {
|
||||
width: 110px;
|
||||
height: 26px;
|
||||
border-radius: 8px;
|
||||
background: redetect-touch.has-hover ? Theme.surface-hover : Theme.surface-elevated;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-main;
|
||||
|
||||
redetect-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.redetect();
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text: "Автодетект";
|
||||
color: redetect-touch.has-hover ? Theme.text-main : Theme.text-control;
|
||||
font-size: 12px;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
source: @image-url("../icons/arrow_left.svg");
|
||||
colorize: back-touch.has-hover ? Theme.text-main : Theme.text-muted;
|
||||
Rectangle {
|
||||
vertical-stretch: 1;
|
||||
border-radius: 12px;
|
||||
background: Theme.surface-elevated;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-main;
|
||||
clip: true;
|
||||
|
||||
ListView {
|
||||
for b in root.browsers: Rectangle {
|
||||
height: 56px;
|
||||
background: transparent;
|
||||
|
||||
HorizontalLayout {
|
||||
padding-left: 14px;
|
||||
padding-right: 10px;
|
||||
spacing: 12px;
|
||||
|
||||
Image {
|
||||
width: 26px;
|
||||
y: (parent.height - self.height) / 2;
|
||||
source: b.icon;
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
horizontal-stretch: 1;
|
||||
alignment: center;
|
||||
|
||||
Text {
|
||||
text: b.name;
|
||||
color: Theme.text-main;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
Text {
|
||||
text: b.path;
|
||||
color: Theme.text-hint;
|
||||
font-size: 11px;
|
||||
font-family: "Consolas";
|
||||
overflow: elide;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 30px;
|
||||
border-radius: 6px;
|
||||
background: del-touch.has-hover ? #ef444420 : transparent;
|
||||
|
||||
del-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.remove-browser(b.name);
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
source: @image-url("../icons/trash.svg");
|
||||
colorize: del-touch.has-hover ? #ef4444 : Theme.text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
alignment: center;
|
||||
spacing: 8px;
|
||||
|
||||
Text {
|
||||
text: "Настройки";
|
||||
color: Theme.text-main;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 8px;
|
||||
|
||||
Text {
|
||||
text: "Браузеры";
|
||||
color: Theme.text-muted;
|
||||
font-size: 13px;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
Rectangle {}
|
||||
|
||||
Rectangle {
|
||||
width: 120px;
|
||||
height: 26px;
|
||||
border-radius: 8px;
|
||||
background: redetect-touch.has-hover ? Theme.surface-hover : Theme.surface-elevated;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-main;
|
||||
|
||||
redetect-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.redetect();
|
||||
}
|
||||
text: "Запомненные домены";
|
||||
color: Theme.text-muted;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
Text {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text: "Автодетект";
|
||||
color: redetect-touch.has-hover ? Theme.text-main : Theme.text-control;
|
||||
font-size: 12px;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
vertical-stretch: 1;
|
||||
border-radius: 12px;
|
||||
background: Theme.surface-elevated;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-main;
|
||||
clip: true;
|
||||
|
||||
Rectangle {
|
||||
vertical-stretch: 3;
|
||||
border-radius: 8px;
|
||||
background: Theme.surface-elevated;
|
||||
clip: true;
|
||||
|
||||
ListView {
|
||||
for b in root.browsers: Rectangle {
|
||||
height: 52px;
|
||||
background: transparent;
|
||||
|
||||
HorizontalLayout {
|
||||
padding-left: 12px;
|
||||
padding-right: 8px;
|
||||
spacing: 10px;
|
||||
|
||||
Image {
|
||||
width: 22px;
|
||||
y: (parent.height - self.height) / 2;
|
||||
source: b.icon;
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
horizontal-stretch: 1;
|
||||
alignment: center;
|
||||
|
||||
Text {
|
||||
text: b.name;
|
||||
color: Theme.text-main;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
Text {
|
||||
text: b.path;
|
||||
color: Theme.text-hint;
|
||||
font-size: 11px;
|
||||
font-family: "Consolas";
|
||||
overflow: elide;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 28px;
|
||||
border-radius: 6px;
|
||||
background: del-touch.has-hover ? #ef444420 : transparent;
|
||||
|
||||
del-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.remove-browser(b.name);
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
source: @image-url("../icons/trash.svg");
|
||||
colorize: del-touch.has-hover ? #ef4444 : Theme.text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Запомненные домены";
|
||||
color: Theme.text-muted;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
vertical-stretch: 2;
|
||||
border-radius: 8px;
|
||||
background: Theme.surface-elevated;
|
||||
clip: true;
|
||||
|
||||
ListView {
|
||||
for r in root.remembered: Rectangle {
|
||||
height: 40px;
|
||||
background: transparent;
|
||||
|
||||
HorizontalLayout {
|
||||
padding-left: 12px;
|
||||
padding-right: 8px;
|
||||
spacing: 10px;
|
||||
|
||||
VerticalLayout {
|
||||
horizontal-stretch: 1;
|
||||
alignment: center;
|
||||
ListView {
|
||||
for r in root.remembered: Rectangle {
|
||||
height: 44px;
|
||||
background: transparent;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 6px;
|
||||
padding-left: 14px;
|
||||
padding-right: 10px;
|
||||
spacing: 12px;
|
||||
|
||||
Text {
|
||||
text: r.domain;
|
||||
color: Theme.text-main;
|
||||
font-size: 13px;
|
||||
font-family: "Consolas";
|
||||
vertical-alignment: center;
|
||||
VerticalLayout {
|
||||
horizontal-stretch: 1;
|
||||
alignment: center;
|
||||
|
||||
Text {
|
||||
text: r.domain;
|
||||
color: Theme.text-main;
|
||||
font-size: 14px;
|
||||
font-family: "Consolas";
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "→ " + r.browser;
|
||||
color: Theme.text-hint;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "→ " + r.browser;
|
||||
color: Theme.text-hint;
|
||||
font-size: 12px;
|
||||
vertical-alignment: center;
|
||||
Rectangle {
|
||||
width: 30px;
|
||||
border-radius: 6px;
|
||||
background: del2-touch.has-hover ? #ef444420 : transparent;
|
||||
|
||||
del2-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.remove-remembered(r.domain);
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
source: @image-url("../icons/trash.svg");
|
||||
colorize: del2-touch.has-hover ? #ef4444 : Theme.text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 28px;
|
||||
border-radius: 6px;
|
||||
background: del2-touch.has-hover ? #ef444420 : transparent;
|
||||
|
||||
del2-touch := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.remove-remembered(r.domain);
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
source: @image-url("../icons/trash.svg");
|
||||
colorize: del2-touch.has-hover ? #ef4444 : Theme.text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user