From 87725bbb178c5e0e2c27dd7d8b3d258698316742 Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Wed, 28 Oct 2026 00:15:57 +0900 Subject: [PATCH] feat(toolbar): move a donut profile up or down the list (#522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filee opens the first profile in the list that has a file's extension, and a new profile goes in after the built-in ones, so a profile with .jpg never won over Images. The profile list in Settings → Donut toolbar now has Move up / Move down arrows under it, and Alt+↑ / Alt+↓ in the list do the same. A profile trades places only with one of its own kind (normal or mixed), since a normal profile always wins over a mixed one anyway; with a search typed, it passes the profile the list shows, not a hidden one. The order is the order of profiles.json, so nothing new is saved and no settings schema change is needed. "Reset to default" keeps the profile's place. The remark under the extension chips now says to move the profile above the other one, and turns into "this profile comes first" after the move. A caption under the list explains that the higher profile opens. Co-Authored-By: Claude Opus 5.5 --- src/Filee.App/Assets/i18n/ar.json | 5 +- src/Filee.App/Assets/i18n/de.json | 5 +- src/Filee.App/Assets/i18n/en.json | 5 +- src/Filee.App/Assets/i18n/es.json | 5 +- src/Filee.App/Assets/i18n/fr.json | 5 +- src/Filee.App/Assets/i18n/hi.json | 5 +- src/Filee.App/Assets/i18n/ja.json | 5 +- src/Filee.App/Assets/i18n/ko.json | 5 +- src/Filee.App/Assets/i18n/ne.json | 5 +- src/Filee.App/Assets/i18n/pl.json | 5 +- src/Filee.App/Assets/i18n/pt-BR.json | 5 +- src/Filee.App/Assets/i18n/pt-PT.json | 5 +- src/Filee.App/Assets/i18n/ru.json | 5 +- src/Filee.App/Assets/i18n/th.json | 5 +- src/Filee.App/Assets/i18n/tr.json | 5 +- src/Filee.App/Assets/i18n/zh-CN.json | 5 +- src/Filee.App/Assets/i18n/zh-TW.json | 5 +- .../ViewModels/Pages/ToolbarPageViewModel.cs | 61 +++++++- src/Filee.App/Views/Pages/ToolbarPage.axaml | 28 +++- src/Filee.Core/Profiles/ProfileOrder.cs | 56 +++++++ tests/Filee.App.Tests/RenderTests.cs | 55 +++++++ tests/Filee.App.Tests/ToolbarEditorTests.cs | 126 ++++++++++++++++ tests/Filee.Core.Tests/ProfileOrderTests.cs | 138 ++++++++++++++++++ 23 files changed, 529 insertions(+), 20 deletions(-) create mode 100644 src/Filee.Core/Profiles/ProfileOrder.cs create mode 100644 tests/Filee.Core.Tests/ProfileOrderTests.cs diff --git a/src/Filee.App/Assets/i18n/ar.json b/src/Filee.App/Assets/i18n/ar.json index 2e478d2ed..a59b45196 100644 --- a/src/Filee.App/Assets/i18n/ar.json +++ b/src/Filee.App/Assets/i18n/ar.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. اختر ملف تعريف", "toolbar.step_arrange": "2. رتّب الإعدادات المسبقة", "toolbar.add_profile": "ملف تعريف جديد", + "toolbar.profile_up": "نقل ملف التعريف لأعلى", + "toolbar.profile_down": "نقل ملف التعريف لأسفل", + "toolbar.profile_order_hint": "إذا اشترك ملفا تعريف في امتداد واحد، فسيُفتح الأعلى منهما في القائمة. يَنقل ‎Alt+↑ / Alt+↓‎ ملف التعريف المحدد.", "toolbar.profile_new": "ملف تعريف جديد", "toolbar.delete_profile": "حذف ملف التعريف", "toolbar.reset_profile": "استعادة الافتراضي", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "الامتداد {0} موجود في القائمة بالفعل.", "toolbar.ext_also_in": "موجود أيضًا في «{0}»", "toolbar.ext_in_profile": "في {0}", - "toolbar.ext_claimed_first": "{0}: موجود أيضًا في «{1}»، وهو أسبق في القائمة، لذلك ما زالت هذه الملفات تفتح «{1}».", + "toolbar.ext_claimed_first": "{0}: موجود أيضًا في «{1}»، وهو أسبق في القائمة، لذلك ما زالت هذه الملفات تفتح «{1}». انقل ملف التعريف هذا فوق «{1}» لتُفتح هنا.", "toolbar.ext_claimed_later": "{0}: موجود أيضًا في «{1}».\nملف التعريف هذا أسبق في القائمة، لذلك ستفتح هذه الملفات هذا الملف الآن.", "toolbar.ext_unknown": "{0}: لا يعرف Filee نوع الملف هذا.\nيمكنك الاحتفاظ به، لكن لا يمكن تحويل هذه الملفات.", "toolbar.ext_unknown_tip": "نوع ملف غير معروف", diff --git a/src/Filee.App/Assets/i18n/de.json b/src/Filee.App/Assets/i18n/de.json index bd6d41814..daefc0bec 100644 --- a/src/Filee.App/Assets/i18n/de.json +++ b/src/Filee.App/Assets/i18n/de.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. Profil auswählen", "toolbar.step_arrange": "2. Vorlagen anordnen", "toolbar.add_profile": "Neues Profil", + "toolbar.profile_up": "Profil nach oben", + "toolbar.profile_down": "Profil nach unten", + "toolbar.profile_order_hint": "Haben zwei Profile dieselbe Endung, öffnet das obere. Alt+↑ / Alt+↓ verschiebt das ausgewählte Profil.", "toolbar.profile_new": "Neues Profil", "toolbar.delete_profile": "Profil löschen", "toolbar.reset_profile": "Auf Standard zurücksetzen", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0} steht bereits in der Liste.", "toolbar.ext_also_in": "Auch in „{0}“", "toolbar.ext_in_profile": "in {0}", - "toolbar.ext_claimed_first": "{0}: auch in „{1}“. Dieses Profil steht weiter oben in der Liste, daher öffnen diese Dateien weiterhin „{1}“.", + "toolbar.ext_claimed_first": "{0}: auch in „{1}“. „{1}“ steht weiter oben in der Liste, daher öffnen diese Dateien weiterhin „{1}“. Schiebe dieses Profil darüber, damit sie hier geöffnet werden.", "toolbar.ext_claimed_later": "{0}: auch in „{1}“.\nDieses Profil steht weiter oben in der Liste, daher öffnen diese Dateien jetzt dieses Profil.", "toolbar.ext_unknown": "{0}: Filee kennt diesen Dateityp nicht.\nDu kannst ihn behalten, die Dateien lassen sich jedoch nicht konvertieren.", "toolbar.ext_unknown_tip": "Unbekannter Dateityp", diff --git a/src/Filee.App/Assets/i18n/en.json b/src/Filee.App/Assets/i18n/en.json index f41855faa..039fbef45 100644 --- a/src/Filee.App/Assets/i18n/en.json +++ b/src/Filee.App/Assets/i18n/en.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. Choose a profile", "toolbar.step_arrange": "2. Arrange presets", "toolbar.add_profile": "New profile", + "toolbar.profile_up": "Move profile up", + "toolbar.profile_down": "Move profile down", + "toolbar.profile_order_hint": "When two profiles share an extension, the higher one opens. Alt+↑ / Alt+↓ moves the selected profile.", "toolbar.profile_new": "New profile", "toolbar.delete_profile": "Delete profile", "toolbar.reset_profile": "Reset to default", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} is already in the list.", "toolbar.ext_also_in": "Also in “{0}”", "toolbar.ext_in_profile": "in {0}", - "toolbar.ext_claimed_first": "{0}: also in “{1}”, which comes first in the list, so these files still open “{1}”.", + "toolbar.ext_claimed_first": "{0}: also in “{1}”, which comes first in the list, so these files still open “{1}”. Move this profile above “{1}” to open them here.", "toolbar.ext_claimed_later": "{0}: also in “{1}”.\nThis profile comes first in the list, so these files now open this one instead.", "toolbar.ext_unknown": "{0}: Filee doesn't know this file type.\nYou can keep it, but these files can't be converted.", "toolbar.ext_unknown_tip": "Unknown file type", diff --git a/src/Filee.App/Assets/i18n/es.json b/src/Filee.App/Assets/i18n/es.json index 18f3d58d9..5ed50a700 100644 --- a/src/Filee.App/Assets/i18n/es.json +++ b/src/Filee.App/Assets/i18n/es.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. Elige un perfil", "toolbar.step_arrange": "2. Coloca los ajustes preestablecidos", "toolbar.add_profile": "Nuevo perfil", + "toolbar.profile_up": "Subir perfil", + "toolbar.profile_down": "Bajar perfil", + "toolbar.profile_order_hint": "Si dos perfiles comparten una extensión, se abre el que está más arriba. Alt+↑ / Alt+↓ mueve el perfil seleccionado.", "toolbar.profile_new": "Nuevo perfil", "toolbar.delete_profile": "Eliminar perfil", "toolbar.reset_profile": "Restablecer perfil", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0} ya está en la lista.", "toolbar.ext_also_in": "También en «{0}»", "toolbar.ext_in_profile": "en {0}", - "toolbar.ext_claimed_first": "{0}: también en «{1}», que va antes en la lista, así que estos archivos siguen abriendo «{1}».", + "toolbar.ext_claimed_first": "{0}: también en «{1}», que va antes en la lista, así que estos archivos siguen abriendo «{1}». Sube este perfil por encima de «{1}» para que se abran aquí.", "toolbar.ext_claimed_later": "{0}: también en «{1}».\nEste perfil va antes en la lista, así que ahora estos archivos abren este en su lugar.", "toolbar.ext_unknown": "{0}: Filee no conoce este tipo de archivo.\nPuedes conservarlo, pero estos archivos no se pueden convertir.", "toolbar.ext_unknown_tip": "Tipo de archivo desconocido", diff --git a/src/Filee.App/Assets/i18n/fr.json b/src/Filee.App/Assets/i18n/fr.json index c5d243b5e..a9049faff 100644 --- a/src/Filee.App/Assets/i18n/fr.json +++ b/src/Filee.App/Assets/i18n/fr.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. Choisir un profil", "toolbar.step_arrange": "2. Organiser les préréglages", "toolbar.add_profile": "Nouveau profil", + "toolbar.profile_up": "Monter le profil", + "toolbar.profile_down": "Descendre le profil", + "toolbar.profile_order_hint": "Si deux profils partagent une extension, c'est celui placé le plus haut qui s'ouvre. Alt+↑ / Alt+↓ déplace le profil sélectionné.", "toolbar.profile_new": "Nouveau profil", "toolbar.delete_profile": "Supprimer le profil", "toolbar.reset_profile": "Rétablir par défaut", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} est déjà dans la liste.", "toolbar.ext_also_in": "Aussi dans « {0} »", "toolbar.ext_in_profile": "dans {0}", - "toolbar.ext_claimed_first": "{0} : aussi dans « {1} », placé plus haut dans la liste ; ces fichiers ouvrent donc toujours « {1} ».", + "toolbar.ext_claimed_first": "{0} : aussi dans « {1} », placé plus haut dans la liste ; ces fichiers ouvrent donc toujours « {1} ». Placez ce profil au-dessus de « {1} » pour qu'ils s'ouvrent ici.", "toolbar.ext_claimed_later": "{0} : aussi dans « {1} ».\nCe profil est placé plus haut dans la liste : ces fichiers l'ouvrent désormais à la place.", "toolbar.ext_unknown": "{0} : Filee ne connaît pas ce type de fichier.\nVous pouvez le garder, mais ces fichiers ne pourront pas être convertis.", "toolbar.ext_unknown_tip": "Type de fichier inconnu", diff --git a/src/Filee.App/Assets/i18n/hi.json b/src/Filee.App/Assets/i18n/hi.json index a3e798a5e..725823a01 100644 --- a/src/Filee.App/Assets/i18n/hi.json +++ b/src/Filee.App/Assets/i18n/hi.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. प्रोफ़ाइल चुनें", "toolbar.step_arrange": "2. प्रीसेट व्यवस्थित करें", "toolbar.add_profile": "नई प्रोफ़ाइल", + "toolbar.profile_up": "प्रोफ़ाइल ऊपर ले जाएँ", + "toolbar.profile_down": "प्रोफ़ाइल नीचे ले जाएँ", + "toolbar.profile_order_hint": "अगर दो प्रोफ़ाइलों में एक ही एक्सटेंशन है, तो सूची में ऊपर वाली खुलती है। Alt+↑ / Alt+↓ से चुनी गई प्रोफ़ाइल ऊपर-नीचे होती है।", "toolbar.profile_new": "नई प्रोफ़ाइल", "toolbar.delete_profile": "प्रोफ़ाइल हटाएँ", "toolbar.reset_profile": "डिफ़ॉल्ट पर रीसेट करें", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0} पहले से सूची में है।", "toolbar.ext_also_in": "“{0}” में भी है", "toolbar.ext_in_profile": "{0} में", - "toolbar.ext_claimed_first": "{0}: “{1}” में भी है, जो सूची में पहले आती है, इसलिए ये फ़ाइलें अब भी “{1}” खोलेंगी।", + "toolbar.ext_claimed_first": "{0}: “{1}” में भी है, जो सूची में पहले आती है, इसलिए ये फ़ाइलें अब भी “{1}” खोलेंगी। इन्हें यहाँ खोलने के लिए इस प्रोफ़ाइल को “{1}” से ऊपर ले जाएँ।", "toolbar.ext_claimed_later": "{0}: “{1}” में भी है।\nयह प्रोफ़ाइल सूची में पहले आती है, इसलिए अब ये फ़ाइलें इसी को खोलेंगी।", "toolbar.ext_unknown": "{0}: Filee इस फ़ाइल प्रकार को नहीं जानता।\nआप इसे रख सकते हैं, पर ये फ़ाइलें कन्वर्ट नहीं हो सकतीं।", "toolbar.ext_unknown_tip": "अज्ञात फ़ाइल प्रकार", diff --git a/src/Filee.App/Assets/i18n/ja.json b/src/Filee.App/Assets/i18n/ja.json index b6960a369..e2759e2cc 100644 --- a/src/Filee.App/Assets/i18n/ja.json +++ b/src/Filee.App/Assets/i18n/ja.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. プロファイルを選択", "toolbar.step_arrange": "2. プリセットを配置", "toolbar.add_profile": "新しいプロファイル", + "toolbar.profile_up": "プロファイルを上へ移動", + "toolbar.profile_down": "プロファイルを下へ移動", + "toolbar.profile_order_hint": "同じ拡張子が複数のプロファイルにある場合は、一覧で上にあるものが使われます。Alt+↑ / Alt+↓ で選択中のプロファイルを移動できます。", "toolbar.profile_new": "新しいプロファイル", "toolbar.delete_profile": "プロファイルを削除", "toolbar.reset_profile": "既定に戻す", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0}はすでに一覧にあります。", "toolbar.ext_also_in": "「{0}」にも登録されています", "toolbar.ext_in_profile": "{0}内", - "toolbar.ext_claimed_first": "{0}:「{1}」にも登録されています。一覧ではそちらの方が先にあるため、この形式のファイルには引き続き「{1}」が使われます。", + "toolbar.ext_claimed_first": "{0}:「{1}」にも登録されています。一覧ではそちらの方が先にあるため、この形式のファイルには引き続き「{1}」が使われます。このプロファイルを「{1}」より上に移動すると、こちらが使われます。", "toolbar.ext_claimed_later": "{0}:「{1}」にも登録されています。\nこのプロファイルの方が一覧で先にあるため、この形式のファイルにはこちらが使われます。", "toolbar.ext_unknown": "{0}:Fileeはこのファイル形式を認識できません。\n登録はできますが、このファイルは変換できません。", "toolbar.ext_unknown_tip": "不明なファイル形式", diff --git a/src/Filee.App/Assets/i18n/ko.json b/src/Filee.App/Assets/i18n/ko.json index 09604ddae..8213328ad 100644 --- a/src/Filee.App/Assets/i18n/ko.json +++ b/src/Filee.App/Assets/i18n/ko.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. 프로필 선택", "toolbar.step_arrange": "2. 프리셋 배치", "toolbar.add_profile": "새 프로필", + "toolbar.profile_up": "프로필 위로", + "toolbar.profile_down": "프로필 아래로", + "toolbar.profile_order_hint": "두 프로필에 같은 확장자가 있으면 목록에서 위에 있는 프로필로 열려요. Alt+↑ / Alt+↓로 선택한 프로필을 옮길 수 있어요.", "toolbar.profile_new": "새 프로필", "toolbar.delete_profile": "프로필 삭제", "toolbar.reset_profile": "기본값으로 초기화", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0}은(는) 이미 목록에 있어요.", "toolbar.ext_also_in": "“{0}”에도 있음", "toolbar.ext_in_profile": "{0}에 있음", - "toolbar.ext_claimed_first": "{0}: “{1}”에도 있어요.\n목록에서 “{1}”이(가) 먼저라서 이 파일들은 계속 “{1}”로 열려요.", + "toolbar.ext_claimed_first": "{0}: “{1}”에도 있어요.\n목록에서 “{1}”이(가) 먼저라서 이 파일들은 계속 “{1}”로 열려요. 이 프로필을 “{1}”보다 위로 옮기면 여기서 열려요.", "toolbar.ext_claimed_later": "{0}: “{1}”에도 있어요.\n목록에서 이 프로필이 먼저라서 이제 이 파일들은 이 프로필로 열려요.", "toolbar.ext_unknown": "{0}: Filee가 모르는 파일 형식이에요.\n넣어 둘 수는 있지만 이 파일들은 변환할 수 없어요.", "toolbar.ext_unknown_tip": "알 수 없는 파일 형식", diff --git a/src/Filee.App/Assets/i18n/ne.json b/src/Filee.App/Assets/i18n/ne.json index dade701b1..47c19c8ba 100644 --- a/src/Filee.App/Assets/i18n/ne.json +++ b/src/Filee.App/Assets/i18n/ne.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "१. प्रोफाइल छनोट गर्नुहोस्", "toolbar.step_arrange": "२. प्रिसेटहरू व्यवस्थित गर्नुहोस्", "toolbar.add_profile": "नयाँ प्रोफाइल", + "toolbar.profile_up": "प्रोफाइल माथि सार्नुहोस्", + "toolbar.profile_down": "प्रोफाइल तल सार्नुहोस्", + "toolbar.profile_order_hint": "दुई प्रोफाइलमा एउटै एक्सटेन्सन भए सूचीमा माथि रहेको प्रोफाइल खुल्छ। Alt+↑ / Alt+↓ ले छानिएको प्रोफाइल सार्छ।", "toolbar.profile_new": "नयाँ प्रोफाइल", "toolbar.delete_profile": "प्रोफाइल हटाउनुहोस्", "toolbar.reset_profile": "पूर्वनिर्धारितमा रिसेट गर्नुहोस्", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0} पहिले नै सूचीमा छ।", "toolbar.ext_also_in": "“{0}” मा पनि छ", "toolbar.ext_in_profile": "{0} मा", - "toolbar.ext_claimed_first": "{0}: “{1}” मा पनि छ, जुन सूचीमा पहिले आउँछ, त्यसैले यी फाइलहरूले अझै “{1}” खोल्नेछन्।", + "toolbar.ext_claimed_first": "{0}: “{1}” मा पनि छ, जुन सूचीमा पहिले आउँछ, त्यसैले यी फाइलहरूले अझै “{1}” खोल्नेछन्। यी फाइलहरू यहीँ खोल्न यो प्रोफाइललाई “{1}” भन्दा माथि सार्नुहोस्।", "toolbar.ext_claimed_later": "{0}: “{1}” मा पनि छ।\nयो प्रोफाइल सूचीमा पहिले आउँछ, त्यसैले यी फाइलहरूले अब यसको सट्टा यो प्रोफाइल खोल्नेछन्।", "toolbar.ext_unknown": "{0}: Filee लाई यो फाइल प्रकार थाहा छैन।\nतपाईंले यसलाई राख्न सक्नुहुन्छ, तर यी फाइलहरू रूपान्तरण गर्न सकिँदैन।", "toolbar.ext_unknown_tip": "अज्ञात फाइल प्रकार", diff --git a/src/Filee.App/Assets/i18n/pl.json b/src/Filee.App/Assets/i18n/pl.json index 0c7af06e2..e4d72e60b 100644 --- a/src/Filee.App/Assets/i18n/pl.json +++ b/src/Filee.App/Assets/i18n/pl.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. Wybierz profil", "toolbar.step_arrange": "2. Ułóż ustawienia", "toolbar.add_profile": "Nowy profil", + "toolbar.profile_up": "Przesuń profil w górę", + "toolbar.profile_down": "Przesuń profil w dół", + "toolbar.profile_order_hint": "Gdy dwa profile mają to samo rozszerzenie, otwiera się ten wyżej na liście. Alt+↑ / Alt+↓ przesuwa zaznaczony profil.", "toolbar.profile_new": "Nowy profil", "toolbar.delete_profile": "Usuń profil", "toolbar.reset_profile": "Przywróć domyślny", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} jest już na liście.", "toolbar.ext_also_in": "Także w „{0}”", "toolbar.ext_in_profile": "w {0}", - "toolbar.ext_claimed_first": "{0}: także w „{1}”, który jest wcześniej na liście, więc te pliki nadal otwierają „{1}”.", + "toolbar.ext_claimed_first": "{0}: także w „{1}”, który jest wcześniej na liście, więc te pliki nadal otwierają „{1}”. Przesuń ten profil nad „{1}”, aby otwierały się tutaj.", "toolbar.ext_claimed_later": "{0}: także w „{1}”.\nTen profil jest wcześniej na liście, więc te pliki otwierają teraz ten profil.", "toolbar.ext_unknown": "{0}: Filee nie zna tego typu pliku.\nMożesz go zostawić, ale tych plików nie da się przekonwertować.", "toolbar.ext_unknown_tip": "Nieznany typ pliku", diff --git a/src/Filee.App/Assets/i18n/pt-BR.json b/src/Filee.App/Assets/i18n/pt-BR.json index 88d47fdae..4613c7159 100644 --- a/src/Filee.App/Assets/i18n/pt-BR.json +++ b/src/Filee.App/Assets/i18n/pt-BR.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. Escolha um perfil", "toolbar.step_arrange": "2. Organize as predefinições", "toolbar.add_profile": "Novo perfil", + "toolbar.profile_up": "Mover perfil para cima", + "toolbar.profile_down": "Mover perfil para baixo", + "toolbar.profile_order_hint": "Quando dois perfis têm a mesma extensão, abre o que está mais acima. Alt+↑ / Alt+↓ move o perfil selecionado.", "toolbar.profile_new": "Novo perfil", "toolbar.delete_profile": "Excluir perfil", "toolbar.reset_profile": "Restaurar padrão", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} já está na lista.", "toolbar.ext_also_in": "Também em “{0}”", "toolbar.ext_in_profile": "em {0}", - "toolbar.ext_claimed_first": "{0}: também em “{1}”, que vem primeiro na lista, então estes arquivos ainda abrem “{1}”.", + "toolbar.ext_claimed_first": "{0}: também em “{1}”, que vem primeiro na lista, então estes arquivos ainda abrem “{1}”. Mova este perfil para cima de “{1}” para abri-los aqui.", "toolbar.ext_claimed_later": "{0}: também em “{1}”.\nEste perfil vem primeiro na lista, então estes arquivos agora abrem este.", "toolbar.ext_unknown": "{0}: o Filee não conhece este tipo de arquivo.\nVocê pode manter, mas estes arquivos não podem ser convertidos.", "toolbar.ext_unknown_tip": "Tipo de arquivo desconhecido", diff --git a/src/Filee.App/Assets/i18n/pt-PT.json b/src/Filee.App/Assets/i18n/pt-PT.json index f89ce25c5..6b1e6e363 100644 --- a/src/Filee.App/Assets/i18n/pt-PT.json +++ b/src/Filee.App/Assets/i18n/pt-PT.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. Escolhe um perfil", "toolbar.step_arrange": "2. Organiza as predefinições", "toolbar.add_profile": "Novo perfil", + "toolbar.profile_up": "Mover perfil para cima", + "toolbar.profile_down": "Mover perfil para baixo", + "toolbar.profile_order_hint": "Quando dois perfis têm a mesma extensão, abre o que está mais acima. Alt+↑ / Alt+↓ move o perfil selecionado.", "toolbar.profile_new": "Novo perfil", "toolbar.delete_profile": "Eliminar perfil", "toolbar.reset_profile": "Repor valores de origem", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} já está na lista.", "toolbar.ext_also_in": "Também em «{0}»", "toolbar.ext_in_profile": "em {0}", - "toolbar.ext_claimed_first": "{0}: também em «{1}», que aparece primeiro na lista. Estes ficheiros continuam, por isso, a abrir «{1}».", + "toolbar.ext_claimed_first": "{0}: também em «{1}», que aparece primeiro na lista. Estes ficheiros continuam, por isso, a abrir «{1}». Move este perfil para cima de «{1}» para os abrir aqui.", "toolbar.ext_claimed_later": "{0}: também em «{1}».\nEste perfil aparece primeiro na lista, pelo que estes ficheiros passam a abri-lo.", "toolbar.ext_unknown": "{0}: o Filee não conhece este tipo de ficheiro.\nPodes mantê-lo, mas estes ficheiros não podem ser convertidos.", "toolbar.ext_unknown_tip": "Tipo de ficheiro desconhecido", diff --git a/src/Filee.App/Assets/i18n/ru.json b/src/Filee.App/Assets/i18n/ru.json index 47f36cb2d..83f6bd040 100644 --- a/src/Filee.App/Assets/i18n/ru.json +++ b/src/Filee.App/Assets/i18n/ru.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. Выберите профиль", "toolbar.step_arrange": "2. Расставьте пресеты", "toolbar.add_profile": "Новый профиль", + "toolbar.profile_up": "Переместить профиль выше", + "toolbar.profile_down": "Переместить профиль ниже", + "toolbar.profile_order_hint": "Если у двух профилей есть одно и то же расширение, открывается тот, что выше. Alt+↑ / Alt+↓ перемещает выбранный профиль.", "toolbar.profile_new": "Новый профиль", "toolbar.delete_profile": "Удалить профиль", "toolbar.reset_profile": "Сбросить", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} уже есть в списке.", "toolbar.ext_also_in": "Также в «{0}»", "toolbar.ext_in_profile": "в {0}", - "toolbar.ext_claimed_first": "{0}: также в «{1}», а он выше в списке, поэтому такие файлы по-прежнему открывают «{1}».", + "toolbar.ext_claimed_first": "{0}: также в «{1}», а он выше в списке, поэтому такие файлы по-прежнему открывают «{1}». Переместите этот профиль выше «{1}», чтобы они открывались здесь.", "toolbar.ext_claimed_later": "{0}: также в «{1}».\nЭтот профиль выше в списке, поэтому такие файлы теперь открывают его.", "toolbar.ext_unknown": "{0}: Filee не знает такой тип файлов.\nЕго можно оставить, но такие файлы не сконвертируются.", "toolbar.ext_unknown_tip": "Неизвестный тип файлов", diff --git a/src/Filee.App/Assets/i18n/th.json b/src/Filee.App/Assets/i18n/th.json index ff9466b61..e4088b3c1 100644 --- a/src/Filee.App/Assets/i18n/th.json +++ b/src/Filee.App/Assets/i18n/th.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. เลือกโปรไฟล์", "toolbar.step_arrange": "2. จัดเรียงพรีเซ็ต", "toolbar.add_profile": "โปรไฟล์ใหม่", + "toolbar.profile_up": "เลื่อนโปรไฟล์ขึ้น", + "toolbar.profile_down": "เลื่อนโปรไฟล์ลง", + "toolbar.profile_order_hint": "ถ้าสองโปรไฟล์มีนามสกุลไฟล์เดียวกัน จะเปิดด้วยโปรไฟล์ที่อยู่สูงกว่า กด Alt+↑ / Alt+↓ เพื่อเลื่อนโปรไฟล์ที่เลือก", "toolbar.profile_new": "โปรไฟล์ใหม่", "toolbar.delete_profile": "ลบโปรไฟล์", "toolbar.reset_profile": "รีเซ็ตเป็นค่าเริ่มต้น", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0} มีอยู่ในรายการแล้ว", "toolbar.ext_also_in": "อยู่ใน “{0}” ด้วย", "toolbar.ext_in_profile": "ใน {0}", - "toolbar.ext_claimed_first": "{0}: อยู่ใน “{1}” ด้วย ซึ่งอยู่ก่อนหน้าในรายการ ดังนั้นไฟล์เหล่านี้จะยังคงเปิดด้วย “{1}”", + "toolbar.ext_claimed_first": "{0}: อยู่ใน “{1}” ด้วย ซึ่งอยู่ก่อนหน้าในรายการ ดังนั้นไฟล์เหล่านี้จะยังคงเปิดด้วย “{1}” เลื่อนโปรไฟล์นี้ขึ้นไปไว้เหนือ “{1}” เพื่อให้เปิดด้วยโปรไฟล์นี้", "toolbar.ext_claimed_later": "{0}: อยู่ใน “{1}” ด้วย\nโปรไฟล์นี้อยู่ก่อนหน้าในรายการ ดังนั้นไฟล์เหล่านี้จะเปิดด้วยโปรไฟล์นี้แทน", "toolbar.ext_unknown": "{0}: Filee ไม่รู้จักประเภทไฟล์นี้\nคุณสามารถเก็บไว้ได้ แต่ไฟล์เหล่านี้จะไม่สามารถแปลงได้", "toolbar.ext_unknown_tip": "ไม่รู้จักประเภทไฟล์นี้", diff --git a/src/Filee.App/Assets/i18n/tr.json b/src/Filee.App/Assets/i18n/tr.json index ad1043c97..8a9671386 100644 --- a/src/Filee.App/Assets/i18n/tr.json +++ b/src/Filee.App/Assets/i18n/tr.json @@ -536,6 +536,9 @@ "toolbar.step_profile": "1. Profil seçin", "toolbar.step_arrange": "2. Ön ayarları düzenleyin", "toolbar.add_profile": "Yeni profil", + "toolbar.profile_up": "Profili yukarı taşı", + "toolbar.profile_down": "Profili aşağı taşı", + "toolbar.profile_order_hint": "İki profil aynı uzantıya sahipse listede üstte olan açılır. Alt+↑ / Alt+↓ seçili profili taşır.", "toolbar.profile_new": "Yeni profil", "toolbar.delete_profile": "Profili sil", "toolbar.reset_profile": "Varsayılana sıfırla", @@ -581,7 +584,7 @@ "toolbar.ext_duplicate": "{0} zaten listede.", "toolbar.ext_also_in": "“{0}” profilinde de var", "toolbar.ext_in_profile": "{0} içinde", - "toolbar.ext_claimed_first": "{0}: listede önce gelen “{1}” profilinde de var; bu dosyalar hâlâ “{1}” profilini açar.", + "toolbar.ext_claimed_first": "{0}: listede önce gelen “{1}” profilinde de var; bu dosyalar hâlâ “{1}” profilini açar. Burada açılmaları için bu profili “{1}” profilinin üstüne taşıyın.", "toolbar.ext_claimed_later": "{0}: “{1}” profilinde de var.\nBu profil listede önce geldiği için dosyalar artık bunu açar.", "toolbar.ext_unknown": "{0}: Filee bu dosya türünü tanımıyor.\nTutabilirsiniz ancak bu dosyalar dönüştürülemez.", "toolbar.ext_unknown_tip": "Bilinmeyen dosya türü", diff --git a/src/Filee.App/Assets/i18n/zh-CN.json b/src/Filee.App/Assets/i18n/zh-CN.json index e0b384c6f..78ef80a8c 100644 --- a/src/Filee.App/Assets/i18n/zh-CN.json +++ b/src/Filee.App/Assets/i18n/zh-CN.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. 选择配置", "toolbar.step_arrange": "2. 排列预设", "toolbar.add_profile": "新建配置", + "toolbar.profile_up": "上移配置", + "toolbar.profile_down": "下移配置", + "toolbar.profile_order_hint": "两个配置包含相同的扩展名时,打开列表中靠上的那个。按 Alt+↑ / Alt+↓ 可移动所选配置。", "toolbar.profile_new": "新配置", "toolbar.delete_profile": "删除配置", "toolbar.reset_profile": "恢复默认", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} 已在列表中。", "toolbar.ext_also_in": "也在“{0}”中", "toolbar.ext_in_profile": "在“{0}”中", - "toolbar.ext_claimed_first": "{0}:也在“{1}”中。\n“{1}”在列表中靠前,所以这些文件仍会打开“{1}”。", + "toolbar.ext_claimed_first": "{0}:也在“{1}”中。\n“{1}”在列表中靠前,所以这些文件仍会打开“{1}”。把此配置移到“{1}”上方,这些文件就会用此配置打开。", "toolbar.ext_claimed_later": "{0}:也在“{1}”中。\n此配置在列表中靠前,所以这些文件现在会改用此配置。", "toolbar.ext_unknown": "{0}:Filee 不认识这种文件类型。\n可以保留,但这些文件无法转换。", "toolbar.ext_unknown_tip": "未知文件类型", diff --git a/src/Filee.App/Assets/i18n/zh-TW.json b/src/Filee.App/Assets/i18n/zh-TW.json index ae6a38060..322a6791d 100644 --- a/src/Filee.App/Assets/i18n/zh-TW.json +++ b/src/Filee.App/Assets/i18n/zh-TW.json @@ -550,6 +550,9 @@ "toolbar.step_profile": "1. 選擇設定檔", "toolbar.step_arrange": "2. 排列預設", "toolbar.add_profile": "新增設定檔", + "toolbar.profile_up": "上移設定檔", + "toolbar.profile_down": "下移設定檔", + "toolbar.profile_order_hint": "兩個設定檔包含相同的副檔名時,會開啟清單中較上方的那個。按 Alt+↑ / Alt+↓ 可移動所選設定檔。", "toolbar.profile_new": "新設定檔", "toolbar.delete_profile": "刪除設定檔", "toolbar.reset_profile": "還原為初始設定", @@ -595,7 +598,7 @@ "toolbar.ext_duplicate": "{0} 已在清單中。", "toolbar.ext_also_in": "也在「{0}」中", "toolbar.ext_in_profile": "在「{0}」中", - "toolbar.ext_claimed_first": "{0}:也在「{1}」中。\n「{1}」在清單中排在前面,所以這些檔案仍會開啟「{1}」。", + "toolbar.ext_claimed_first": "{0}:也在「{1}」中。\n「{1}」在清單中排在前面,所以這些檔案仍會開啟「{1}」。把此設定檔移到「{1}」上方,這些檔案就會改用此設定檔開啟。", "toolbar.ext_claimed_later": "{0}:也在「{1}」中。\n此設定檔在清單中排在前面,所以這些檔案現在會改用此設定檔。", "toolbar.ext_unknown": "{0}:Filee 不認識這種檔案類型。\n可以保留,但這些檔案無法轉換。", "toolbar.ext_unknown_tip": "未知檔案類型", diff --git a/src/Filee.App/ViewModels/Pages/ToolbarPageViewModel.cs b/src/Filee.App/ViewModels/Pages/ToolbarPageViewModel.cs index bdc6354f6..f01f584cf 100644 --- a/src/Filee.App/ViewModels/Pages/ToolbarPageViewModel.cs +++ b/src/Filee.App/ViewModels/Pages/ToolbarPageViewModel.cs @@ -3,7 +3,8 @@ // The drag gestures themselves live in the view (ToolbarPage.axaml.cs); this class only mutates the model. // A profile is either normal (extension chips, ExtensionTagsViewModel) or for mixed selections (check list, // MixedExtensionsViewModel). Normal profiles are kept before the mixed ones, so a new mixed profile never takes over -// the catch-all role of the built-in "Mixed files" donut (see ProfileSelector). +// the catch-all role of the built-in "Mixed files" donut (see ProfileSelector). Move up / Move down (Alt+↑ / Alt+↓) +// reorder a profile among its own kind, which decides the profile that opens for a shared extension (#522). using System.Collections.ObjectModel; using System.Diagnostics; @@ -235,7 +236,11 @@ internal static PaletteTab TabOf(Preset preset) [ObservableProperty] private PaletteTabItem? _selectedTab; [ObservableProperty] private bool _showTabRow; - partial void OnProfileSearchChanged(string value) => VisibleProfiles.Query = value; + partial void OnProfileSearchChanged(string value) + { + VisibleProfiles.Query = value; + NotifyMoveChanged(); + } partial void OnPaletteSearchChanged(string value) { _pendingTabRestore = null; @@ -309,6 +314,7 @@ partial void OnSelectedProfileChanged(ProfileItemViewModel? value) // The list box briefly drops its selection while the selected profile is moved (see Reposition). if (_repositioning) return; + NotifyMoveChanged(); _loading = true; ProfileName = value is null ? "" : _loc.DisplayName(value.Profile); _loading = false; @@ -369,6 +375,54 @@ private void Reposition(ProfileItemViewModel item) { _repositioning = false; } + NotifyMoveChanged(); + } + + /// The profile the selected one would pass going , among those the search shows. + private ToolbarProfile? MoveNeighbor(int direction) => + Profile is { } profile + ? ProfileOrder.Neighbor(_store.Profiles, profile, direction, p => VisibleProfiles.Any(v => v.Profile == p)) + : null; + + private bool CanMoveProfileUp() => MoveNeighbor(-1) is not null; + private bool CanMoveProfileDown() => MoveNeighbor(1) is not null; + + /// + /// Moves the selected profile above the profile of its kind shown above it: the higher of two profiles with the + /// same extension opens for it (#522). With a search, it passes the one the list shows, not a hidden one. + /// + [RelayCommand(CanExecute = nameof(CanMoveProfileUp))] + private void MoveProfileUp() => MoveProfile(-1); + + /// Moves the selected profile below the profile of its kind shown below it. + [RelayCommand(CanExecute = nameof(CanMoveProfileDown))] + private void MoveProfileDown() => MoveProfile(1); + + private void MoveProfile(int direction) + { + if (SelectedProfile is not { } item + || ProfileOrder.Move(_store.Profiles, item.Profile, direction, p => VisibleProfiles.Any(v => v.Profile == p)) is not { } move) + return; + _repositioning = true; + try + { + Profiles.Move(move.From, move.To); + SelectedProfile = item; + } + finally + { + _repositioning = false; + } + SaveOwnLibrary(); + // The remarks under the extensions say which profile comes first; that just changed. + RebuildProfileEditor(); + NotifyMoveChanged(); + } + + private void NotifyMoveChanged() + { + MoveProfileUpCommand.NotifyCanExecuteChanged(); + MoveProfileDownCommand.NotifyCanExecuteChanged(); } /// Shows the chips or the check list for the selected profile. @@ -523,6 +577,7 @@ private void AddProfile() var item = new ProfileItemViewModel(profile, _loc); Profiles.Insert(index, item); SelectedProfile = item; + NotifyMoveChanged(); } [RelayCommand] @@ -539,6 +594,7 @@ private async Task DeleteProfile() SaveOwnLibrary(); Profiles.Remove(SelectedProfile!); SelectedProfile = Profiles.FirstOrDefault(); + NotifyMoveChanged(); } [RelayCommand] @@ -580,6 +636,7 @@ internal void Reset(ProfileItemViewModel item) foreach (var other in Profiles) other.Refresh(_loc); RebuildProfileEditor(); + NotifyMoveChanged(); ForgetJudgements(item.Profile.Id); Rebuild(); } diff --git a/src/Filee.App/Views/Pages/ToolbarPage.axaml b/src/Filee.App/Views/Pages/ToolbarPage.axaml index 611899134..c57d78ade 100644 --- a/src/Filee.App/Views/Pages/ToolbarPage.axaml +++ b/src/Filee.App/Views/Pages/ToolbarPage.axaml @@ -45,6 +45,14 @@ + + + +