Welcome Page Port Part 1

This commit is contained in:
Hongtao Zhang 2024-01-18 21:46:21 -06:00
parent 2d8490b4d9
commit 4c7b5921e6
38 changed files with 1170 additions and 1015 deletions

View file

@ -3,6 +3,9 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using Avalonia.Input;
using Key = Avalonia.Input.Key;
using KeyGesture = Avalonia.Input.KeyGesture;
namespace Flow.Launcher.Infrastructure.Hotkey
{
@ -17,8 +20,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey
private static readonly Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string>
{
{Key.Space, "Space"},
{Key.Oem3, "~"}
{ Key.Space, "Space" }, { Key.Oem3, "~" }
};
public ModifierKeys ModifierKeys
@ -30,18 +32,22 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{
modifierKeys |= ModifierKeys.Alt;
}
if (Shift)
{
modifierKeys |= ModifierKeys.Shift;
}
if (Win)
{
modifierKeys |= ModifierKeys.Windows;
}
if (Ctrl)
{
modifierKeys |= ModifierKeys.Control;
}
return modifierKeys;
}
}
@ -66,31 +72,37 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{
return;
}
List<string> keys = hotkeyString.Replace(" ", "").Split('+').ToList();
if (keys.Contains("Alt"))
{
Alt = true;
keys.Remove("Alt");
}
if (keys.Contains("Shift"))
{
Shift = true;
keys.Remove("Shift");
}
if (keys.Contains("Win"))
{
Win = true;
keys.Remove("Win");
}
if (keys.Contains("Ctrl"))
{
Ctrl = true;
keys.Remove("Ctrl");
}
if (keys.Count == 1)
{
string charKey = keys[0];
KeyValuePair<Key, string>? specialSymbolPair = specialSymbolDictionary.FirstOrDefault(pair => pair.Value == charKey);
KeyValuePair<Key, string>? specialSymbolPair =
specialSymbolDictionary.FirstOrDefault(pair => pair.Value == charKey);
if (specialSymbolPair.Value.Value != null)
{
CharKey = specialSymbolPair.Value.Key;
@ -103,7 +115,6 @@ namespace Flow.Launcher.Infrastructure.Hotkey
}
catch (ArgumentException)
{
}
}
}
@ -116,14 +127,17 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{
keys.Add("Ctrl");
}
if (Alt)
{
keys.Add("Alt");
}
if (Shift)
{
keys.Add("Shift");
}
if (Win)
{
keys.Add("Win");
@ -135,9 +149,10 @@ namespace Flow.Launcher.Infrastructure.Hotkey
? specialSymbolDictionary[CharKey]
: CharKey.ToString());
}
return string.Join(" + ", keys);
}
/// <summary>
/// Validate hotkey
/// </summary>
@ -162,13 +177,15 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{
try
{
KeyGesture keyGesture = new KeyGesture(CharKey, ModifierKeys);
KeyGesture keyGesture = new KeyGesture(CharKey, ToKeyModifiers(ModifierKeys));
}
catch (System.Exception e) when (e is NotSupportedException || e is InvalidEnumArgumentException)
catch (System.Exception e) when
(e is NotSupportedException || e is InvalidEnumArgumentException)
{
return false;
}
}
if (ModifierKeys == ModifierKeys.None)
{
return !IsPrintableCharacter(CharKey);
@ -180,6 +197,58 @@ namespace Flow.Launcher.Infrastructure.Hotkey
}
}
public ModifierKeys ToModifierKeys(KeyModifiers keyModifiers)
{
ModifierKeys modifierKeys = ModifierKeys.None;
if (keyModifiers.HasFlag(KeyModifiers.Alt))
{
modifierKeys |= ModifierKeys.Alt;
}
if (keyModifiers.HasFlag(KeyModifiers.Shift))
{
modifierKeys |= ModifierKeys.Shift;
}
if (keyModifiers.HasFlag(KeyModifiers.Meta))
{
modifierKeys |= ModifierKeys.Windows;
}
if (keyModifiers.HasFlag(KeyModifiers.Control))
{
modifierKeys |= ModifierKeys.Control;
}
return modifierKeys;
}
public KeyModifiers ToKeyModifiers(ModifierKeys modifierKeys)
{
KeyModifiers keyModifiers = KeyModifiers.None;
if (modifierKeys.HasFlag(ModifierKeys.Alt))
{
keyModifiers |= KeyModifiers.Alt;
}
if (modifierKeys.HasFlag(ModifierKeys.Shift))
{
keyModifiers |= KeyModifiers.Shift;
}
if (modifierKeys.HasFlag(ModifierKeys.Windows))
{
keyModifiers |= KeyModifiers.Meta;
}
if (modifierKeys.HasFlag(ModifierKeys.Control))
{
keyModifiers |= KeyModifiers.Control;
}
return keyModifiers;
}
private static bool IsPrintableCharacter(Key key)
{
// https://stackoverflow.com/questions/11881199/identify-if-a-event-key-is-text-not-only-alphanumeric

View file

@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using Avalonia.Media.Imaging;
@ -11,7 +12,6 @@ namespace Flow.Launcher.Infrastructure.Image
[Serializable]
public class ImageUsage
{
public int usage;
public Bitmap imageSource;
@ -24,7 +24,7 @@ namespace Flow.Launcher.Infrastructure.Image
public class ImageCache
{
private const int MaxCached = 50;
private const int MaxCached = 150;
public ConcurrentDictionary<(string, bool), ImageUsage> Data { get; } = new();
private const int permissibleFactor = 2;
private SemaphoreSlim semaphore = new(1, 1);
@ -45,9 +45,9 @@ namespace Flow.Launcher.Infrastructure.Image
{
return null;
}
value.usage++;
return value.imageSource;
}
set
{
@ -64,7 +64,7 @@ namespace Flow.Launcher.Infrastructure.Image
SliceExtra();
async void SliceExtra()
async Task SliceExtra()
{
// To prevent the dictionary from drastically increasing in size by caching images, the dictionary size is not allowed to grow more than the permissibleFactor * maxCached size
// This is done so that we don't constantly perform this resizing operation and also maintain the image cache size at the same time
@ -74,7 +74,8 @@ namespace Flow.Launcher.Infrastructure.Image
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary
// Double Check to avoid concurrent remove
if (Data.Count > permissibleFactor * MaxCached)
foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached)
.Select(x => x.Key))
Data.TryRemove(key, out _);
semaphore.Release();
}
@ -84,7 +85,8 @@ namespace Flow.Launcher.Infrastructure.Image
public bool ContainsKey(string key, bool isFullImage)
{
return key is not null && Data.ContainsKey((key, isFullImage)) && Data[(key, isFullImage)].imageSource != null;
return key is not null && Data.ContainsKey((key, isFullImage)) &&
Data[(key, isFullImage)].imageSource != null;
}
public bool TryGetValue(string key, bool isFullImage, out Bitmap image)

View file

@ -4,7 +4,10 @@
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Resources>
<FontFamily x:Key="UIFont">avares://Flow.Launcher/Resources/#Segoe Fluent Icons</FontFamily>
</Application.Resources>
<Application.Styles>
<FluentTheme />
</Application.Styles>

View file

@ -45,6 +45,21 @@
<ItemGroup>
<Page Remove="Themes\ThemeBuilder\Template.xaml" />
<Page Update="Pages\WelcomePage1.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Pages\WelcomePage2.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Pages\WelcomePage3.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Pages\WelcomePage4.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Pages\WelcomePage5.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
@ -77,6 +92,7 @@
<Content Include="Resources\*.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<AvaloniaResource Include="Resources\*.ttf"/>
</ItemGroup>
<ItemGroup>

View file

@ -5,6 +5,7 @@ using NHotkey;
using NHotkey.Wpf;
using Flow.Launcher.Core.Resource;
using System.Windows;
using System.Windows.Input;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher.Helper
@ -40,13 +41,15 @@ namespace Flow.Launcher.Helper
string hotkeyStr = hotkey.ToString();
try
{
HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys, action);
HotkeyManager.Current.AddOrReplace(hotkeyStr, (Key)hotkey.CharKey, hotkey.ModifierKeys, action);
}
catch (Exception)
{
string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr);
string errorMsg =
string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"),
hotkeyStr);
string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle");
MessageBox.Show(errorMsg,errorMsgTitle);
MessageBox.Show(errorMsg, errorMsgTitle);
}
}
@ -85,7 +88,8 @@ namespace Flow.Launcher.Helper
{
try
{
HotkeyManager.Current.AddOrReplace("HotkeyAvailabilityTest", currentHotkey.CharKey, currentHotkey.ModifierKeys, (sender, e) => { });
HotkeyManager.Current.AddOrReplace("HotkeyAvailabilityTest", (Key)currentHotkey.CharKey,
currentHotkey.ModifierKeys, (sender, e) => { });
return true;
}

View file

@ -1,27 +1,23 @@
<UserControl
x:Class="Flow.Launcher.HotkeyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:launcher="clr-namespace:Flow.Launcher"
Height="24"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
mc:Ignorable="d"
x:DataType="launcher:HotkeyControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Popup
x:Name="popup"
AllowDrop="True"
AllowsTransparency="True"
IsOpen="{Binding IsKeyboardFocused, ElementName=tbHotkey, Mode=OneWay}"
Placement="Top"
PlacementTarget="{Binding ElementName=tbHotkey}"
PopupAnimation="Fade"
StaysOpen="True"
VerticalOffset="-5">
<Border
Width="140"
@ -38,8 +34,7 @@
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}"
Text="{DynamicResource flowlauncherPressHotkey}"
Visibility="Visible" />
Text="{DynamicResource flowlauncherPressHotkey}"/>
</Border>
</Popup>
@ -47,10 +42,8 @@
x:Name="tbHotkey"
Margin="0,0,18,0"
VerticalContentAlignment="Center"
input:InputMethod.IsInputMethodEnabled="False"
GotFocus="tbHotkey_GotFocus"
LostFocus="tbHotkey_LostFocus"
PreviewKeyDown="TbHotkey_OnPreviewKeyDown"
KeyDown="TbHotkey_OnPreviewKeyDown"
TabIndex="100" />
</Grid>
</UserControl>

View file

@ -1,17 +1,22 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using System.Threading;
using System.Windows.Input;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Threading;
using PropertyChanged;
using FocusManager = Avalonia.Input.FocusManager;
using Key = Avalonia.Input.Key;
using KeyEventArgs = Avalonia.Input.KeyEventArgs;
namespace Flow.Launcher
{
[DoNotNotify]
public partial class HotkeyControl : UserControl
{
public HotkeyModel CurrentHotkey { get; private set; }
@ -42,7 +47,7 @@ namespace Flow.Launcher
e.Handled = true;
//when alt is pressed, the real key should be e.SystemKey
Key key = e.Key == Key.System ? e.SystemKey : e.Key;
Key key = e.Key;
SpecialKeyState specialKeyState = GlobalHotkey.CheckModifiers();
@ -58,7 +63,7 @@ namespace Flow.Launcher
return;
}
_ = Dispatcher.InvokeAsync(async () =>
_ = Dispatcher.UIThread.InvokeAsync(async () =>
{
await Task.Delay(500, token);
if (!token.IsCancellationRequested)
@ -69,7 +74,7 @@ namespace Flow.Launcher
public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true)
{
tbHotkey.Text = keyModel.ToString();
tbHotkey.Select(tbHotkey.Text.Length, 0);
// tbHotkey.Select(tbHotkey.Text.Length, 0);
if (triggerValidate)
{
@ -87,7 +92,6 @@ namespace Flow.Launcher
{
CurrentHotkey = keyModel;
// To trigger LostFocus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null);
Keyboard.ClearFocus();
}
}
@ -96,20 +100,21 @@ namespace Flow.Launcher
CurrentHotkey = keyModel;
}
}
public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true)
{
return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate);
}
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) =>
hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
public new bool IsFocused => tbHotkey.IsFocused;
private void tbHotkey_LostFocus(object sender, RoutedEventArgs e)
{
tbHotkey.Text = CurrentHotkey?.ToString() ?? "";
tbHotkey.Select(tbHotkey.Text.Length, 0);
// tbHotkey.Select(tbHotkey.Text.Length, 0);
}
private void tbHotkey_GotFocus(object sender, RoutedEventArgs e)
@ -120,22 +125,23 @@ namespace Flow.Launcher
private void ResetMessage()
{
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("flowlauncherPressHotkey");
tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B");
// tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B");
}
private void SetMessage(bool hotkeyAvailable)
{
if (!hotkeyAvailable)
{
tbMsg.Foreground = new SolidColorBrush(Colors.Red);
// tbMsg.Foreground = new SolidColorBrush(Colors.Red);
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable");
}
else
{
tbMsg.Foreground = new SolidColorBrush(Colors.Green);
// tbMsg.Foreground = new SolidColorBrush(Colors.Green);
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("success");
}
tbMsg.Visibility = Visibility.Visible;
// tbMsg.Visibility = Visibility.Visible;
}
}
}

View file

@ -336,7 +336,7 @@ namespace Flow.Launcher
private void CheckFirstLaunch()
{
if (_settings.FirstLaunch)
// if (_settings.FirstLaunch)
{
_settings.FirstLaunch = false;
PluginManager.API.SaveAppAllSettings();
@ -347,7 +347,7 @@ namespace Flow.Launcher
private void OpenWelcomeWindow()
{
var WelcomeWindow = new WelcomeWindow(_settings);
WelcomeWindow.Show();
WelcomeWindow.ShowDialog(this);
}
private async void PositionReset()
@ -539,11 +539,11 @@ namespace Flow.Launcher
public void HideStartup()
{
UpdatePosition();
if (_settings.HideOnStartup)
{
_viewModel.Hide();
}
else
// if (_settings.HideOnStartup)
// {
// _viewModel.Hide();
// }
// else
{
_viewModel.Show();
}

View file

@ -1,189 +0,0 @@
<ui:Page
x:Class="Flow.Launcher.Resources.Pages.WelcomePage1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="WelcomePage1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}">
<Style.Triggers>
<!-- Fades-in the image when it becomes visible -->
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard x:Name="FadeIn">
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)"
From="105"
To="95"
Duration="0:0:1">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:1">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="StyleImageFadeInText" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard x:Name="FadeIn">
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)"
From="110"
To="100"
Duration="0:0:1">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:1">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="WizardMove" TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard x:Name="Move">
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Bottom)"
From="-150"
To="0"
Duration="0:0:2.5">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#1494df" />
<GradientStop Offset="1.0" Color="#1073bd" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Canvas Width="550" Height="250">
<Image
Name="Logo"
Canvas.Left="140"
Width="60"
Height="60"
Source="../../images/app.png"
Style="{DynamicResource StyleImageFadeIn}" />
<TextBlock
Canvas.Left="205"
Margin="12,0,0,0"
VerticalAlignment="Center"
FontSize="30"
Foreground="White"
Opacity="0"
Style="{DynamicResource StyleImageFadeInText}">
Flow Launcher
</TextBlock>
</Canvas>
</StackPanel>
</Border>
<Canvas Grid.Row="1" Height="288">
<Image
Name="wizard"
Canvas.Right="30"
Canvas.Bottom="0"
Width="60"
Height="60"
Source="../../images/wizard.png"
Style="{DynamicResource WizardMove}" />
<StackPanel Width="550" Margin="24,20,24,20">
<StackPanel Margin="0,0,24,0">
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page1_Title}" />
<TextBlock
Margin="0,10,24,0"
FontSize="14"
Text="{DynamicResource Welcome_Page1_Text01}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,10,24,0"
FontSize="14"
Text="{DynamicResource Welcome_Page1_Text02}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,30,0,0"
FontSize="14"
FontWeight="SemiBold"
Text="{DynamicResource language}" />
<ComboBox
Width="200"
Margin="0,10,0,0"
DisplayMemberPath="Display"
ItemsSource="{Binding Languages}"
SelectedValue="{Binding CustomLanguage, Mode=TwoWay}"
SelectedValuePath="LanguageCode" />
</StackPanel>
</StackPanel>
</Canvas>
</Grid>
</ScrollViewer>
</ui:Page>

View file

@ -1,52 +0,0 @@
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Navigation;
namespace Flow.Launcher.Resources.Pages
{
public partial class WelcomePage2
{
private Settings Settings { get; set; }
private Brush tbMsgForegroundColorOriginal;
private string tbMsgTextOriginal;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.ExtraData is Settings settings)
Settings = settings;
else
throw new ArgumentException("Unexpected Parameter setting.");
InitializeComponent();
tbMsgTextOriginal = HotkeyControl.tbMsg.Text;
tbMsgForegroundColorOriginal = HotkeyControl.tbMsg.Foreground;
HotkeyControl.SetHotkeyAsync(Settings.Hotkey, false);
}
private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args)
{
HotKeyMapper.RemoveHotkey(Settings.Hotkey);
}
private void HotkeyControl_OnLostFocus(object sender, RoutedEventArgs args)
{
if (HotkeyControl.CurrentHotkeyAvailable)
{
HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
Settings.Hotkey = HotkeyControl.CurrentHotkey.ToString();
}
else
{
HotKeyMapper.SetHotkey(new HotkeyModel(Settings.Hotkey), HotKeyMapper.OnToggleHotkey);
}
HotkeyControl.tbMsg.Text = tbMsgTextOriginal;
HotkeyControl.tbMsg.Foreground = tbMsgForegroundColorOriginal;
}
}
}

View file

@ -1,20 +0,0 @@
using System;
using System.Windows.Navigation;
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.Resources.Pages
{
public partial class WelcomePage3
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.ExtraData is Settings settings)
Settings = settings;
else if(Settings is null)
throw new ArgumentException("Unexpected Navigation Parameter for Settings");
InitializeComponent();
}
public Settings Settings { get; set; }
}
}

View file

@ -1,136 +0,0 @@
<ui:Page
x:Class="Flow.Launcher.Resources.Pages.WelcomePage4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="WelcomePage4"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard x:Name="Move">
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Left)"
From="0"
To="100"
Duration="0:0:20">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="RecommendQuery" TargetType="Border">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="20,7,12,7" />
<Setter Property="Margin" Value="4,4,4,4" />
<Setter Property="Background" Value="{DynamicResource Color01B}" />
</Style>
<Style x:Key="QueryText" TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Left" />
<Setter Property="TextAlignment" Value="Left" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
<Style x:Key="ResultText" TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Left" />
<Setter Property="TextAlignment" Value="Left" />
<Setter Property="FontSize" Value="13" />
<Setter Property="Margin" Value="0,4,0,0" />
<Setter Property="Foreground" Value="{DynamicResource Color04B}" />
</Style>
</Page.Resources>
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#e8457c" />
<GradientStop Offset="1.0" Color="#bc1948" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Canvas
Width="600"
Height="301"
ClipToBounds="True">
<Image
Name="Logo"
Canvas.Left="0"
Width="450"
Height="280"
Margin="0,0,0,0"
Source="../../images/page_img01.png"
Style="{DynamicResource StyleImageFadeIn}" />
</Canvas>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Margin="24,20,24,20">
<StackPanel>
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page4_Title}" />
<TextBlock
Margin="0,10,0,10"
FontSize="14"
Text="{DynamicResource Welcome_Page4_Text01}"
TextWrapping="WrapWithOverflow" />
<UniformGrid
Margin="0,14,0,0"
Columns="2"
Rows="2">
<Border Style="{DynamicResource RecommendQuery}">
<StackPanel>
<TextBlock Style="{DynamicResource QueryText}" Text="{DynamicResource RecommendWeather}" />
<TextBlock Style="{DynamicResource ResultText}" Text="{DynamicResource RecommendWeatherDesc}" />
</StackPanel>
</Border>
<Border Style="{DynamicResource RecommendQuery}">
<StackPanel>
<TextBlock Style="{DynamicResource QueryText}" Text="{DynamicResource RecommendShell}" />
<TextBlock Style="{DynamicResource ResultText}" Text="{DynamicResource RecommendShellDesc}" />
</StackPanel>
</Border>
<Border Style="{DynamicResource RecommendQuery}">
<StackPanel>
<TextBlock Style="{DynamicResource QueryText}" Text="{DynamicResource RecommendBluetooth}" />
<TextBlock Style="{DynamicResource ResultText}" Text="{DynamicResource RecommendBluetoothDesc}" />
</StackPanel>
</Border>
<Border Style="{DynamicResource RecommendQuery}">
<StackPanel>
<TextBlock Style="{DynamicResource QueryText}" Text="{DynamicResource RecommendAcronyms}" />
<TextBlock Style="{DynamicResource ResultText}" Text="{DynamicResource RecommendAcronymsDesc}" />
</StackPanel>
</Border>
</UniformGrid>
</StackPanel>
</StackPanel>
</Grid>
</ScrollViewer>
</ui:Page>

View file

@ -1,20 +0,0 @@
using Flow.Launcher.Infrastructure.UserSettings;
using System;
using System.Windows.Navigation;
namespace Flow.Launcher.Resources.Pages
{
public partial class WelcomePage4
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.ExtraData is Settings settings)
Settings = settings;
else
throw new ArgumentException("Unexpected Navigation Parameter for Settings");
InitializeComponent();
}
public Settings Settings { get; set; }
}
}

View file

@ -1,122 +0,0 @@
<ui:Page
x:Class="Flow.Launcher.Resources.Pages.WelcomePage5"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure"
Title="WelcomePage5"
d:DesignHeight="450"
d:DesignWidth="800"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}">
<Setter Property="Opacity" Value="0" />
<Style.Triggers>
<!-- Fades-in the image when it becomes visible -->
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard x:Name="FadeIn">
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)"
From="110"
To="75"
Duration="0:0:1">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:1">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#7b83eb" />
<GradientStop Offset="1.0" Color="#555dc0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Canvas Width="550" Height="250">
<Image
Name="Logo"
Canvas.Left="225"
Width="100"
Height="100"
Source="../../images/app.png"
Style="{DynamicResource StyleImageFadeIn}" />
</Canvas>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Margin="24,20,24,20">
<StackPanel>
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page5_Title}" />
<TextBlock
Margin="0,10,0,0"
FontSize="14"
Text="{DynamicResource Welcome_Page5_Text01}"
TextWrapping="WrapWithOverflow" />
<StackPanel Margin="0,30,0,0" Orientation="Horizontal">
<CheckBox
Checked="OnAutoStartupChecked"
Content="{DynamicResource startFlowLauncherOnSystemStartup}"
IsChecked="{Binding Settings.StartFlowLauncherOnSystemStartup}"
Style="{DynamicResource DefaultCheckBoxStyle}"
Unchecked="OnAutoStartupUncheck" />
</StackPanel>
<StackPanel Margin="0,0,0,0" Orientation="Horizontal">
<CheckBox
Checked="OnHideOnStartupChecked"
Content="{DynamicResource hideOnStartup}"
IsChecked="{Binding Settings.HideOnStartup}"
Style="{DynamicResource DefaultCheckBoxStyle}"
Unchecked="OnHideOnStartupUnchecked" />
</StackPanel>
<Button
Width="150"
Height="40"
Margin="0,60,0,0"
HorizontalAlignment="Right"
Click="BtnCancel_OnClick"
Content="{DynamicResource done}"
Style="{DynamicResource AccentButtonStyle}" />
</StackPanel>
</StackPanel>
</Grid>
</ScrollViewer>
</ui:Page>

View file

@ -258,7 +258,7 @@ namespace Flow.Launcher
private void OpenWelcomeWindow(object sender, RoutedEventArgs e)
{
var WelcomeWindow = new WelcomeWindow(settings);
WelcomeWindow.ShowDialog();
WelcomeWindow.ShowDialog(null);
}
private void OpenLogFolder(object sender, RoutedEventArgs e)
{

View file

@ -0,0 +1,36 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Flow.Launcher.Plugin;
using ReactiveUI;
namespace Flow.Launcher
{
public class ViewLocator : IDataTemplate
{
public Control Build(object? data)
{
if (data is null)
{
return new TextBlock { Text = "data was null" };
}
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
else
{
return new TextBlock { Text = "Not Found: " + name };
}
}
public bool Match(object? data)
{
return data is ReactiveObject;
}
}
}

View file

@ -58,7 +58,7 @@ namespace Flow.Launcher.ViewModel
Glyph = glyph;
}
}
LoadImage();
}
@ -177,7 +177,7 @@ namespace Flow.Launcher.ViewModel
}
}
return default; // await ImageLoader.LoadAsync(imagePath, loadFullImage).ConfigureAwait(false);
return await ImageLoader.LoadAsync(imagePath, loadFullImage).ConfigureAwait(false);
}
private void LoadImage()

View file

@ -0,0 +1,19 @@
using Flow.Launcher.Plugin;
namespace Flow.Launcher.ViewModel.WelcomePages
{
public abstract class PageViewModelBase : BaseModel
{
/// <summary>
/// Gets if the user can navigate to the next page
/// </summary>
public abstract bool CanNavigateNext { get; protected set; }
/// <summary>
/// Gets if the user can navigate to the previous page
/// </summary>
public abstract bool CanNavigatePrevious { get; protected set; }
public abstract string PageTitle { get; }
}
}

View file

@ -1,21 +1,21 @@
using System;
using System.Collections.Generic;
using System.Windows.Navigation;
using Flow.Launcher.Infrastructure.UserSettings;
using System.Collections.Generic;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.Resources.Pages
namespace Flow.Launcher.ViewModel.WelcomePages
{
public partial class WelcomePage1
public class WelcomePage1ViewModel : PageViewModelBase
{
protected override void OnNavigatedTo(NavigationEventArgs e)
public override bool CanNavigateNext { get; protected set; } = true;
public override bool CanNavigatePrevious { get; protected set; } = false;
public override string PageTitle { get; }
public WelcomePage1ViewModel(Settings settings)
{
if (e.ExtraData is Settings settings)
Settings = settings;
else
throw new ArgumentException("Unexpected Navigation Parameter for Settings");
InitializeComponent();
PageTitle = _translater.GetTranslation("welcomePage1Title");
Settings = settings;
}
private Internationalization _translater => InternationalizationManager.Instance;
public List<Language> Languages => _translater.LoadAvailableLanguages();
@ -35,6 +35,5 @@ namespace Flow.Launcher.Resources.Pages
Settings.ShouldUsePinyin = true;
}
}
}
}
}

View file

@ -0,0 +1,21 @@
using Avalonia.Interactivity;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.ViewModel.WelcomePages
{
public class WelcomePage2ViewModel : PageViewModelBase
{
public override bool CanNavigateNext { get; protected set; }
public override bool CanNavigatePrevious { get; protected set; }
public override string PageTitle { get; }
public Settings Settings { get; set; }
public WelcomePage2ViewModel(Settings settings)
{
Settings = settings;
}
}
}

View file

@ -0,0 +1,18 @@
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.ViewModel.WelcomePages
{
public class WelcomePage3ViewModel : PageViewModelBase
{
public override bool CanNavigateNext { get; protected set; }
public override bool CanNavigatePrevious { get; protected set; }
public override string PageTitle { get; }
public WelcomePage3ViewModel(Settings settings)
{
Settings = settings;
}
public Settings Settings { get; set; }
}
}

View file

@ -0,0 +1,18 @@
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.ViewModel.WelcomePages
{
public class WelcomePage4ViewModel : PageViewModelBase
{
public override bool CanNavigateNext { get; protected set; }
public override bool CanNavigatePrevious { get; protected set; }
public override string PageTitle { get; }
public WelcomePage4ViewModel(Settings settings)
{
Settings = settings;
}
public Settings Settings { get; set; }
}
}

View file

@ -0,0 +1,18 @@
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher.ViewModel.WelcomePages
{
public class WelcomePage5ViewModel : PageViewModelBase
{
public override bool CanNavigateNext { get; protected set; }
public override bool CanNavigatePrevious { get; protected set; }
public override string PageTitle { get; }
public WelcomePage5ViewModel(Settings settings)
{
Settings = settings;
}
public Settings Settings { get; set; }
}
}

View file

@ -0,0 +1,70 @@
using System.Reactive;
using System.Windows.Input;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel.WelcomePages;
using ReactiveUI;
namespace Flow.Launcher.ViewModel
{
public class WelcomeWindowViewModel : ReactiveObject
{
private PageViewModelBase _currentPage;
public WelcomeWindowViewModel(Settings settings)
{
Pages =
[
new WelcomePage1ViewModel(settings), new WelcomePage2ViewModel(settings),
new WelcomePage3ViewModel(settings), new WelcomePage4ViewModel(settings),
new WelcomePage5ViewModel(settings)
];
CurrentPage = Pages[0];
// Create Observables which will activate to deactivate our commands based on CurrentPage state
var canNavNext = this.WhenAnyValue(x => x.CurrentPage.CanNavigateNext);
var canNavPrev = this.WhenAnyValue(x => x.CurrentPage.CanNavigatePrevious);
NavigateNextCommand = ReactiveCommand.Create(NavigateNext, canNavNext);
NavigatePreviousCommand = ReactiveCommand.Create(NavigatePrevious, canNavPrev);
}
public ICommand NavigateNextCommand { get; set; }
public PageViewModelBase CurrentPage
{
get { return _currentPage; }
private set { this.RaiseAndSetIfChanged(ref _currentPage, value); }
}
public string PageDisplay => CurrentPage.PageTitle;
private PageViewModelBase[] Pages { get; }
private int CurrentPageIndex { get; set; }
private void NavigateNext()
{
// get the current index and add 1
CurrentPageIndex++;
// /!\ Be aware that we have no check if the index is valid. You may want to add it on your own. /!\
CurrentPage = Pages[CurrentPageIndex];
}
/// <summary>
/// Gets a command that navigates to the previous page
/// </summary>
public ICommand NavigatePreviousCommand { get; }
private void NavigatePrevious()
{
// get the current index and subtract 1
CurrentPageIndex--;
// /!\ Be aware that we have no check if the index is valid. You may want to add it on your own. /!\
CurrentPage = Pages[CurrentPageIndex];
}
}
}

View file

@ -0,0 +1,183 @@
<UserControl
x:Class="Flow.Launcher.WelcomePages.WelcomePage1"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:welcomePages="clr-namespace:Flow.Launcher.ViewModel.WelcomePages"
x:DataType="welcomePages:WelcomePage1ViewModel"
mc:Ignorable="d">
<!-- <Page.Resources> -->
<!-- <Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}"> -->
<!-- <Style.Triggers> -->
<!-- ~1~ Fades-in the image when it becomes visible @1@ -->
<!-- <Trigger Property="IsVisible" Value="True"> -->
<!-- <Trigger.EnterActions> -->
<!-- <BeginStoryboard> -->
<!-- <BeginStoryboard.Storyboard> -->
<!-- <Storyboard x:Name="FadeIn"> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="(Canvas.Top)" -->
<!-- From="105" -->
<!-- To="95" -->
<!-- Duration="0:0:1"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="Opacity" -->
<!-- From="0" -->
<!-- To="1" -->
<!-- Duration="0:0:1"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- </Storyboard> -->
<!-- </BeginStoryboard.Storyboard> -->
<!-- </BeginStoryboard> -->
<!-- </Trigger.EnterActions> -->
<!-- </Trigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- <Style x:Key="StyleImageFadeInText" TargetType="{x:Type TextBlock}"> -->
<!-- <Style.Triggers> -->
<!-- <Trigger Property="IsVisible" Value="True"> -->
<!-- <Trigger.EnterActions> -->
<!-- <BeginStoryboard> -->
<!-- <BeginStoryboard.Storyboard> -->
<!-- <Storyboard x:Name="FadeIn"> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="(Canvas.Top)" -->
<!-- From="110" -->
<!-- To="100" -->
<!-- Duration="0:0:1"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="Opacity" -->
<!-- From="0" -->
<!-- To="1" -->
<!-- Duration="0:0:1"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- </Storyboard> -->
<!-- </BeginStoryboard.Storyboard> -->
<!-- </BeginStoryboard> -->
<!-- </Trigger.EnterActions> -->
<!-- </Trigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- <Style x:Key="WizardMove" TargetType="{x:Type Image}"> -->
<!-- <Style.Triggers> -->
<!-- <Trigger Property="IsVisible" Value="True"> -->
<!-- <Trigger.EnterActions> -->
<!-- <BeginStoryboard> -->
<!-- <BeginStoryboard.Storyboard> -->
<!-- <Storyboard x:Name="Move"> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="(Canvas.Bottom)" -->
<!-- From="-150" -->
<!-- To="0" -->
<!-- Duration="0:0:2.5"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- </Storyboard> -->
<!-- </BeginStoryboard.Storyboard> -->
<!-- </BeginStoryboard> -->
<!-- </Trigger.EnterActions> -->
<!-- </Trigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- </Page.Resources> -->
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#1494df" />
<GradientStop Offset="1.0" Color="#1073bd" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Canvas Width="550" Height="250">
<Image
Name="Logo"
Canvas.Left="140"
Width="60"
Height="60"
Source="../../images/app.png" />
<TextBlock
Canvas.Left="205"
Margin="12,0,0,0"
VerticalAlignment="Center"
FontSize="30"
Foreground="White"
Opacity="0">
Flow Launcher
</TextBlock>
</Canvas>
</StackPanel>
</Border>
<Canvas Grid.Row="1" Height="288">
<Image
Name="wizard"
Canvas.Right="30"
Canvas.Bottom="0"
Width="60"
Height="60"
Source="../../images/wizard.png" />
<StackPanel Width="550" Margin="24,20,24,20">
<StackPanel Margin="0,0,24,0">
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page1_Title}" />
<TextBlock
Margin="0,10,24,0"
FontSize="14"
Text="{DynamicResource Welcome_Page1_Text01}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,10,24,0"
FontSize="14"
Text="{DynamicResource Welcome_Page1_Text02}"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,30,0,0"
FontSize="14"
FontWeight="SemiBold"
Text="{DynamicResource language}" />
<ComboBox
Width="200"
Margin="0,10,0,0"
DisplayMemberBinding="{Binding Display}"
ItemsSource="{Binding Languages}"
SelectedValue="{Binding CustomLanguage, Mode=TwoWay}"
SelectedValueBinding="{Binding LanguageCode}" />
</StackPanel>
</StackPanel>
</Canvas>
</Grid>
</ScrollViewer>
</UserControl>

View file

@ -0,0 +1,14 @@
using Avalonia.Controls;
using PropertyChanged;
namespace Flow.Launcher.WelcomePages
{
[DoNotNotify]
public partial class WelcomePage1 : UserControl
{
public WelcomePage1()
{
InitializeComponent();
}
}
}

View file

@ -1,38 +1,36 @@
<ui:Page
x:Class="Flow.Launcher.Resources.Pages.WelcomePage2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<UserControl
x:Class="Flow.Launcher.WelcomePages.WelcomePage2"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="WelcomePage2"
xmlns:welcomePages="clr-namespace:Flow.Launcher.ViewModel.WelcomePages"
xmlns:launcher="clr-namespace:Flow.Launcher"
x:DataType="welcomePages:WelcomePage2ViewModel"
mc:Ignorable="d">
<Page.Resources>
<converters:BorderClipConverter x:Key="BorderClipConverter" />
<Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}">
<Setter Property="Opacity" Value="0" />
<Style.Triggers>
<!-- Fades-in the image when it becomes visible -->
<Trigger Property="IsVisible" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard x:Name="FadeIn">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:2" />
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<!-- <Page.Resources> -->
<!-- <converters:BorderClipConverter x:Key="BorderClipConverter" /> -->
<!-- <Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}"> -->
<!-- <Setter Property="Opacity" Value="0" /> -->
<!-- <Style.Triggers> -->
<!-- ~1~ Fades-in the image when it becomes visible @1@ -->
<!-- <Trigger Property="IsVisible" Value="True"> -->
<!-- <Trigger.EnterActions> -->
<!-- <BeginStoryboard> -->
<!-- <BeginStoryboard.Storyboard> -->
<!-- <Storyboard x:Name="FadeIn"> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="Opacity" -->
<!-- To="1" -->
<!-- Duration="0:0:2" /> -->
<!-- </Storyboard> -->
<!-- </BeginStoryboard.Storyboard> -->
<!-- </BeginStoryboard> -->
<!-- </Trigger.EnterActions> -->
<!-- </Trigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- </Page.Resources> -->
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
@ -52,15 +50,14 @@
<StackPanel
Grid.Row="1"
Margin="0"
Background="{Binding PreviewBackground}">
Margin="0">
<StackPanel
Margin="0,80,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Width="450" Style="{DynamicResource WindowBorderStyle}">
<Border Style="{DynamicResource WindowRadius}">
<Border Width="450">
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="54" />
@ -70,16 +67,14 @@
<Border Grid.Row="0">
<TextBox
IsReadOnly="True"
Style="{DynamicResource QueryBoxStyle}"
Text="{DynamicResource hiThere}" />
</Border>
<Canvas Style="{DynamicResource SearchIconPosition}">
<Canvas>
<Path
Margin="0"
Data="{DynamicResource SearchIconImg}"
Stretch="Fill"
Style="{DynamicResource SearchIconStyle}" />
Stretch="Fill"/>
</Canvas>
</Grid>
</Border>
@ -109,16 +104,15 @@
FontSize="14"
FontWeight="SemiBold"
Text="{DynamicResource flowlauncherHotkey}" />
<flowlauncher:HotkeyControl
x:Name="HotkeyControl"
<launcher:HotkeyControl
x:Name="hotkeyControl"
Width="300"
Height="35"
Margin="-206,10,0,0"
GotFocus="HotkeyControl_OnGotFocus"
LostFocus="HotkeyControl_OnLostFocus"/>
LostFocus="HotkeyControl_OnLostFocus" />
</StackPanel>
</StackPanel>
</Grid>
</ScrollViewer>
</ui:Page>
</UserControl>

View file

@ -0,0 +1,44 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
using PropertyChanged;
namespace Flow.Launcher.WelcomePages
{
[DoNotNotify]
public partial class WelcomePage2 : UserControl
{
private Settings Settings { get; set; }
private Brush tbMsgForegroundColorOriginal;
private string tbMsgTextOriginal;
public WelcomePage2()
{
InitializeComponent();
hotkeyControl.SetHotkeyAsync(Settings.Hotkey, false);
}
private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args)
{
HotKeyMapper.RemoveHotkey(Settings.Hotkey);
}
private void HotkeyControl_OnLostFocus(object sender, RoutedEventArgs args)
{
if (hotkeyControl.CurrentHotkeyAvailable)
{
HotKeyMapper.SetHotkey(hotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
Settings.Hotkey = hotkeyControl.CurrentHotkey.ToString();
}
else
{
HotKeyMapper.SetHotkey(new HotkeyModel(Settings.Hotkey), HotKeyMapper.OnToggleHotkey);
}
}
}
}

View file

@ -1,32 +1,31 @@
<ui:Page
x:Class="Flow.Launcher.Resources.Pages.WelcomePage3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<UserControl
x:Class="Flow.Launcher.WelcomePages.WelcomePage3"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="WelcomePage3"
xmlns:welcomePages="clr-namespace:Flow.Launcher.ViewModel.WelcomePages"
x:DataType="welcomePages:WelcomePage1ViewModel"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="KbdLine" TargetType="Border">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Margin" Value="0,3,0,3" />
<Setter Property="Background" Value="{DynamicResource Color01B}" />
</Style>
<Style x:Key="Kbd" TargetType="Border">
<Setter Property="CornerRadius" Value="4" />
<Setter Property="Padding" Value="12,4,12,4" />
<Setter Property="Background" Value="{DynamicResource Color00B}" />
<Setter Property="BorderBrush" Value="{DynamicResource Color18B}" />
<Setter Property="BorderThickness" Value="1,1,1,2" />
</Style>
<Style x:Key="KbdText" TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
</Page.Resources>
<!-- <Page.Resources> -->
<!-- <Style x:Key="KbdLine" TargetType="Border"> -->
<!-- <Setter Property="CornerRadius" Value="8" /> -->
<!-- <Setter Property="Margin" Value="0,3,0,3" /> -->
<!-- <Setter Property="Background" Value="{DynamicResource Color01B}" /> -->
<!-- </Style> -->
<!-- <Style x:Key="Kbd" TargetType="Border"> -->
<!-- <Setter Property="CornerRadius" Value="4" /> -->
<!-- <Setter Property="Padding" Value="12,4,12,4" /> -->
<!-- <Setter Property="Background" Value="{DynamicResource Color00B}" /> -->
<!-- <Setter Property="BorderBrush" Value="{DynamicResource Color18B}" /> -->
<!-- <Setter Property="BorderThickness" Value="1,1,1,2" /> -->
<!-- </Style> -->
<!-- <Style x:Key="KbdText" TargetType="TextBlock"> -->
<!-- <Setter Property="TextAlignment" Value="Center" /> -->
<!-- <Setter Property="FontSize" Value="12" /> -->
<!-- <Setter Property="Foreground" Value="{DynamicResource Color05B}" /> -->
<!-- </Style> -->
<!-- </Page.Resources> -->
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
@ -49,8 +48,7 @@
Width="300"
Height="100"
Margin="0,0,0,0"
Source="../../images/page_img02.png"
Style="{DynamicResource StyleImageFadeIn}" />
Source="../../images/page_img02.png" />
</StackPanel>
</Border>
@ -66,19 +64,19 @@
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page3_Title}" />
</StackPanel>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">←</TextBlock>
<Border Margin="0,0,5,0">
<TextBlock>←</TextBlock>
</Border>
<TextBlock VerticalAlignment="Center">,</TextBlock>
<Border Margin="5,0,0,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">→</TextBlock>
<Border Margin="5,0,0,0">
<TextBlock>→</TextBlock>
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -90,19 +88,19 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">↑</TextBlock>
<Border Margin="0,0,5,0">
<TextBlock>↑</TextBlock>
</Border>
<TextBlock VerticalAlignment="Center">,</TextBlock>
<Border Margin="5,0,0,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">↓</TextBlock>
<Border Margin="5,0,0,0">
<TextBlock>↓</TextBlock>
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -114,15 +112,15 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">Enter</TextBlock>
<Border Margin="0,0,5,0">
<TextBlock>Enter</TextBlock>
</Border>
</StackPanel>
@ -135,15 +133,15 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ESC" />
<Border Margin="0,0,5,0">
<TextBlock Text="ESC" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -155,15 +153,15 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Tab" />
<Border Margin="0,0,5,0">
<TextBlock Text="Tab" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -175,19 +173,19 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Shift" />
<Border Margin="0,0,5,0">
<TextBlock Text="Shift" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ENTER" />
<Border Margin="5,0,5,0">
<TextBlock Text="ENTER" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -199,19 +197,19 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
<Border Margin="0,0,5,0">
<TextBlock Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ENTER" />
<Border Margin="5,0,5,0">
<TextBlock Text="ENTER" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -223,23 +221,23 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
<Border Margin="0,0,5,0">
<TextBlock Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Shift" />
<Border Margin="5,0,5,0">
<TextBlock Text="Shift" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ENTER" />
<Border Margin="5,0,5,0">
<TextBlock Text="ENTER" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -251,19 +249,19 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
<Border Margin="0,0,5,0">
<TextBlock Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="H" />
<Border Margin="5,0,5,0">
<TextBlock Text="H" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -275,19 +273,19 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
<Border Margin="0,0,5,0">
<TextBlock Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="I" />
<Border Margin="5,0,5,0">
<TextBlock Text="I" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -299,15 +297,15 @@
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<Border>
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="F5" />
<Border Margin="0,0,5,0">
<TextBlock Text="F5" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
@ -324,4 +322,4 @@
</Grid>
</ScrollViewer>
</ui:Page>
</UserControl>

View file

@ -0,0 +1,19 @@
using System;
using System.Windows.Navigation;
using Avalonia.Controls;
using Flow.Launcher.Infrastructure.UserSettings;
using PropertyChanged;
namespace Flow.Launcher.WelcomePages
{
[DoNotNotify]
public partial class WelcomePage3 : UserControl
{
public WelcomePage3()
{
InitializeComponent();
}
public Settings Settings { get; set; }
}
}

View file

@ -0,0 +1,139 @@
<UserControl
x:Class="Flow.Launcher.WelcomePages.WelcomePage4"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:welcomePages="clr-namespace:Flow.Launcher.ViewModel.WelcomePages"
x:DataType="welcomePages:WelcomePage4ViewModel"
mc:Ignorable="d">
<!-- <Page.Resources> -->
<!-- <Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}"> -->
<!-- <Style.Triggers> -->
<!-- <Trigger Property="IsVisible" Value="True"> -->
<!-- <Trigger.EnterActions> -->
<!-- <BeginStoryboard> -->
<!-- <BeginStoryboard.Storyboard> -->
<!-- <Storyboard x:Name="Move"> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="(Canvas.Left)" -->
<!-- From="0" -->
<!-- To="100" -->
<!-- Duration="0:0:20"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- </Storyboard> -->
<!-- </BeginStoryboard.Storyboard> -->
<!-- </BeginStoryboard> -->
<!-- </Trigger.EnterActions> -->
<!-- </Trigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- <Style x:Key="RecommendQuery" TargetType="Border"> -->
<!-- <Setter Property="CornerRadius" Value="8" /> -->
<!-- <Setter Property="Padding" Value="20,7,12,7" /> -->
<!-- <Setter Property="Margin" Value="4,4,4,4" /> -->
<!-- <Setter Property="Background" Value="{DynamicResource Color01B}" /> -->
<!-- </Style> -->
<!-- <Style x:Key="QueryText" TargetType="TextBlock"> -->
<!-- <Setter Property="TextAlignment" Value="Left" /> -->
<!-- <Setter Property="TextAlignment" Value="Left" /> -->
<!-- <Setter Property="FontSize" Value="14" /> -->
<!-- <Setter Property="Foreground" Value="{DynamicResource Color05B}" /> -->
<!-- </Style> -->
<!-- <Style x:Key="ResultText" TargetType="TextBlock"> -->
<!-- <Setter Property="TextAlignment" Value="Left" /> -->
<!-- <Setter Property="TextAlignment" Value="Left" /> -->
<!-- <Setter Property="FontSize" Value="13" /> -->
<!-- <Setter Property="Margin" Value="0,4,0,0" /> -->
<!-- <Setter Property="Foreground" Value="{DynamicResource Color04B}" /> -->
<!-- </Style> -->
<!-- </Page.Resources> -->
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#e8457c" />
<GradientStop Offset="1.0" Color="#bc1948" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Canvas
Width="600"
Height="301"
ClipToBounds="True">
<Image
Name="Logo"
Canvas.Left="0"
Width="450"
Height="280"
Margin="0,0,0,0"
Source="../../images/page_img01.png" />
</Canvas>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Margin="24,20,24,20">
<StackPanel>
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page4_Title}" />
<TextBlock
Margin="0,10,0,10"
FontSize="14"
Text="{DynamicResource Welcome_Page4_Text01}"
TextWrapping="WrapWithOverflow" />
<UniformGrid
Margin="0,14,0,0"
Columns="2"
Rows="2">
<Border>
<StackPanel>
<TextBlock
Text="{DynamicResource RecommendWeather}" />
<TextBlock
Text="{DynamicResource RecommendWeatherDesc}" />
</StackPanel>
</Border>
<Border>
<StackPanel>
<TextBlock Text="{DynamicResource RecommendShell}" />
<TextBlock
Text="{DynamicResource RecommendShellDesc}" />
</StackPanel>
</Border>
<Border>
<StackPanel>
<TextBlock
Text="{DynamicResource RecommendBluetooth}" />
<TextBlock
Text="{DynamicResource RecommendBluetoothDesc}" />
</StackPanel>
</Border>
<Border>
<StackPanel>
<TextBlock
Text="{DynamicResource RecommendAcronyms}" />
<TextBlock
Text="{DynamicResource RecommendAcronymsDesc}" />
</StackPanel>
</Border>
</UniformGrid>
</StackPanel>
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View file

@ -0,0 +1,20 @@
using System;
using System.Windows.Navigation;
using Avalonia.Controls;
using Flow.Launcher.Infrastructure.UserSettings;
using PropertyChanged;
namespace Flow.Launcher.WelcomePages
{
[DoNotNotify]
public partial class WelcomePage4 : UserControl
{
public WelcomePage4()
{
InitializeComponent();
}
public Settings Settings { get; set; }
}
}

View file

@ -0,0 +1,106 @@
<UserControl
x:Class="Flow.Launcher.WelcomePages.WelcomePage5"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:welcomePages="clr-namespace:Flow.Launcher.ViewModel.WelcomePages"
x:DataType="welcomePages:WelcomePage5ViewModel"
mc:Ignorable="d">
<!-- <Page.Resources> -->
<!-- <Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}"> -->
<!-- <Setter Property="Opacity" Value="0" /> -->
<!-- <Style.Triggers> -->
<!-- ~1~ Fades-in the image when it becomes visible @1@ -->
<!-- <Trigger Property="IsVisible" Value="True"> -->
<!-- <Trigger.EnterActions> -->
<!-- <BeginStoryboard> -->
<!-- <BeginStoryboard.Storyboard> -->
<!-- <Storyboard x:Name="FadeIn"> -->
<!-- -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="(Canvas.Top)" -->
<!-- From="110" -->
<!-- To="75" -->
<!-- Duration="0:0:1"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- <DoubleAnimation -->
<!-- Storyboard.TargetProperty="Opacity" -->
<!-- From="0" -->
<!-- To="1" -->
<!-- Duration="0:0:1"> -->
<!-- <DoubleAnimation.EasingFunction> -->
<!-- <QuadraticEase EasingMode="EaseOut" /> -->
<!-- </DoubleAnimation.EasingFunction> -->
<!-- </DoubleAnimation> -->
<!-- </Storyboard> -->
<!-- </BeginStoryboard.Storyboard> -->
<!-- </BeginStoryboard> -->
<!-- </Trigger.EnterActions> -->
<!-- </Trigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- </Page.Resources> -->
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="250" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#7b83eb" />
<GradientStop Offset="1.0" Color="#555dc0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Canvas Width="550" Height="250">
<Image
Name="Logo"
Canvas.Left="225"
Width="100"
Height="100"
Source="../../images/app.png" />
</Canvas>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Margin="24,20,24,20">
<StackPanel>
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page5_Title}" />
<TextBlock
Margin="0,10,0,0"
FontSize="14"
Text="{DynamicResource Welcome_Page5_Text01}"
TextWrapping="WrapWithOverflow" />
<StackPanel Margin="0,30,0,0" Orientation="Horizontal">
<CheckBox
IsCheckedChanged="OnAutoStartupChecked"
Content="{DynamicResource startFlowLauncherOnSystemStartup}"
IsChecked="{Binding Settings.StartFlowLauncherOnSystemStartup}"
Unchecked="OnAutoStartupUncheck" />
</StackPanel>
<StackPanel Margin="0,0,0,0" Orientation="Horizontal">
<CheckBox
Checked="OnHideOnStartupChecked"
Content="{DynamicResource hideOnStartup}"
IsChecked="{Binding Settings.HideOnStartup}"
Unchecked="OnHideOnStartupUnchecked" />
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View file

@ -1,24 +1,21 @@
using System;
using System.Windows;
using System.Windows.Navigation;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Microsoft.Win32;
using Flow.Launcher.Infrastructure;
using PropertyChanged;
namespace Flow.Launcher.Resources.Pages
namespace Flow.Launcher.WelcomePages
{
public partial class WelcomePage5
[DoNotNotify]
public partial class WelcomePage5 : UserControl
{
private const string StartupPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
public Settings Settings { get; set; }
public bool HideOnStartup { get; set; }
protected override void OnNavigatedTo(NavigationEventArgs e)
public WelcomePage5()
{
if (e.ExtraData is Settings settings)
Settings = settings;
else
throw new ArgumentException("Unexpected Navigation Parameter for Settings");
InitializeComponent();
}
@ -26,6 +23,7 @@ namespace Flow.Launcher.Resources.Pages
{
SetStartup();
}
private void OnAutoStartupUncheck(object sender, RoutedEventArgs e)
{
RemoveStartup();
@ -37,6 +35,7 @@ namespace Flow.Launcher.Resources.Pages
key?.DeleteValue(Constant.FlowLauncher, false);
Settings.StartFlowLauncherOnSystemStartup = false;
}
private void SetStartup()
{
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
@ -48,16 +47,10 @@ namespace Flow.Launcher.Resources.Pages
{
Settings.HideOnStartup = true;
}
private void OnHideOnStartupUnchecked(object sender, RoutedEventArgs e)
{
Settings.HideOnStartup = false;
}
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
{
var window = Window.GetWindow(this);
window.Close();
}
}
}

View file

@ -0,0 +1,125 @@
<Window
x:Class="Flow.Launcher.WelcomeWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Flow.Launcher.ViewModel"
Name="FlowWelcomeWindow"
Title="Welcome"
Width="550"
Height="650"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d"
x:DataType="vm:WelcomeWindowViewModel">
<Window.DataTemplates>
<local:ViewLocator />
</Window.DataTemplates>
<!--#region TitleBar-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto,Auto,Auto">
<Image
Grid.Column="0"
Width="16"
Height="16"
Margin="10,4,4,4" />
<TextBlock
Grid.Column="1"
Margin="4,0,0,0"
VerticalAlignment="Center"
FontSize="12"
Text="111" />
<Button
Grid.Column="4">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<!-- <Path.Style> -->
<!-- <Style TargetType="Path"> -->
<!-- <Style.Triggers> -->
<!-- <DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False"> -->
<!-- <Setter Property="Opacity" Value="0.5" /> -->
<!-- </DataTrigger> -->
<!-- </Style.Triggers> -->
<!-- </Style> -->
<!-- </Path.Style> -->
</Path>
</Button>
</Grid>
</StackPanel>
<!--#endregion-->
<StackPanel Margin="0">
<TransitioningContentControl
Content="{Binding CurrentPage}">
</TransitioningContentControl>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
BorderThickness="0,1,0,0">
<Grid ColumnDefinitions="130,*,130">
<StackPanel
Grid.Column="0"
Grid.ColumnSpan="3"
VerticalAlignment="Center">
<TextBlock
Name="PageNavigation"
Margin="0,2,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
Text="{Binding PageDisplay, Mode=OneWay}"
TextAlignment="Center" />
</StackPanel>
<Button
x:Name="SkipButton"
Grid.Column="0"
Width="100"
Height="40"
Margin="20,5,0,5"
Content="Skip"
DockPanel.Dock="Right"
FontSize="14" />
<DockPanel
Grid.Column="2"
Margin="0,0,20,0"
VerticalAlignment="Stretch">
<Button
x:Name="NextButton"
Width="40"
Height="40"
Command="{Binding NavigateNextCommand}"
Margin="8,5,0,5"
Content="&#xe76c;"
DockPanel.Dock="Right"
FontFamily="{StaticResource UIFont}"
FontSize="18" />
<Button
x:Name="BackButton"
Width="40"
Height="40"
Command="{Binding NavigatePreviousCommand}"
Content="&#xe76b;"
DockPanel.Dock="Right"
FontFamily="{StaticResource UIFont}"
FontSize="18" />
<StackPanel />
</DockPanel>
</Grid>
</Border>
</Grid>
</Window>

View file

@ -0,0 +1,34 @@
using System;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Flow.Launcher.Infrastructure.UserSettings;
using ModernWpf.Media.Animation;
using PropertyChanged;
namespace Flow.Launcher
{
[DoNotNotify]
public partial class WelcomeWindow : Window
{
private readonly Settings settings;
public WelcomeWindow(Settings settings)
{
DataContext = new ViewModel.WelcomeWindowViewModel(settings);
InitializeComponent();
BackButton.IsEnabled = false;
this.settings = settings;
}
private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo()
{
Effect = SlideNavigationTransitionEffect.FromRight
};
private NavigationTransitionInfo _backTransitionInfo = new SlideNavigationTransitionInfo()
{
Effect = SlideNavigationTransitionEffect.FromLeft
};
}
}

View file

@ -1,157 +0,0 @@
<Window
x:Class="Flow.Launcher.WelcomeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Name="FlowWelcomeWindow"
Title="{DynamicResource Welcome_Page1_Title}"
Width="550"
Height="650"
Activated="OnActivated"
Background="{DynamicResource Color00B}"
Foreground="{DynamicResource PopupTextColor}"
MouseDown="window_MouseDown"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<!--#region TitleBar-->
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="16"
Height="16"
Margin="10,4,4,4"
RenderOptions.BitmapScalingMode="HighQuality"
Source="/Images/app.png" />
<TextBlock
Grid.Column="1"
Margin="4,0,0,0"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource Color05B}"
Text="{DynamicResource Welcome_Page1_Title}" />
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<!--#endregion-->
<StackPanel Margin="0">
<ui:Frame
x:Name="ContentFrame"
HorizontalAlignment="Stretch"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ui:Frame.ContentTransitions>
<ui:TransitionCollection>
<ui:NavigationThemeTransition />
</ui:TransitionCollection>
</ui:Frame.ContentTransitions>
</ui:Frame>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Background="{DynamicResource Color00B}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130" />
<ColumnDefinition />
<ColumnDefinition Width="130" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
Grid.ColumnSpan="3"
VerticalAlignment="Center">
<TextBlock
Name="PageNavigation"
Margin="0,2,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
Text="{Binding PageDisplay, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
TextAlignment="Center" />
</StackPanel>
<Button
x:Name="SkipButton"
Grid.Column="0"
Width="100"
Height="40"
Margin="20,5,0,5"
Click="BtnCancel_OnClick"
Content="{DynamicResource Skip}"
DockPanel.Dock="Right"
FontSize="14" />
<DockPanel
Grid.Column="2"
Margin="0,0,20,0"
VerticalAlignment="Stretch">
<Button
x:Name="NextButton"
Width="40"
Height="40"
Margin="8,5,0,5"
Click="ForwardButton_Click"
Content="&#xe76c;"
DockPanel.Dock="Right"
FontFamily="/Resources/#Segoe Fluent Icons"
FontSize="18" />
<Button
x:Name="BackButton"
Width="40"
Height="40"
Click="BackwardButton_Click"
Content="&#xe76b;"
DockPanel.Dock="Right"
FontFamily="/Resources/#Segoe Fluent Icons"
FontSize="18" />
<StackPanel />
</DockPanel>
</Grid>
</Border>
</Grid>
</Window>

View file

@ -1,110 +0,0 @@
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Resources.Pages;
using ModernWpf.Media.Animation;
namespace Flow.Launcher
{
public partial class WelcomeWindow : Window
{
private readonly Settings settings;
public WelcomeWindow(Settings settings)
{
InitializeComponent();
BackButton.IsEnabled = false;
this.settings = settings;
ContentFrame.Navigate(PageTypeSelector(1), settings);
}
private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo()
{
Effect = SlideNavigationTransitionEffect.FromRight
};
private NavigationTransitionInfo _backTransitionInfo = new SlideNavigationTransitionInfo()
{
Effect = SlideNavigationTransitionEffect.FromLeft
};
private int pageNum = 1;
private int MaxPage = 5;
public string PageDisplay => $"{pageNum}/5";
private void UpdateView()
{
PageNavigation.Text = PageDisplay;
if (pageNum == 1)
{
BackButton.IsEnabled = false;
NextButton.IsEnabled = true;
}
else if (pageNum == MaxPage)
{
BackButton.IsEnabled = true;
NextButton.IsEnabled = false;
}
else
{
BackButton.IsEnabled = true;
NextButton.IsEnabled = true;
}
}
private void ForwardButton_Click(object sender, RoutedEventArgs e)
{
pageNum++;
UpdateView();
ContentFrame.Navigate(PageTypeSelector(pageNum), settings, _transitionInfo);
}
private void BackwardButton_Click(object sender, RoutedEventArgs e)
{
if (pageNum > 1)
{
pageNum--;
UpdateView();
ContentFrame.Navigate(PageTypeSelector(pageNum), settings, _backTransitionInfo);
}
else
{
BackButton.IsEnabled = false;
}
}
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
{
Close();
}
private static Type PageTypeSelector(int pageNumber)
{
return pageNumber switch
{
1 => typeof(WelcomePage1),
2 => typeof(WelcomePage2),
3 => typeof(WelcomePage3),
4 => typeof(WelcomePage4),
5 => typeof(WelcomePage5),
_ => throw new ArgumentOutOfRangeException(nameof(pageNumber), pageNumber, "Unexpected Page Number")
};
}
private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */
{
if (Keyboard.FocusedElement is not TextBox textBox)
{
return;
}
var tRequest = new TraversalRequest(FocusNavigationDirection.Next);
textBox.MoveFocus(tRequest);
}
private void OnActivated(object sender, EventArgs e)
{
Keyboard.ClearFocus();
}
}
}