mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
merge
This commit is contained in:
parent
6aa35d592e
commit
156cb3055c
2 changed files with 78 additions and 78 deletions
|
|
@ -392,55 +392,37 @@
|
||||||
OnContent="{DynamicResource enable}" />
|
OnContent="{DynamicResource enable}" />
|
||||||
</ui:SettingsCard>
|
</ui:SettingsCard>
|
||||||
|
|
||||||
<ui:SettingsExpander Margin="0 4 0 0" Header="{DynamicResource historyResultsForHomePage}">
|
<ui:SettingsExpander Margin="0 4 0 0" Header="{DynamicResource homePageHistory}" Description="{DynamicResource homePageHistoryTooltip}" IsEnabled="{Binding Settings.ShowHomePage}">
|
||||||
<ui:SettingsExpander.HeaderIcon>
|
<ui:SettingsExpander.HeaderIcon>
|
||||||
<ui:FontIcon Glyph="" />
|
<ui:FontIcon Glyph="" />
|
||||||
</ui:SettingsExpander.HeaderIcon>
|
</ui:SettingsExpander.HeaderIcon>
|
||||||
|
|
||||||
<cc:ExCard Title="{DynamicResource homePageHistory}" Margin="0 14 0 0" Icon="" Sub="{DynamicResource homePageHistoryTooltip}">
|
<ui:ToggleSwitch
|
||||||
<cc:ExCard.SideContent>
|
IsOn="{Binding Settings.ShowHistoryOnHomePage}"
|
||||||
<ui:ToggleSwitch
|
OffContent="{DynamicResource disable}"
|
||||||
IsOn="{Binding Settings.ShowHistoryOnHomePage}"
|
OnContent="{DynamicResource enable}" />
|
||||||
OffContent="{DynamicResource disable}"
|
|
||||||
OnContent="{DynamicResource enable}" />
|
|
||||||
</cc:ExCard.SideContent>
|
|
||||||
<ContentControl>
|
|
||||||
<ContentControl.Style>
|
|
||||||
<Style TargetType="ContentControl">
|
|
||||||
<Setter Property="Content">
|
|
||||||
<Setter.Value>
|
|
||||||
<StackPanel Margin="15,10,0,0">
|
|
||||||
<RadioButton GroupName="HistoryType" Content="{DynamicResource historyQueryResultsForHomePage}"
|
|
||||||
IsChecked="{Binding Settings.ShowHistoryQueryResultsForHomePage}" />
|
|
||||||
<RadioButton GroupName="HistoryType" Content="{DynamicResource historyLastOpenedResultsForHomePage}"
|
|
||||||
IsChecked="{Binding Settings.ShowHistoryLastOpenedResultsForHomePage}"
|
|
||||||
Margin="0 0 0 0" />
|
|
||||||
|
|
||||||
<cc:Card Title="{DynamicResource historyResultsCountForHomePage}" Type="InsideFit" Margin="0 10 0 0">
|
<ui:SettingsExpander.Items>
|
||||||
<StackPanel Orientation="Vertical">
|
<ui:SettingsCard Header="{DynamicResource historyQueryResultsForHomePage}" IsEnabled="{Binding Settings.ShowHistoryOnHomePage}">
|
||||||
<ui:NumberBox
|
<RadioButton GroupName="HistoryType" IsChecked="{Binding Settings.ShowHistoryQueryResultsForHomePage}" />
|
||||||
Width="120"
|
</ui:SettingsCard>
|
||||||
Margin="0 0 0 0"
|
<ui:SettingsCard Header="{DynamicResource historyLastOpenedResultsForHomePage}" IsEnabled="{Binding Settings.ShowHistoryOnHomePage}">
|
||||||
Maximum="100"
|
<RadioButton GroupName="HistoryType" IsChecked="{Binding Settings.ShowHistoryLastOpenedResultsForHomePage}" />
|
||||||
Minimum="0"
|
</ui:SettingsCard>
|
||||||
SmallChange="5"
|
<ui:SettingsCard Header="{DynamicResource historyResultsCountForHomePage}" IsEnabled="{Binding Settings.ShowHistoryOnHomePage}">
|
||||||
SpinButtonPlacementMode="Compact"
|
<ui:NumberBox
|
||||||
ValidationMode="InvalidInputOverwritten"
|
Width="120"
|
||||||
Value="{Binding MaxHistoryResultsToShowValue}" />
|
MinWidth="120"
|
||||||
</StackPanel>
|
Margin="0 0 0 0"
|
||||||
</cc:Card>
|
Maximum="100"
|
||||||
</StackPanel>
|
Minimum="0"
|
||||||
</Setter.Value>
|
SmallChange="5"
|
||||||
</Setter>
|
SpinButtonPlacementMode="Compact"
|
||||||
<Style.Triggers>
|
ValidationMode="InvalidInputOverwritten"
|
||||||
<DataTrigger Binding="{Binding Settings.ShowHistoryOnHomePage}" Value="False">
|
Value="{Binding MaxHistoryResultsToShowValue}" />
|
||||||
<Setter Property="Content" Value="{x:Null}" />
|
</ui:SettingsCard>
|
||||||
</DataTrigger>
|
</ui:SettingsExpander.Items>
|
||||||
</Style.Triggers>
|
</ui:SettingsExpander>
|
||||||
</Style>
|
|
||||||
</ContentControl.Style>
|
|
||||||
</ContentControl>
|
|
||||||
</cc:ExCard>
|
|
||||||
|
|
||||||
<ui:SettingsCard
|
<ui:SettingsCard
|
||||||
Margin="0 14 0 0"
|
Margin="0 14 0 0"
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,10 @@ namespace Flow.Launcher.ViewModel
|
||||||
private Query _lastQuery;
|
private Query _lastQuery;
|
||||||
private bool _previousIsHomeQuery;
|
private bool _previousIsHomeQuery;
|
||||||
private string _queryTextBeforeLeaveResults;
|
private string _queryTextBeforeLeaveResults;
|
||||||
private string _ignoredQueryText; // Used to ignore query text change when switching between context menu and query results
|
|
||||||
|
private string
|
||||||
|
_ignoredQueryText; // Used to ignore query text change when switching between context menu and query results
|
||||||
|
|
||||||
private readonly FlowLauncherJsonStorage<History> _historyStorage;
|
private readonly FlowLauncherJsonStorage<History> _historyStorage;
|
||||||
private readonly FlowLauncherJsonStorage<UserSelectedRecord> _userSelectedRecordStorage;
|
private readonly FlowLauncherJsonStorage<UserSelectedRecord> _userSelectedRecordStorage;
|
||||||
private readonly FlowLauncherJsonStorageTopMostRecord _topMostRecord;
|
private readonly FlowLauncherJsonStorageTopMostRecord _topMostRecord;
|
||||||
|
|
@ -241,14 +244,16 @@ namespace Flow.Launcher.ViewModel
|
||||||
// Indicate if to clear existing results so to show only ones from plugins with action keywords
|
// Indicate if to clear existing results so to show only ones from plugins with action keywords
|
||||||
var query = item.Query;
|
var query = item.Query;
|
||||||
var currentIsHomeQuery = query.IsHomeQuery;
|
var currentIsHomeQuery = query.IsHomeQuery;
|
||||||
var shouldClearExistingResults = ShouldClearExistingResultsForQuery(query, currentIsHomeQuery);
|
var shouldClearExistingResults =
|
||||||
|
ShouldClearExistingResultsForQuery(query, currentIsHomeQuery);
|
||||||
_lastQuery = item.Query;
|
_lastQuery = item.Query;
|
||||||
_previousIsHomeQuery = currentIsHomeQuery;
|
_previousIsHomeQuery = currentIsHomeQuery;
|
||||||
|
|
||||||
// If the queue already has the item, we need to pass the shouldClearExistingResults flag
|
// If the queue already has the item, we need to pass the shouldClearExistingResults flag
|
||||||
if (queue.TryGetValue(item.ID, out var existingItem))
|
if (queue.TryGetValue(item.ID, out var existingItem))
|
||||||
{
|
{
|
||||||
item.ShouldClearExistingResults = shouldClearExistingResults || existingItem.ShouldClearExistingResults;
|
item.ShouldClearExistingResults = shouldClearExistingResults ||
|
||||||
|
existingItem.ShouldClearExistingResults;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -319,7 +324,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
App.API.LogDebug(ClassName, $"Update results for plugin <{pair.Metadata.Name}>");
|
App.API.LogDebug(ClassName, $"Update results for plugin <{pair.Metadata.Name}>");
|
||||||
|
|
||||||
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query,
|
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query,
|
||||||
token)))
|
token)))
|
||||||
{
|
{
|
||||||
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
|
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
|
||||||
}
|
}
|
||||||
|
|
@ -422,9 +427,11 @@ namespace Flow.Launcher.ViewModel
|
||||||
if (result is DialogJumpResult dialogJumpResult)
|
if (result is DialogJumpResult dialogJumpResult)
|
||||||
{
|
{
|
||||||
Win32Helper.SetForegroundWindow(DialogWindowHandle);
|
Win32Helper.SetForegroundWindow(DialogWindowHandle);
|
||||||
_ = Task.Run(() => DialogJump.JumpToPathAsync(DialogWindowHandle, dialogJumpResult.DialogJumpPath));
|
_ = Task.Run(() =>
|
||||||
|
DialogJump.JumpToPathAsync(DialogWindowHandle, dialogJumpResult.DialogJumpPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -540,12 +547,14 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
_history.AddToHistory(result, Settings);
|
_history.AddToHistory(result, Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
_userSelectedRecord.Add(result);
|
_userSelectedRecord.Add(result);
|
||||||
lastHistoryIndex = 1;
|
lastHistoryIndex = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyList<Result> DeepCloneResults(IReadOnlyList<Result> results, bool isDialogJump, CancellationToken token = default)
|
private static IReadOnlyList<Result> DeepCloneResults(IReadOnlyList<Result> results, bool isDialogJump,
|
||||||
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var resultsCopy = new List<Result>();
|
var resultsCopy = new List<Result>();
|
||||||
|
|
||||||
|
|
@ -569,7 +578,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
resultsCopy.Add(resultCopy);
|
resultsCopy.Add(resultCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultsCopy;
|
return resultsCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -619,7 +628,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
var historyItems = _history.GetHistoryItems(Settings);
|
var historyItems = _history.GetHistoryItems(Settings);
|
||||||
if (QueryResultsSelected() // Results selected
|
if (QueryResultsSelected() // Results selected
|
||||||
&& string.IsNullOrEmpty(QueryText) // No input
|
&& string.IsNullOrEmpty(QueryText) // No input
|
||||||
&& Results.Visibility != Visibility.Visible // No items in result list, e.g. when home page is off and no query text is entered, therefore the view is collapsed.
|
&& Results.Visibility !=
|
||||||
|
Visibility.Visible // No items in result list, e.g. when home page is off and no query text is entered, therefore the view is collapsed.
|
||||||
&& historyItems.Count > 0) // Have history items
|
&& historyItems.Count > 0) // Have history items
|
||||||
{
|
{
|
||||||
lastHistoryIndex = 1;
|
lastHistoryIndex = 1;
|
||||||
|
|
@ -692,6 +702,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
public bool GameModeStatus { get; set; } = false;
|
public bool GameModeStatus { get; set; } = false;
|
||||||
|
|
||||||
private string _queryText;
|
private string _queryText;
|
||||||
|
|
||||||
public string QueryText
|
public string QueryText
|
||||||
{
|
{
|
||||||
get => _queryText;
|
get => _queryText;
|
||||||
|
|
@ -853,7 +864,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
// If we are returning from history and we have not set select item yet,
|
// If we are returning from history and we have not set select item yet,
|
||||||
// we need to clear the preview selected item
|
// we need to clear the preview selected item
|
||||||
if (isReturningFromHistory && _selectedItemFromQueryResults.HasValue && (!_selectedItemFromQueryResults.Value))
|
if (isReturningFromHistory && _selectedItemFromQueryResults.HasValue &&
|
||||||
|
(!_selectedItemFromQueryResults.Value))
|
||||||
{
|
{
|
||||||
PreviewSelectedItem = null;
|
PreviewSelectedItem = null;
|
||||||
}
|
}
|
||||||
|
|
@ -871,6 +883,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
ContextMenu.Visibility = Visibility.Visible;
|
ContextMenu.Visibility = Visibility.Visible;
|
||||||
History.Visibility = Visibility.Collapsed;
|
History.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
_queryTextBeforeLeaveResults = QueryText;
|
_queryTextBeforeLeaveResults = QueryText;
|
||||||
|
|
||||||
// Because of Fody's optimization
|
// Because of Fody's optimization
|
||||||
|
|
@ -886,7 +899,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
// If we are returning from query results and we have not set select item yet,
|
// If we are returning from query results and we have not set select item yet,
|
||||||
// we need to clear the preview selected item
|
// we need to clear the preview selected item
|
||||||
if (isReturningFromQueryResults && _selectedItemFromQueryResults.HasValue && _selectedItemFromQueryResults.Value)
|
if (isReturningFromQueryResults && _selectedItemFromQueryResults.HasValue &&
|
||||||
|
_selectedItemFromQueryResults.Value)
|
||||||
{
|
{
|
||||||
PreviewSelectedItem = null;
|
PreviewSelectedItem = null;
|
||||||
}
|
}
|
||||||
|
|
@ -896,7 +910,9 @@ namespace Flow.Launcher.ViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
public Visibility ShowCustomizedPreview
|
public Visibility ShowCustomizedPreview
|
||||||
=> InternalPreviewVisible && PreviewSelectedItem?.Result.PreviewPanel != null ? Visibility.Visible : Visibility.Collapsed;
|
=> InternalPreviewVisible && PreviewSelectedItem?.Result.PreviewPanel != null
|
||||||
|
? Visibility.Visible
|
||||||
|
: Visibility.Collapsed;
|
||||||
|
|
||||||
public UserControl CustomizedPreviewControl
|
public UserControl CustomizedPreviewControl
|
||||||
=> ShowCustomizedPreview == Visibility.Visible ? PreviewSelectedItem?.Result.PreviewPanel.Value : null;
|
=> ShowCustomizedPreview == Visibility.Visible ? PreviewSelectedItem?.Result.PreviewPanel.Value : null;
|
||||||
|
|
@ -917,9 +933,10 @@ namespace Flow.Launcher.ViewModel
|
||||||
public double SearchIconOpacity { get; set; } = 1;
|
public double SearchIconOpacity { get; set; } = 1;
|
||||||
|
|
||||||
private string _placeholderText;
|
private string _placeholderText;
|
||||||
|
|
||||||
public string PlaceholderText
|
public string PlaceholderText
|
||||||
{
|
{
|
||||||
get => string.IsNullOrEmpty(_placeholderText) ? Localize.queryTextBoxPlaceholder(): _placeholderText;
|
get => string.IsNullOrEmpty(_placeholderText) ? Localize.queryTextBoxPlaceholder() : _placeholderText;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_placeholderText = value;
|
_placeholderText = value;
|
||||||
|
|
@ -1015,6 +1032,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
private bool? _selectedItemFromQueryResults;
|
private bool? _selectedItemFromQueryResults;
|
||||||
|
|
||||||
private ResultViewModel _previewSelectedItem;
|
private ResultViewModel _previewSelectedItem;
|
||||||
|
|
||||||
public ResultViewModel PreviewSelectedItem
|
public ResultViewModel PreviewSelectedItem
|
||||||
{
|
{
|
||||||
get => _previewSelectedItem;
|
get => _previewSelectedItem;
|
||||||
|
|
@ -1035,7 +1053,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
if (ResultAreaColumn == ResultAreaColumnPreviewHidden)
|
if (ResultAreaColumn == ResultAreaColumnPreviewHidden)
|
||||||
return false;
|
return false;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
throw new NotImplementedException("ResultAreaColumn should match ResultAreaColumnPreviewShown/ResultAreaColumnPreviewHidden value");
|
throw new NotImplementedException(
|
||||||
|
"ResultAreaColumn should match ResultAreaColumnPreviewShown/ResultAreaColumnPreviewHidden value");
|
||||||
#else
|
#else
|
||||||
App.API.LogError(ClassName, "ResultAreaColumnPreviewHidden/ResultAreaColumnPreviewShown int value not implemented", "InternalPreviewVisible");
|
App.API.LogError(ClassName, "ResultAreaColumnPreviewHidden/ResultAreaColumnPreviewShown int value not implemented", "InternalPreviewVisible");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1161,6 +1180,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
HideInternalPreview();
|
HideInternalPreview();
|
||||||
_ = OpenExternalPreviewAsync(path);
|
_ = OpenExternalPreviewAsync(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case true
|
case true
|
||||||
when !CanExternalPreviewSelectedResult(out var _):
|
when !CanExternalPreviewSelectedResult(out var _):
|
||||||
|
|
@ -1169,6 +1189,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
await CloseExternalPreviewAsync();
|
await CloseExternalPreviewAsync();
|
||||||
ShowInternalPreview();
|
ShowInternalPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case false
|
case false
|
||||||
when InternalPreviewVisible:
|
when InternalPreviewVisible:
|
||||||
|
|
@ -1257,10 +1278,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
List<Result> results;
|
List<Result> results;
|
||||||
if (selected.PluginID == null) // SelectedItem from history in home page.
|
if (selected.PluginID == null) // SelectedItem from history in home page.
|
||||||
{
|
{
|
||||||
results = new()
|
results = new() { ContextMenuTopMost(selected) };
|
||||||
{
|
|
||||||
ContextMenuTopMost(selected)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1272,20 +1290,19 @@ namespace Flow.Launcher.ViewModel
|
||||||
if (!string.IsNullOrEmpty(query))
|
if (!string.IsNullOrEmpty(query))
|
||||||
{
|
{
|
||||||
var filtered = results.Select(x => x.Clone()).Where
|
var filtered = results.Select(x => x.Clone()).Where
|
||||||
(
|
(r =>
|
||||||
r =>
|
{
|
||||||
|
var match = App.API.FuzzySearch(query, r.Title);
|
||||||
|
if (!match.IsSearchPrecisionScoreMet())
|
||||||
{
|
{
|
||||||
var match = App.API.FuzzySearch(query, r.Title);
|
match = App.API.FuzzySearch(query, r.SubTitle);
|
||||||
if (!match.IsSearchPrecisionScoreMet())
|
}
|
||||||
{
|
|
||||||
match = App.API.FuzzySearch(query, r.SubTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!match.IsSearchPrecisionScoreMet()) return false;
|
if (!match.IsSearchPrecisionScoreMet()) return false;
|
||||||
|
|
||||||
r.Score = match.Score;
|
r.Score = match.Score;
|
||||||
return true;
|
return true;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
ContextMenu.AddResults(filtered, id);
|
ContextMenu.AddResults(filtered, id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1308,9 +1325,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
if (!string.IsNullOrEmpty(query))
|
if (!string.IsNullOrEmpty(query))
|
||||||
{
|
{
|
||||||
var filtered = results.Where
|
var filtered = results.Where
|
||||||
(
|
(r => App.API.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet() ||
|
||||||
r => App.API.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet() ||
|
App.API.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet()
|
||||||
App.API.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet()
|
|
||||||
).ToList();
|
).ToList();
|
||||||
History.AddResults(filtered, id);
|
History.AddResults(filtered, id);
|
||||||
}
|
}
|
||||||
|
|
@ -1320,14 +1336,15 @@ namespace Flow.Launcher.ViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Result> GetHistoryResults(IEnumerable<HistoryItem> historyItems)
|
private List<Result> GetHistoryResults(IEnumerable<HistoryItem> historyItems)
|
||||||
{
|
{
|
||||||
var results = new List<Result>();
|
var results = new List<Result>();
|
||||||
foreach (var h in historyItems)
|
foreach (var h in historyItems)
|
||||||
{
|
{
|
||||||
var result = new Result
|
var result = new Result
|
||||||
{
|
{
|
||||||
Title = Settings.ShowHistoryLastOpenedResultsForHomePage ? Localize.executeQuery(h.Query) : h.Title
|
Title =
|
||||||
|
Settings.ShowHistoryQueryResultsForHomePage ? Localize.executeQuery(h.OriginQuery.RawQuery) : h.Title,
|
||||||
SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime),
|
SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime),
|
||||||
IcoPath = Constant.HistoryIcon,
|
IcoPath = Constant.HistoryIcon,
|
||||||
PluginID = h.PluginID,
|
PluginID = h.PluginID,
|
||||||
|
|
@ -1337,10 +1354,11 @@ namespace Flow.Launcher.ViewModel
|
||||||
};
|
};
|
||||||
results.Add(result);
|
results.Add(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, bool reSelect = true)
|
private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, bool reSelect = true)
|
||||||
{
|
{
|
||||||
_updateSource?.Cancel();
|
_updateSource?.Cancel();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue