diff --git a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs
index f98815c1a9f..bb1279b2c61 100644
--- a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs
@@ -1,4 +1,6 @@
-namespace Flow.Launcher.Core.ExternalPlugins
+using System;
+
+namespace Flow.Launcher.Core.ExternalPlugins
{
public record UserPlugin
{
@@ -12,5 +14,8 @@ public record UserPlugin
public string UrlDownload { get; set; }
public string UrlSourceCode { get; set; }
public string IcoPath { get; set; }
+ public DateTime LatestReleaseDate { get; set; }
+ public DateTime DateAdded { get; set; }
+
}
}
diff --git a/Flow.Launcher/Converters/BoolToVisibilityConverter.cs b/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
new file mode 100644
index 00000000000..ad474d693b1
--- /dev/null
+++ b/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+namespace Flow.Launcher.Converters
+{
+ public class BoolToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter != null)
+ {
+ if (value is true)
+ {
+ return Visibility.Collapsed;
+ }
+
+ else
+ {
+ return Visibility.Visible;
+ }
+ }
+ else {
+ if (value is true)
+ {
+ return Visibility.Visible;
+ }
+
+ else {
+ return Visibility.Collapsed;
+ }
+ }
+ }
+
+ public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ }
+}
diff --git a/Flow.Launcher/Converters/TextConverter.cs b/Flow.Launcher/Converters/TextConverter.cs
new file mode 100644
index 00000000000..90d445776df
--- /dev/null
+++ b/Flow.Launcher/Converters/TextConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using Flow.Launcher.Core.Resource;
+using Flow.Launcher.ViewModel;
+
+namespace Flow.Launcher.Converters
+{
+ public class TextConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var ID = value.ToString();
+ switch(ID)
+ {
+ case PluginStoreItemViewModel.NewRelease:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_NewRelease");
+ case PluginStoreItemViewModel.RecentlyUpdated:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_RecentlyUpdated");
+ case PluginStoreItemViewModel.None:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_None");
+ case PluginStoreItemViewModel.Installed:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_Installed");
+ default:
+ return ID;
+ }
+
+ }
+
+ public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ }
+}
diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml
index 7ec94fed109..25bd195dd04 100644
--- a/Flow.Launcher/Languages/da.xaml
+++ b/Flow.Launcher/Languages/da.xaml
@@ -77,13 +77,13 @@
Søgetid:
| Version
Website
- Uninstall
+ Uninstall
Plugin Store
Refresh
- Install
+ Install
Tema
diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml
index a1b0b3b9b37..ebd549adf9a 100644
--- a/Flow.Launcher/Languages/de.xaml
+++ b/Flow.Launcher/Languages/de.xaml
@@ -77,13 +77,13 @@
Abfragezeit:
Version
Webseite
- Deinstallieren
+ Deinstallieren
Erweiterungen laden
Aktualisieren
- Installieren
+ Installieren
Design
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 2019c1b6629..578e5cd6aa0 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -83,13 +83,24 @@
Query time:
| Version
Website
- Uninstall
Plugin Store
+ New Release
+ Recently Updated
+ Plugins
+ Installed
Refresh
- Install
+ Install
+ Uninstall
+ Update
+ Plug-in already installed
+ New Version
+ This plug-in has been updated within the last 7 days
+ New Update is Available
+
+
Theme
diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml
index 84a492d1553..a410f4b326b 100644
--- a/Flow.Launcher/Languages/es-419.xaml
+++ b/Flow.Launcher/Languages/es-419.xaml
@@ -77,13 +77,13 @@
Tiempo de consulta:
| Versión
Sitio web
- Uninstall
+ Uninstall
Tienda de Plugins
Recargar
- Instalar
+ Instalar
Tema
diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml
index 141d868a2d9..edc5e4f0701 100644
--- a/Flow.Launcher/Languages/fr.xaml
+++ b/Flow.Launcher/Languages/fr.xaml
@@ -77,13 +77,13 @@
Utilisation :
| Version
Website
- Désinstaller
+ Désinstaller
Plugin Store
Refresh
- Install
+ Install
Thèmes
diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml
index 4304aead83e..30a4018759f 100644
--- a/Flow.Launcher/Languages/it.xaml
+++ b/Flow.Launcher/Languages/it.xaml
@@ -77,13 +77,13 @@
Tempo ricerca:
| Versione
Sito Web
- Disinstalla
+ Disinstalla
Negozio dei Plugin
Aggiorna
- Installa
+ Installa
Tema
diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml
index 8c13863710c..a2dcfb6a098 100644
--- a/Flow.Launcher/Languages/ja.xaml
+++ b/Flow.Launcher/Languages/ja.xaml
@@ -77,13 +77,13 @@
クエリ時間:
| バージョン
ウェブサイト
- アンインストール
+ アンインストール
プラグインストア
Refresh
- Install
+ Install
テーマ
diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml
index 809c5ccf817..acb68cb4f42 100644
--- a/Flow.Launcher/Languages/ko.xaml
+++ b/Flow.Launcher/Languages/ko.xaml
@@ -77,13 +77,13 @@
쿼리 시간:
| 버전
웹사이트
- 제거
+ 제거
플러그인 스토어
새로고침
- 설치
+ 설치
테마
diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml
index e90a32347a5..0848e9d6478 100644
--- a/Flow.Launcher/Languages/nb.xaml
+++ b/Flow.Launcher/Languages/nb.xaml
@@ -77,13 +77,13 @@
Query time:
| Version
Website
- Uninstall
+ Uninstall
Plugin Store
Refresh
- Install
+ Install
Theme
diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml
index 77a8e9e2902..e398afa5134 100644
--- a/Flow.Launcher/Languages/nl.xaml
+++ b/Flow.Launcher/Languages/nl.xaml
@@ -77,13 +77,13 @@
Query tijd:
| Versie
Website
- Uninstall
+ Uninstall
Plugin Winkel
Vernieuwen
- Installeren
+ Installeren
Thema
diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml
index bd7acd4e88b..fc5badd6972 100644
--- a/Flow.Launcher/Languages/pl.xaml
+++ b/Flow.Launcher/Languages/pl.xaml
@@ -77,13 +77,13 @@
Czas zapytania:
| Version
Website
- Odinstalowywanie
+ Odinstalowywanie
Plugin Store
Refresh
- Install
+ Install
Skórka
diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml
index 28ed3091674..f6fc062c638 100644
--- a/Flow.Launcher/Languages/pt-br.xaml
+++ b/Flow.Launcher/Languages/pt-br.xaml
@@ -77,13 +77,13 @@
Tempo de consulta:
| Version
Website
- Desinstalar
+ Desinstalar
Plugin Store
Refresh
- Install
+ Install
Tema
diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml
index e7179e6e873..b19fc992413 100644
--- a/Flow.Launcher/Languages/pt-pt.xaml
+++ b/Flow.Launcher/Languages/pt-pt.xaml
@@ -77,13 +77,13 @@
Tempo de consulta:
| Versão
Site
- Desinstalar
+ Desinstalar
Loja de plugins
Recarregar
- Instalar
+ Instalar
Tema
diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml
index 2c8ca9fa3d7..87b3dd4ef35 100644
--- a/Flow.Launcher/Languages/ru.xaml
+++ b/Flow.Launcher/Languages/ru.xaml
@@ -77,13 +77,13 @@
Запрос:
| Version
Website
- Удалить
+ Удалить
Plugin Store
Refresh
- Install
+ Install
Тема
diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml
index c4d5de6bf29..ee703bcf8c8 100644
--- a/Flow.Launcher/Languages/sk.xaml
+++ b/Flow.Launcher/Languages/sk.xaml
@@ -77,13 +77,13 @@
Trvanie dopytu:
| Verzia
Webstránka
- Odinštalovať
+ Odinštalovať
Repozitár pluginov
Obnoviť
- Inštalovať
+ Inštalovať
Motív
diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml
index 61f619fd038..e805860dcc1 100644
--- a/Flow.Launcher/Languages/sr.xaml
+++ b/Flow.Launcher/Languages/sr.xaml
@@ -77,13 +77,13 @@
Vreme upita:
| Version
Website
- Uninstall
+ Uninstall
Plugin Store
Refresh
- Install
+ Install
Tema
diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml
index fb8e1d6f621..4a016ced8bd 100644
--- a/Flow.Launcher/Languages/tr.xaml
+++ b/Flow.Launcher/Languages/tr.xaml
@@ -77,13 +77,13 @@
Sorgu Süresi:
Sürüm
İnternet Sitesi
- Kaldır
+ Kaldır
Eklenti Mağazası
Yenile
- İndir
+ İndir
Temalar
diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml
index 8115a5dd1a8..a34ed4e8bce 100644
--- a/Flow.Launcher/Languages/uk-UA.xaml
+++ b/Flow.Launcher/Languages/uk-UA.xaml
@@ -77,13 +77,13 @@
Запит:
| Версія
Сайт
- Uninstall
+ Uninstall
Магазин плагінів
Оновити
- Встановити
+ Встановити
Тема
diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml
index d80bfdaf66a..b62736d16af 100644
--- a/Flow.Launcher/Languages/zh-cn.xaml
+++ b/Flow.Launcher/Languages/zh-cn.xaml
@@ -77,13 +77,13 @@
查询耗时:
| 版本
官方网站
- 卸载
+ 卸载
插件商店
刷新
- 安装
+ 安装
主题
diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml
index 71cc887cf8f..69abbe40160 100644
--- a/Flow.Launcher/Languages/zh-tw.xaml
+++ b/Flow.Launcher/Languages/zh-tw.xaml
@@ -77,13 +77,13 @@
查詢耗時:
| 版本
官方網站
- 解除安裝
+ 解除安裝
外掛商店
重新整理
- 安裝
+ 安裝
主題
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index dc3b3f1454b..627b8025216 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -177,9 +177,9 @@
AllowDrop="True"
Background="Transparent"
PreviewDragOver="OnPreviewDragOver"
+ PreviewKeyUp="QueryTextBox_KeyUp"
Style="{DynamicResource QueryBoxStyle}"
Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
- PreviewKeyUp="QueryTextBox_KeyUp"
Visibility="Visible">
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index 0a63b3a6cfb..4346fd59a1b 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -40,6 +40,8 @@
+
+
@@ -1315,7 +1317,7 @@
FontSize="11"
Foreground="{DynamicResource PluginInfoColor}"
MouseUp="OnExternalPluginUninstallClick"
- Text="{DynamicResource plugin_uninstall}"
+ Text="{DynamicResource uninstallbtn}"
TextDecorations="Underline" />
+
+
+
+
+
+
+
-
-
-
-
-
+ Background="#45BD59"
+ CornerRadius="36"
+ ToolTip="{DynamicResource LabelUpdateToolTip}"
+ Visibility="{Binding LabelUpdate, Converter={StaticResource BoolToVisibilityConverter}}" />
+ Text="{Binding Description, Mode=OneWay}" />
@@ -1665,25 +1676,45 @@
Foreground="{DynamicResource Color04B}"
NavigateUri="{Binding Website}"
RequestNavigate="OnRequestNavigate">
-
+
-
-
+ Orientation="Horizontal">
+
+
+
+
+
+
diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs
index 51017b96bd7..fc6be5d04f9 100644
--- a/Flow.Launcher/SettingWindow.xaml.cs
+++ b/Flow.Launcher/SettingWindow.xaml.cs
@@ -47,6 +47,10 @@ public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel)
API = api;
InitializePosition();
InitializeComponent();
+
+ CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource);
+ PropertyGroupDescription groupDescription = new PropertyGroupDescription("Category");
+ view.GroupDescriptions.Add(groupDescription);
}
#region General
@@ -306,15 +310,34 @@ private void OnPluginStoreRefreshClick(object sender, RoutedEventArgs e)
private void OnExternalPluginInstallClick(object sender, RoutedEventArgs e)
{
- if (sender is Button { DataContext: UserPlugin plugin })
+ if (sender is Button { DataContext: PluginStoreItemViewModel plugin })
{
- var pluginsManagerPlugin = PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7");
- var actionKeyword = pluginsManagerPlugin.Metadata.ActionKeywords.Count == 0 ? "" : pluginsManagerPlugin.Metadata.ActionKeywords[0];
- API.ChangeQuery($"{actionKeyword} install {plugin.Name}");
- API.ShowMainWindow();
+ viewModel.DisplayPluginQuery($"install {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
}
}
+ private void OnExternalPluginUninstallClick(object sender, MouseButtonEventArgs e)
+ {
+ if (e.ChangedButton == MouseButton.Left)
+ {
+ var name = viewModel.SelectedPlugin.PluginPair.Metadata.Name;
+ viewModel.DisplayPluginQuery($"uninstall {name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
+ }
+
+ }
+
+ private void OnExternalPluginUninstallClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is Button { DataContext: PluginStoreItemViewModel plugin })
+ viewModel.DisplayPluginQuery($"uninstall {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
+ }
+
+ private void OnExternalPluginUpdateClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is Button { DataContext: PluginStoreItemViewModel plugin })
+ viewModel.DisplayPluginQuery($"update {plugin.Name}", PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"));
+ }
+
private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */
{
if (Keyboard.FocusedElement is not TextBox textBox)
@@ -388,7 +411,7 @@ private bool PluginStoreFilter(object item)
{
if (string.IsNullOrEmpty(pluginStoreFilterTxb.Text))
return true;
- if (item is UserPlugin model)
+ if (item is PluginStoreItemViewModel model)
{
return StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Name).IsSearchPrecisionScoreMet()
|| StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Description).IsSearchPrecisionScoreMet();
@@ -473,17 +496,6 @@ public double WindowTop()
var top = (dip2.Y - this.ActualHeight) / 2 + dip1.Y - 20;
return top;
}
- private void OnExternalPluginUninstallClick(object sender, MouseButtonEventArgs e)
- {
- if (e.ChangedButton == MouseButton.Left)
- {
- var id = viewModel.SelectedPlugin.PluginPair.Metadata.Name;
- var pluginsManagerPlugin = PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7");
- var actionKeyword = pluginsManagerPlugin.Metadata.ActionKeywords.Count == 0 ? "" : pluginsManagerPlugin.Metadata.ActionKeywords[0];
- API.ChangeQuery($"{actionKeyword} uninstall {id}");
- API.ShowMainWindow();
- }
- }
}
}
diff --git a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs
new file mode 100644
index 00000000000..622e41b1bcf
--- /dev/null
+++ b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs
@@ -0,0 +1,58 @@
+using System;
+using Flow.Launcher.Core.ExternalPlugins;
+using Flow.Launcher.Core.Plugin;
+using Flow.Launcher.Plugin;
+
+namespace Flow.Launcher.ViewModel
+{
+ public class PluginStoreItemViewModel : BaseModel
+ {
+ public PluginStoreItemViewModel(UserPlugin plugin)
+ {
+ _plugin = plugin;
+ }
+
+ private UserPlugin _plugin;
+
+ public string ID => _plugin.ID;
+ public string Name => _plugin.Name;
+ public string Description => _plugin.Description;
+ public string Author => _plugin.Author;
+ public string Version => _plugin.Version;
+ public string Language => _plugin.Language;
+ public string Website => _plugin.Website;
+ public string UrlDownload => _plugin.UrlDownload;
+ public string UrlSourceCode => _plugin.UrlSourceCode;
+ public string IcoPath => _plugin.IcoPath;
+
+ public bool LabelInstalled => PluginManager.GetPluginForId(_plugin.ID) != null;
+ public bool LabelUpdate => LabelInstalled && _plugin.Version != PluginManager.GetPluginForId(_plugin.ID).Metadata.Version;
+
+ internal const string None = "None";
+ internal const string RecentlyUpdated = "RecentlyUpdated";
+ internal const string NewRelease = "NewRelease";
+ internal const string Installed = "Installed";
+
+ public string Category
+ {
+ get
+ {
+ string category = None;
+ if (DateTime.Now - _plugin.LatestReleaseDate < TimeSpan.FromDays(7))
+ {
+ category = RecentlyUpdated;
+ }
+ if (DateTime.Now - _plugin.DateAdded < TimeSpan.FromDays(7))
+ {
+ category = NewRelease;
+ }
+ if (PluginManager.GetPluginForId(_plugin.ID) != null)
+ {
+ category = Installed;
+ }
+
+ return category;
+ }
+ }
+ }
+}
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index 9e7ead7d07c..432699c4b33 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -278,14 +278,24 @@ public IList PluginViewModels
}
}
- public IList ExternalPlugins
+ public IList ExternalPlugins
{
get
{
- return PluginsManifest.UserPlugins;
+ return LabelMaker(PluginsManifest.UserPlugins);
}
}
+ private IList LabelMaker(IList list)
+ {
+ return list.Select(p=>new PluginStoreItemViewModel(p))
+ .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease)
+ .ThenByDescending(p=>p.Category == PluginStoreItemViewModel.RecentlyUpdated)
+ .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None)
+ .ThenByDescending(p => p.Category == PluginStoreItemViewModel.Installed)
+ .ToList();
+ }
+
public Control SettingProvider
{
get
@@ -311,6 +321,15 @@ public async Task RefreshExternalPluginsAsync()
OnPropertyChanged(nameof(ExternalPlugins));
}
+ internal void DisplayPluginQuery(string queryToDisplay, PluginPair plugin, int actionKeywordPosition = 0)
+ {
+ var actionKeyword = plugin.Metadata.ActionKeywords.Count == 0
+ ? string.Empty
+ : plugin.Metadata.ActionKeywords[actionKeywordPosition];
+
+ App.API.ChangeQuery($"{actionKeyword} {queryToDisplay}");
+ App.API.ShowMainWindow();
+ }
#endregion