Merge pull request #134 from an-anime-team/next

Release 3.5.2
This commit is contained in:
Observer KRypt0n_ 2023-04-17 19:14:01 +02:00 committed by GitHub
commit dceb4ea188
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 361 additions and 130 deletions

View file

@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Added arguments and symlinks editor to sandbox settings
### Fixed
- Fixed game running issue if you have spaces in paths
## [3.5.1] (hotfix) - 16.04.2023
### Fixed

8
Cargo.lock generated
View file

@ -40,8 +40,8 @@ dependencies = [
[[package]]
name = "anime-game-core"
version = "1.7.0"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.7.0#290cc5ff9399f68799e8e00fd3f78fa26d076296"
version = "1.7.1"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.7.1#8978728ce5d94aec5c6aecfe470e45fc43d5b522"
dependencies = [
"anyhow",
"bzip2",
@ -87,8 +87,8 @@ dependencies = [
[[package]]
name = "anime-launcher-sdk"
version = "1.0.2"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.0.2#979ca46f5b4ba8961b0effa4e35ba8f8069c9607"
version = "1.0.6"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.0.6#2a8272c1afdd006925c150ac480a82be645f4b52"
dependencies = [
"anime-game-core",
"anyhow",

View file

@ -17,7 +17,7 @@ glib-build-tools = "0.17"
[dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/anime-launcher-sdk"
tag = "1.0.2"
tag = "1.0.6"
features = ["all", "genshin"]
# path = "../anime-launcher-sdk" # ! for dev purposes only
@ -30,7 +30,7 @@ adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }
rfd = { version = "0.11", features = ["xdg-portal"], default-features = false }
open = "4.0"
serde_json = "1"
serde_json = "1.0"
anyhow = "1.0"
lazy_static = "1.4.0"
cached = { version = "0.43", features = ["proc_macro"] }

View file

@ -37,6 +37,11 @@ dxvk-unpack-error = Entpacken von DXVK fehlgeschlagen
dxvk-apply-error = DXVK konnte nicht angewendet werden
downloaded-wine-list-failed = Auflistung der heruntergeladenen Wine versionen fehlgeschlagen
patch-sync-failed = Synchronisierung des Patch-Ordners fehlgeschlagen
patch-state-check-failed = Status des Patchordners konnte nicht überprüft werden
game-patching-error = Spiel konnte nicht gepatcht werden
# Sandbox
documentation-url-open-failed = Failed to open documentation URL

View file

@ -8,6 +8,7 @@ hide-home-directory = Hide home directory
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
hostname = Hostname
additional-arguments = Additional arguments
private-directories = Private directories
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
@ -22,3 +23,6 @@ new-path = New path
read-only = Read-only
read-only-description = Forbid game to write any data to this directory
symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox

View file

@ -41,3 +41,7 @@ downloaded-wine-list-failed = Failed to list downloaded wine versions
patch-sync-failed = Failed to sync patch folder
patch-state-check-failed = Failed to check patch folder state
game-patching-error = Failed to patch game
# Sandbox
documentation-url-open-failed = Failed to open documentation URL

View file

@ -8,6 +8,7 @@ hide-home-directory = Hide home directory
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
hostname = Hostname
additional-arguments = Additional arguments
private-directories = Private directories
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
@ -22,3 +23,6 @@ new-path = New path
read-only = Read-only
read-only-description = Forbid game to write any data to this directory
symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox

View file

@ -41,3 +41,7 @@ downloaded-wine-list-failed = Fallo al listar versiones descargadas de Wine
patch-sync-failed = Fallo al sincronizar carpeta del parche
patch-state-check-failed = Fallo al comprobar estado de carpeta del parche
game-patching-error = Fallo al parchear el juego
# Sandbox
documentation-url-open-failed = Failed to open documentation URL

View file

@ -69,7 +69,7 @@ registry-editor = Editor del Registro
explorer = Explorador
task-manager = Administrador de Tareas
configuration = Configuración
debugger = Debugger
debugger = Depurador
dxvk-version = Versión de DXVK
dxvk-selection-disabled = La selección de DXVK está deshabilitada por las preferencias de su grupo de vinos

View file

@ -1,24 +1,28 @@
sandbox = Sandbox
sandbox-description = Run the game in isolated environment, preventing it from accessing your personal data
sandbox = Aislamiento
sandbox-description = Ejecutar el juego en un entorno aislado, previniendo el acceso a datos personales
enable-sandboxing = Enable sandboxing
enable-sandboxing-description = Run the game in read-only copy of your root filesystem
enable-sandboxing = Activar aislamiento
enable-sandboxing-description = Ejecutar el juego en una copia de sólo lectura de tu sistema de archivos
hide-home-directory = Hide home directory
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
hide-home-directory = Esconder el directorio home
hide-home-directory-description = Aisla las carpetas /home, /var/home/$USER, y $HOME del juego
hostname = Hostname
hostname = Nombre del host
additional-arguments = Additional arguments
private-directories = Private directories
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
private-directories = Directorios privados
private-directories-description = Estas carpetas serán reemplazadas por un sistema de archivos virtual (tmpfs) vacío, y su contenido real no será accesible al juego aislado
path = Path
path = Ruta
shared-directories = Shared directories
shared-directories-description = These directories will be symlinked to directories in your host system
shared-directories = Directorios compartidos
shared-directories-description = Estos directorios serán enlazados a directorios de tu sistema anfitrión
original-path = Original path
new-path = New path
original-path = Ruta original
new-path = Nueva ruta
read-only = Read-only
read-only-description = Forbid game to write any data to this directory
read-only = Sólo lectura
read-only-description = Le prohibe al juego escribir datos en este directorio
symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox

View file

@ -41,3 +41,7 @@ downloaded-wine-list-failed = Impossible de lister les versions de wine téléch
patch-sync-failed = Impossible de synchroniser le patch
patch-state-check-failed = Impossible de déterminer l'état du patch
game-patching-error = Le patch du jeu a échoué
# Sandbox
documentation-url-open-failed = Failed to open documentation URL

View file

@ -8,6 +8,7 @@ hide-home-directory = Hide home directory
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
hostname = Hostname
additional-arguments = Additional arguments
private-directories = Private directories
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
@ -22,3 +23,6 @@ new-path = New path
read-only = Read-only
read-only-description = Forbid game to write any data to this directory
symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox

View file

@ -41,3 +41,7 @@ downloaded-wine-list-failed = Не удалось получить список
patch-sync-failed = Ошибка синхронизации папки патча
patch-state-check-failed = Ошибка проверки статуса папки патча
game-patching-error = Не удалось установить патч игры
# Sandbox
documentation-url-open-failed = Не удалось открыть ссылку с документацией

View file

@ -8,6 +8,7 @@ hide-home-directory = Скрыть домашнюю директорию
hide-home-directory-description = Изолировать ваши директории /home, /var/home/$USER, и $HOME от игры
hostname = Имя хоста
additional-arguments = Дополнительные аргументы
private-directories = Приватные директории
private-directories-description = Эти папки будут заменены пустой виртуальной файловой системой (tmpfs) и их изначальное содержимое не будет доступно игре
@ -22,3 +23,6 @@ new-path = Путь в песочнице
read-only = Только для чтения
read-only-description = Запретить игре изменять содержимое этой директории
symlinks = Ссылки
symlinks-description = Добавить ссылку на оригинальный файл или папку в вашу песочницу

View file

@ -41,3 +41,7 @@ downloaded-wine-list-failed = İndirilmiş Wine versiyonlarını listeleme başa
patch-sync-failed = Yama dosyalarını senkronize etme başarısız oldu
patch-state-check-failed = Yama dosyalarının durumunu kontrol etme başarısız oldu
game-patching-error = Yamayı uygulamada sorun çıktı
# Sandbox
documentation-url-open-failed = Failed to open documentation URL

View file

@ -8,6 +8,7 @@ hide-home-directory = Hide home directory
hide-home-directory-description = Isolate your /home, /var/home/$USER, and $HOME folders from the game
hostname = Hostname
additional-arguments = Additional arguments
private-directories = Private directories
private-directories-description = These folders will be replaced by an empty virtual filesystem (tmpfs), and their original content will not be available to sandboxed game
@ -22,3 +23,6 @@ new-path = New path
read-only = Read-only
read-only-description = Forbid game to write any data to this directory
symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox

View file

@ -41,3 +41,7 @@ downloaded-wine-list-failed = 列举 Wine 版本失败
patch-sync-failed = 同步补丁文件夹失败
patch-state-check-failed = 检查补丁文件夹失败
game-patching-error = 应用游戏补丁失败
# Sandbox
documentation-url-open-failed = Failed to open documentation URL

View file

@ -8,6 +8,7 @@ hide-home-directory = 隐藏家目录
hide-home-directory-description = 将 /home、 /var/home/$USER 和 $HOME 目录与游戏隔离
hostname = 主机名
additional-arguments = Additional arguments
private-directories = 隐私目录
private-directories-description = 这些目录将会被空的虚拟文件系统tmpfs替代其中的原始内容不可被沙盒中的游戏访问
@ -22,3 +23,6 @@ new-path = 新路径
read-only = 只读
read-only-description = 禁止游戏向此目录写入任何数据
symlinks = Symlinks
symlinks-description = Symlink original path to the new one inside of your sandbox

74
fluentscan.py Normal file
View file

@ -0,0 +1,74 @@
#!/usr/bin/python
# Author: @xstraok
# Modified by Observer KRypt0n_ <https://github.com/krypt0nn>
import os
import sys
path = "assets/locales/" + sys.argv[1] + "/"
for filename in os.listdir("assets/locales/en"):
with open(os.path.join("assets/locales/en", filename), 'r') as locale_file:
created_locale = open(path + filename)
def to_dict(text):
result={}
for i in text:
if " = " in i:
try:
result[i.split()[0]] = ' '.join(i.split()[2:])
except:
pass
elif i:
result[list(result.keys())[-1]] += i
return result
def dict_compare(d1, d2):
d1_keys = set(d1.keys())
d2_keys = set(d2.keys())
shared_keys = d1_keys.intersection(d2_keys)
added = d1_keys - d2_keys
removed = d2_keys - d1_keys
modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
same = set(o for o in shared_keys if d1[o] == d2[o])
return added, removed, modified, same
expected=to_dict(locale_file)
expected2=to_dict(created_locale)
# TODO: why modified is not used?
added, removed, modified, same = dict_compare(expected, expected2)
if added or removed or same:
print(f"[{created_locale.name[15:]}]")
if added:
print(" [Added]")
for i in added:
print(f" {i} = {expected[i]}")
if removed:
print(" [Removed]")
for i in removed:
print(f" {i} = {expected2[i]}")
#workaround
if same and same != "set()":
print(" [Untranslated]")
for i in same:
print(f" {i} = {expected[i]}")
print("")

View file

@ -82,10 +82,16 @@ impl SimpleComponent for AboutDialog {
set_release_notes_version: &APP_VERSION,
set_release_notes: &[
"<p>Added</p>",
"<ul>",
"<li>Added arguments and symlinks editor to sandbox settings</li>",
"</ul>",
"<p>Fixed</p>",
"<ul>",
"<li>Fixed telemetry checking</li>",
"<li>Fixed game running issue if you have spaces in paths</li>",
"</ul>",
].join("\n"),

View file

@ -172,6 +172,9 @@ impl SimpleAsyncComponent for EnvironmentApp {
let value = self.value_entry.text().trim().to_string();
if !name.is_empty() && !value.is_empty() {
self.name_entry.set_text("");
self.value_entry.set_text("");
config.game.environment.insert(name.clone(), value.clone());
Config::update(config);

View file

@ -103,7 +103,7 @@ impl SimpleAsyncComponent for PreferencesApp {
sandbox: SandboxApp::builder()
.launch(())
.detach(),
.forward(sender.input_sender(), std::convert::identity),
environment: EnvironmentApp::builder()
.launch(())

View file

@ -6,119 +6,86 @@ use adw::prelude::*;
use anime_launcher_sdk::is_available;
use super::main::PreferencesAppMsg;
use crate::i18n::tr;
use crate::*;
#[derive(Debug)]
struct PrivateDirectory {
path: String
}
macro_rules! impl_directory {
($name:ident, $msg:expr) => {
#[derive(Debug)]
struct $name {
from: String,
to: Option<String>
}
#[relm4::factory(async)]
impl AsyncFactoryComponent for PrivateDirectory {
type Init = String;
type Input = SandboxAppMsg;
type Output = SandboxAppMsg;
type CommandOutput = ();
type ParentInput = SandboxAppMsg;
type ParentWidget = adw::PreferencesGroup;
#[relm4::factory(async)]
impl AsyncFactoryComponent for $name {
type Init = (String, Option<String>);
type Input = SandboxAppMsg;
type Output = SandboxAppMsg;
type CommandOutput = ();
type ParentInput = SandboxAppMsg;
type ParentWidget = adw::PreferencesGroup;
view! {
root = adw::ActionRow {
set_title: &self.path,
view! {
root = adw::ActionRow {
set_title: &self.from,
set_subtitle: match self.to.as_ref() {
Some(to) => to,
None => ""
},
add_suffix = &gtk::Button {
set_icon_name: "user-trash-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
add_suffix = &gtk::Button {
set_icon_name: "user-trash-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| {
sender.input(SandboxAppMsg::RemovePrivate(index.clone()));
connect_clicked[sender, index] => move |_| {
sender.input($msg(index.clone()));
}
}
}
}
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model(
init: Self::Init,
_index: &DynamicIndex,
_sender: AsyncFactorySender<Self>,
) -> Self {
Self {
from: init.0,
to: init.1
}
}
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
sender.output(msg);
}
}
}
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model(
init: Self::Init,
_index: &DynamicIndex,
_sender: AsyncFactorySender<Self>,
) -> Self {
Self {
path: init
}
}
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
sender.output(msg);
}
}
#[derive(Debug)]
struct SharedDirectory {
mount_from: String,
mount_to: String
}
#[relm4::factory(async)]
impl AsyncFactoryComponent for SharedDirectory {
type Init = (String, String);
type Input = SandboxAppMsg;
type Output = SandboxAppMsg;
type CommandOutput = ();
type ParentInput = SandboxAppMsg;
type ParentWidget = adw::PreferencesGroup;
view! {
root = adw::ActionRow {
set_title: &self.mount_to,
set_subtitle: &self.mount_from,
add_suffix = &gtk::Button {
set_icon_name: "user-trash-symbolic",
add_css_class: "flat",
set_valign: gtk::Align::Center,
connect_clicked[sender, index] => move |_| {
sender.input(SandboxAppMsg::RemoveShared(index.clone()));
}
}
}
}
fn output_to_parent_input(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
async fn init_model(
init: Self::Init,
_index: &DynamicIndex,
_sender: AsyncFactorySender<Self>,
) -> Self {
Self {
mount_from: init.0,
mount_to: init.1
}
}
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
sender.output(msg);
}
}
impl_directory!(PrivateDirectory, SandboxAppMsg::RemovePrivate);
impl_directory!(SharedDirectory, SandboxAppMsg::RemoveShared);
impl_directory!(SymlinkPath, SandboxAppMsg::RemoveSymlink);
pub struct SandboxApp {
private_paths: AsyncFactoryVecDeque<PrivateDirectory>,
shared_paths: AsyncFactoryVecDeque<SharedDirectory>,
symlink_paths: AsyncFactoryVecDeque<SymlinkPath>,
private_path_entry: adw::EntryRow,
shared_path_from_entry: adw::EntryRow,
shared_path_to_entry: adw::EntryRow,
read_only_switch: gtk::Switch
read_only_switch: gtk::Switch,
symlink_path_from_entry: adw::EntryRow,
symlink_path_to_entry: adw::EntryRow
}
#[derive(Debug, Clone)]
@ -127,14 +94,17 @@ pub enum SandboxAppMsg {
RemovePrivate(DynamicIndex),
AddShared,
RemoveShared(DynamicIndex)
RemoveShared(DynamicIndex),
AddSymlink,
RemoveSymlink(DynamicIndex)
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for SandboxApp {
type Init = ();
type Input = SandboxAppMsg;
type Output = ();
type Output = PreferencesAppMsg;
view! {
adw::PreferencesPage {
@ -206,6 +176,39 @@ impl SimpleAsyncComponent for SandboxApp {
Config::update(config);
}
}
},
adw::EntryRow {
set_title: &tr("additional-arguments"),
set_text: CONFIG.sandbox.args.as_ref().unwrap_or(&String::new()).trim(),
connect_changed => |entry| {
if let Ok(mut config) = Config::get() {
let command = entry.text().trim().to_string();
config.sandbox.args = if command.is_empty() {
None
} else {
Some(command)
};
Config::update(config);
}
},
add_suffix = &gtk::Button {
set_valign: gtk::Align::Center,
set_icon_name: "dialog-information-symbolic",
connect_clicked[sender] => move |_| {
if let Err(err) = open::that("https://man.archlinux.org/man/bwrap.1") {
sender.output(PreferencesAppMsg::Toast {
title: tr("documentation-url-open-failed"),
description: Some(err.to_string())
}).unwrap();
}
}
}
}
},
@ -268,7 +271,35 @@ impl SimpleAsyncComponent for SandboxApp {
},
#[local_ref]
add = shared_paths -> adw::PreferencesGroup {}
add = shared_paths -> adw::PreferencesGroup {},
add = &adw::PreferencesGroup {
set_title: &tr("symlinks"),
set_description: Some(&tr("symlinks-description")),
#[local_ref]
symlink_path_from_entry -> adw::EntryRow {
set_title: &tr("original-path")
},
#[local_ref]
symlink_path_to_entry -> adw::EntryRow {
set_title: &tr("new-path")
},
gtk::Button {
set_label: &tr("add"),
add_css_class: "pill",
set_margin_top: 8,
set_halign: gtk::Align::Start,
connect_clicked => SandboxAppMsg::AddSymlink
}
},
#[local_ref]
add = symlink_paths -> adw::PreferencesGroup {}
}
}
@ -277,39 +308,51 @@ impl SimpleAsyncComponent for SandboxApp {
root: Self::Root,
sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
tracing::info!("Initializing environment settings");
tracing::info!("Initializing sandbox settings");
let mut model = Self {
private_paths: AsyncFactoryVecDeque::new(adw::PreferencesGroup::new(), sender.input_sender()),
shared_paths: AsyncFactoryVecDeque::new(adw::PreferencesGroup::new(), sender.input_sender()),
symlink_paths: AsyncFactoryVecDeque::new(adw::PreferencesGroup::new(), sender.input_sender()),
private_path_entry: adw::EntryRow::new(),
shared_path_from_entry: adw::EntryRow::new(),
shared_path_to_entry: adw::EntryRow::new(),
read_only_switch: gtk::Switch::new()
read_only_switch: gtk::Switch::new(),
symlink_path_from_entry: adw::EntryRow::new(),
symlink_path_to_entry: adw::EntryRow::new()
};
for path in &CONFIG.sandbox.private {
model.private_paths.guard().push_back(path.trim().to_string());
model.private_paths.guard().push_back((path.trim().to_string(), None));
}
for (from, to) in &CONFIG.sandbox.mounts.read_only {
model.shared_paths.guard().push_back((
from.trim().to_string(),
format!("[read-only] {}", to.trim())
Some(format!("[read-only] {}", to.trim()))
));
}
for (from, to) in &CONFIG.sandbox.mounts.bind {
model.shared_paths.guard().push_back((
from.trim().to_string(),
to.trim().to_string()
Some(to.trim().to_string())
));
}
for (from, to) in &CONFIG.sandbox.mounts.symlinks {
model.symlink_paths.guard().push_back((
from.trim().to_string(),
Some(to.trim().to_string())
));
}
let private_paths = model.private_paths.widget();
let shared_paths = model.shared_paths.widget();
let symlink_paths = model.symlink_paths.widget();
let private_path_entry = &model.private_path_entry;
@ -317,6 +360,9 @@ impl SimpleAsyncComponent for SandboxApp {
let shared_path_to_entry = &model.shared_path_to_entry;
let read_only_switch = &model.read_only_switch;
let symlink_path_from_entry = &model.symlink_path_from_entry;
let symlink_path_to_entry = &model.symlink_path_to_entry;
let widgets = view_output!();
AsyncComponentParts { model, widgets }
@ -329,11 +375,13 @@ impl SimpleAsyncComponent for SandboxApp {
let path = self.private_path_entry.text().trim().to_string();
if !path.is_empty() {
self.private_path_entry.set_text("");
config.sandbox.private.push(path.clone());
Config::update(config);
self.private_paths.guard().push_back(path);
self.private_paths.guard().push_back((path, None));
}
}
}
@ -341,7 +389,7 @@ impl SimpleAsyncComponent for SandboxApp {
SandboxAppMsg::RemovePrivate(index) => {
if let Ok(mut config) = Config::get() {
if let Some(var) = self.private_paths.guard().get(index.current_index()) {
config.sandbox.private.retain(|item| item != &var.path);
config.sandbox.private.retain(|item| item != &var.from);
Config::update(config);
}
@ -358,6 +406,9 @@ impl SimpleAsyncComponent for SandboxApp {
let read_only = self.read_only_switch.state();
if !from.is_empty() && !to.is_empty() {
self.shared_path_from_entry.set_text("");
self.shared_path_to_entry.set_text("");
if read_only {
config.sandbox.mounts.read_only.insert(from.clone(), to.clone());
} else {
@ -368,11 +419,11 @@ impl SimpleAsyncComponent for SandboxApp {
self.shared_paths.guard().push_back((
from,
if read_only {
Some(if read_only {
format!("[read-only] {}", to)
} else {
to
}
})
));
}
}
@ -381,14 +432,44 @@ impl SimpleAsyncComponent for SandboxApp {
SandboxAppMsg::RemoveShared(index) => {
if let Ok(mut config) = Config::get() {
if let Some(var) = self.shared_paths.guard().get(index.current_index()) {
config.sandbox.mounts.read_only.remove(&var.mount_from);
config.sandbox.mounts.bind.remove(&var.mount_from);
config.sandbox.mounts.read_only.remove(&var.from);
config.sandbox.mounts.bind.remove(&var.from);
Config::update(config);
}
self.shared_paths.guard().remove(index.current_index());
}
},
SandboxAppMsg::AddSymlink => {
if let Ok(mut config) = Config::get() {
let from = self.symlink_path_from_entry.text().trim().to_string();
let to = self.symlink_path_to_entry.text().trim().to_string();
if !from.is_empty() && !to.is_empty() {
self.symlink_path_from_entry.set_text("");
self.symlink_path_to_entry.set_text("");
config.sandbox.mounts.symlinks.insert(from.clone(), to.clone());
Config::update(config);
self.symlink_paths.guard().push_back((from, Some(to)));
}
}
}
SandboxAppMsg::RemoveSymlink(index) => {
if let Ok(mut config) = Config::get() {
if let Some(var) = self.symlink_paths.guard().get(index.current_index()) {
config.sandbox.mounts.symlinks.remove(&var.from);
Config::update(config);
}
self.symlink_paths.guard().remove(index.current_index());
}
}
}
}