diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/ClipboardCanvas.Package (Package).wapproj b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/ClipboardCanvas.Package (Package).wapproj deleted file mode 100644 index 429d9606..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/ClipboardCanvas.Package (Package).wapproj +++ /dev/null @@ -1,143 +0,0 @@ - - - - 15.0 - - - - Debug - x86 - - - Release - x86 - - - Debug - x64 - - - Release - x64 - - - Debug - arm64 - - - Release - arm64 - - - - $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ - ClipboardCanvas.Package\ - - - - eb0170ce-7213-48c2-8340-aeab2a0d40f8 - 10.0.22000.0 - 10.0.17763.0 - net6.0-windows$(TargetPlatformVersion);$(AssetTargetFallback) - en-US - false - ..\..\ClipboardCanvas\ClipboardCanvas.csproj - False - False - False - en-US - Scale|DXFeatureLevel - Language=en-US;de-DE;pt-PT;ro-RO;ru-RU;zh-CN - x86|x64|arm64 - True - 0 - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - build - - - build - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - \ No newline at end of file diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-100.png deleted file mode 100644 index ef35cda6..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-125.png deleted file mode 100644 index 6c6e885d..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-150.png deleted file mode 100644 index ba2d145a..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-200.png deleted file mode 100644 index b86336b0..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-400.png deleted file mode 100644 index 1679f9cc..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/LargeTile.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-100.png deleted file mode 100644 index 2e2e9c2f..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-125.png deleted file mode 100644 index 19c61dda..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-150.png deleted file mode 100644 index dfb2782f..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-200.png deleted file mode 100644 index d62de8f5..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-400.png deleted file mode 100644 index 92bc4720..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SmallTile.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-100.png deleted file mode 100644 index b2658bb0..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-125.png deleted file mode 100644 index 574a5b52..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-150.png deleted file mode 100644 index 1c842a18..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-200.png deleted file mode 100644 index ea15e888..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-400.png deleted file mode 100644 index 4d74d48f..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/SplashScreen.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-100.png deleted file mode 100644 index becd9a34..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-125.png deleted file mode 100644 index 2fdbe33e..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-150.png deleted file mode 100644 index b5ef2a1d..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-200.png deleted file mode 100644 index 6c6ecb2a..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-400.png deleted file mode 100644 index f88a3650..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square150x150Logo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png deleted file mode 100644 index 5ba88c56..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-16.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png deleted file mode 100644 index 0453592a..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-24.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png deleted file mode 100644 index 0c6ac8ce..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-256.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png deleted file mode 100644 index fa39f134..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-32.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png deleted file mode 100644 index 27765d40..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-lightunplated_targetsize-48.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-16.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-16.png deleted file mode 100644 index 5ba88c56..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-16.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-24.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-24.png deleted file mode 100644 index 0453592a..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-24.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-256.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-256.png deleted file mode 100644 index 0c6ac8ce..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-256.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-32.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-32.png deleted file mode 100644 index fa39f134..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-32.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-48.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-48.png deleted file mode 100644 index 27765d40..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.altform-unplated_targetsize-48.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-100.png deleted file mode 100644 index ee254e63..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-125.png deleted file mode 100644 index 8d0afa2f..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-150.png deleted file mode 100644 index 94b7b62d..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-200.png deleted file mode 100644 index 0b183523..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-400.png deleted file mode 100644 index 7a0d2e6d..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-16.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-16.png deleted file mode 100644 index 5ba88c56..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-16.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-24.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-24.png deleted file mode 100644 index 0453592a..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-24.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-256.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-256.png deleted file mode 100644 index 0c6ac8ce..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-256.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-32.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-32.png deleted file mode 100644 index fa39f134..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-32.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-48.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-48.png deleted file mode 100644 index 27765d40..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Square44x44Logo.targetsize-48.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-100.png deleted file mode 100644 index 27f2c879..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-125.png deleted file mode 100644 index b383adc0..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-150.png deleted file mode 100644 index 4ce2b519..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-200.png deleted file mode 100644 index 40e00991..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-400.png deleted file mode 100644 index 74ef4dc0..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/StoreLogo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-100.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-100.png deleted file mode 100644 index 7c89d166..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-125.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-125.png deleted file mode 100644 index 93dbb92b..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-150.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-150.png deleted file mode 100644 index d61f24eb..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-200.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-200.png deleted file mode 100644 index b2658bb0..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-400.png b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-400.png deleted file mode 100644 index ea15e888..00000000 Binary files a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Images/Wide310x150Logo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Package.appxmanifest b/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Package.appxmanifest deleted file mode 100644 index e9d12735..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package (Package)/Package.appxmanifest +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - Clipboard Canvas - d2dyno - Images\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package/App.xaml b/ClipboardCanvas.Package/ClipboardCanvas.Package/App.xaml deleted file mode 100644 index c2d91310..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package/App.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package/App.xaml.cs b/ClipboardCanvas.Package/ClipboardCanvas.Package/App.xaml.cs deleted file mode 100644 index 96b00e4a..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package/App.xaml.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; -using Microsoft.UI.Xaml.Shapes; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.ApplicationModel; -using Windows.ApplicationModel.Activation; -using Windows.Foundation; -using Windows.Foundation.Collections; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace ClipboardCanvas.Package -{ - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - public partial class App : Application - { - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// - public App() - { - this.InitializeComponent(); - } - - /// - /// Invoked when the application is launched normally by the end user. Other entry points - /// will be used such as when the application is launched to open a specific file. - /// - /// Details about the launch request and process. - protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) - { - m_window = new MainWindow(); - m_window.Activate(); - } - - private Window m_window; - } -} diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package/ClipboardCanvas.Package.csproj b/ClipboardCanvas.Package/ClipboardCanvas.Package/ClipboardCanvas.Package.csproj deleted file mode 100644 index 09e35c27..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package/ClipboardCanvas.Package.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - WinExe - net6.0-windows10.0.19041.0 - 10.0.17763.0 - ClipboardCanvas.Package - app.manifest - x86;x64;arm64 - win10-x86;win10-x64;win10-arm64 - true - - - - - - - - diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package/MainWindow.xaml b/ClipboardCanvas.Package/ClipboardCanvas.Package/MainWindow.xaml deleted file mode 100644 index 3308195d..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package/MainWindow.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package/app.manifest b/ClipboardCanvas.Package/ClipboardCanvas.Package/app.manifest deleted file mode 100644 index a1c3bc17..00000000 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package/app.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - true/PM - PerMonitorV2, PerMonitor - - - diff --git a/ClipboardCanvas.sln b/ClipboardCanvas.sln index 9726e00c..b0675225 100644 --- a/ClipboardCanvas.sln +++ b/ClipboardCanvas.sln @@ -1,63 +1,119 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.0.31912.275 +VisualStudioVersion = 17.8.34309.116 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClipboardCanvas", "ClipboardCanvas\ClipboardCanvas.csproj", "{719C97A4-8A77-4B8E-97DF-3B01BA32C16E}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{18CB587D-DFE1-4C01-92E5-7FDBE43BBEFF}" EndProject -Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "ClipboardCanvas.Package (Package)", "ClipboardCanvas.Package\ClipboardCanvas.Package (Package)\ClipboardCanvas.Package (Package).wapproj", "{EB0170CE-7213-48C2-8340-AEAB2A0D40F8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{595861A4-F6B2-4231-816B-21EB0BEE71CB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{E216C759-D5F9-4DC0-B48B-A5D68394A5F4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClipboardCanvas.WinUI", "src\Platforms\ClipboardCanvas.WinUI\ClipboardCanvas.WinUI.csproj", "{31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClipboardCanvas.Sdk", "src\ClipboardCanvas.Sdk\ClipboardCanvas.Sdk.csproj", "{0C11D681-11A3-4074-AE57-57734A138473}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClipboardCanvas.UI", "src\Platforms\ClipboardCanvas.UI\ClipboardCanvas.UI.csproj", "{FECB96DE-B383-4A58-92B7-6B35DDC64A66}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClipboardCanvas.Shared", "src\ClipboardCanvas.Shared\ClipboardCanvas.Shared.csproj", "{8278EA42-4458-4144-9815-D2C7CE5D8183}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|arm64 = Debug|arm64 + Debug|Any CPU = Debug|Any CPU + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|arm64 = Release|arm64 + Release|Any CPU = Release|Any CPU + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|arm64.ActiveCfg = Debug|arm64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|arm64.Build.0 = Debug|arm64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|arm64.Deploy.0 = Debug|arm64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|x64.ActiveCfg = Debug|x64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|x64.Build.0 = Debug|x64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|x64.Deploy.0 = Debug|x64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|x86.ActiveCfg = Debug|x86 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|x86.Build.0 = Debug|x86 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Debug|x86.Deploy.0 = Debug|x86 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|arm64.ActiveCfg = Release|arm64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|arm64.Build.0 = Release|arm64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|arm64.Deploy.0 = Release|arm64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|x64.ActiveCfg = Release|x64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|x64.Build.0 = Release|x64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|x64.Deploy.0 = Release|x64 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|x86.ActiveCfg = Release|x86 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|x86.Build.0 = Release|x86 - {719C97A4-8A77-4B8E-97DF-3B01BA32C16E}.Release|x86.Deploy.0 = Release|x86 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|arm64.ActiveCfg = Debug|arm64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|arm64.Build.0 = Debug|arm64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|arm64.Deploy.0 = Debug|arm64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|x64.ActiveCfg = Debug|x64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|x64.Build.0 = Debug|x64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|x64.Deploy.0 = Debug|x64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|x86.ActiveCfg = Debug|x86 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|x86.Build.0 = Debug|x86 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Debug|x86.Deploy.0 = Debug|x86 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|arm64.ActiveCfg = Release|arm64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|arm64.Build.0 = Release|arm64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|arm64.Deploy.0 = Release|arm64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|x64.ActiveCfg = Release|x64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|x64.Build.0 = Release|x64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|x64.Deploy.0 = Release|x64 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|x86.ActiveCfg = Release|x86 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|x86.Build.0 = Release|x86 - {EB0170CE-7213-48C2-8340-AEAB2A0D40F8}.Release|x86.Deploy.0 = Release|x86 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|Any CPU.ActiveCfg = Debug|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|Any CPU.Build.0 = Debug|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|Any CPU.Deploy.0 = Debug|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|ARM64.Build.0 = Debug|ARM64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|x64.ActiveCfg = Debug|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|x64.Build.0 = Debug|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|x64.Deploy.0 = Debug|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|x86.ActiveCfg = Debug|x86 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|x86.Build.0 = Debug|x86 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Debug|x86.Deploy.0 = Debug|x86 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|Any CPU.ActiveCfg = Release|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|Any CPU.Build.0 = Release|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|Any CPU.Deploy.0 = Release|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|ARM64.ActiveCfg = Release|ARM64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|ARM64.Build.0 = Release|ARM64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|ARM64.Deploy.0 = Release|ARM64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|x64.ActiveCfg = Release|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|x64.Build.0 = Release|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|x64.Deploy.0 = Release|x64 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|x86.ActiveCfg = Release|x86 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|x86.Build.0 = Release|x86 + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76}.Release|x86.Deploy.0 = Release|x86 + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|ARM64.Build.0 = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|x64.Build.0 = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Debug|x86.Build.0 = Debug|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|Any CPU.Build.0 = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|ARM64.ActiveCfg = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|ARM64.Build.0 = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|x64.ActiveCfg = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|x64.Build.0 = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|x86.ActiveCfg = Release|Any CPU + {0C11D681-11A3-4074-AE57-57734A138473}.Release|x86.Build.0 = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|ARM64.Build.0 = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|x64.ActiveCfg = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|x64.Build.0 = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|x86.ActiveCfg = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Debug|x86.Build.0 = Debug|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|Any CPU.Build.0 = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|ARM64.ActiveCfg = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|ARM64.Build.0 = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|x64.ActiveCfg = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|x64.Build.0 = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|x86.ActiveCfg = Release|Any CPU + {FECB96DE-B383-4A58-92B7-6B35DDC64A66}.Release|x86.Build.0 = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|ARM64.Build.0 = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|x64.ActiveCfg = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|x64.Build.0 = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|x86.ActiveCfg = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Debug|x86.Build.0 = Debug|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|Any CPU.Build.0 = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|ARM64.ActiveCfg = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|ARM64.Build.0 = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|x64.ActiveCfg = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|x64.Build.0 = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|x86.ActiveCfg = Release|Any CPU + {8278EA42-4458-4144-9815-D2C7CE5D8183}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {31DB0DD6-A5F4-4620-8AE9-5DAD218E9F76} = {E216C759-D5F9-4DC0-B48B-A5D68394A5F4} + {595861A4-F6B2-4231-816B-21EB0BEE71CB} = {18CB587D-DFE1-4C01-92E5-7FDBE43BBEFF} + {E216C759-D5F9-4DC0-B48B-A5D68394A5F4} = {18CB587D-DFE1-4C01-92E5-7FDBE43BBEFF} + {0C11D681-11A3-4074-AE57-57734A138473} = {595861A4-F6B2-4231-816B-21EB0BEE71CB} + {FECB96DE-B383-4A58-92B7-6B35DDC64A66} = {E216C759-D5F9-4DC0-B48B-A5D68394A5F4} + {8278EA42-4458-4144-9815-D2C7CE5D8183} = {595861A4-F6B2-4231-816B-21EB0BEE71CB} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E0B2E803-C8A6-4838-88C0-4C9F87A0A480} + SolutionGuid = {A79E5126-51C1-4BE8-8CFD-1CD4482CF341} EndGlobalSection EndGlobal diff --git a/ClipboardCanvas/App.xaml b/ClipboardCanvas/App.xaml deleted file mode 100644 index d2009231..00000000 --- a/ClipboardCanvas/App.xaml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - 0 - 641 - 1008 - - - - - - 4 - - - - - - - diff --git a/ClipboardCanvas/App.xaml.cs b/ClipboardCanvas/App.xaml.cs deleted file mode 100644 index 67afd05e..00000000 --- a/ClipboardCanvas/App.xaml.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using Microsoft.UI.Xaml; -using System.Diagnostics; -using System.Threading.Tasks; -using Windows.UI.Notifications; -using System.Runtime.ExceptionServices; -using Microsoft.Extensions.DependencyInjection; -using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.WinUI.Notifications; -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Services; -using ClipboardCanvas.Services.Implementation; -using Microsoft.AppCenter; -using Microsoft.AppCenter.Analytics; -using Microsoft.AppCenter.Crashes; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace ClipboardCanvas -{ - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - public partial class App : Application - { - private Window m_window; - - /// - /// to resolve application services. - /// - public IServiceProvider Services { get; private set; } - - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// - public App() - { - this.InitializeComponent(); - - // Configure exception handlers - this.UnhandledException += App_UnhandledException; - TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; - if (Constants.Debugging.FIRST_CHANCE_EXCEPTION_DEBUGGING) - { - AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException; - } - - // Configure services - Services = ConfigureServices(); - Ioc.Default.ConfigureServices(Services); - - // Start AppCenter -#if !DEBUG - AppCenter.Start("c7fb111e-c2ba-4c4e-80f9-a919c9939224", typeof(Analytics), typeof(Crashes)); -#endif - } - - /// - /// Invoked when the application is launched normally by the end user. Other entry points - /// will be used such as when the application is launched to open a specific file. - /// - /// Details about the launch request and process. - protected override void OnLaunched(LaunchActivatedEventArgs args) - { - m_window = new MainWindow(); - m_window.Activate(); - } - - private IServiceProvider ConfigureServices() - { - ServiceCollection services = new ServiceCollection(); - - services - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - - // Settings services - .AddSingleton((sp) => new UserSettingsService(sp.GetService())) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton(); - - return services.BuildServiceProvider(); - } - - private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) => LogException(e.Exception); - - private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) => LogException(e.Exception, () => e.Handled = true); - - private void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e) => LogException(e.Exception); - - private void LogException(Exception e, Action tryHandleException = null) - { -#if DEBUG - if (tryHandleException == null) - { - tryHandleException = () => { }; - } - - Debug.WriteLine("--------- UNHANDLED EXCEPTION ---------"); - if (e != null) - { - Debug.WriteLine($"\n>>>> HRESULT: {e.HResult} (0x{e.HResult.ToString("X")})\n"); - if (!string.IsNullOrEmpty(e.Message)) - { - Debug.WriteLine("\n--- MESSAGE ---"); - Debug.WriteLine(e.Message); - } - if (!string.IsNullOrEmpty(e.StackTrace)) - { - Debug.WriteLine("\n--- STACKTRACE ---"); - Debug.WriteLine(e.StackTrace); - } - if (!string.IsNullOrEmpty(e.Source)) - { - Debug.WriteLine("\n--- SOURCE ---"); - Debug.WriteLine(e.Source); - } - if (e.InnerException != null) - { - Debug.WriteLine("\n--- INNER ---"); - Debug.WriteLine(e.InnerException); - } - if (!string.IsNullOrEmpty(e.HelpLink)) - { - Debug.WriteLine("\n--- HELP LINK ---"); - Debug.WriteLine(e.HelpLink); - } - } - else - { - Debug.WriteLine("\nException is null!\n"); - } - - Debug.WriteLine("---------------------------------------"); - - Debugger.Break(); // Please check "Output Window" for exception details (View -> Output Window) (CTRL + ALT + O) - - if (false) // Can only step-in manually in debug mode - { -#pragma warning disable CS0162 // Unreachable code detected - tryHandleException(); -#pragma warning restore CS0162 // Unreachable code detected - } -#else - LogExceptionToFile(e); - - IUserSettingsService userSettingsService = null; - try - { - userSettingsService = Ioc.Default.GetService(); - } - catch { } - - bool pushErrorNotification = userSettingsService?.PushErrorNotification ?? false; - - if (pushErrorNotification) - { - PushErrorNotification(); - } -#endif - } - - private void LogExceptionToFile(Exception e) - { - LoggingHelpers.SafeLogExceptionToFile(e); - } - - private void PushErrorNotification() - { - // Create custom notification - ToastContent toastContent = new ToastContent() - { - Visual = new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric() - { - Children = - { - new AdaptiveText() - { - Text = "ClipboardCanvasCrashTitle".GetLocalized2() - }, - new AdaptiveText() - { - Text = "ClipboardCanvasCrashSubtitle".GetLocalized2() - } - } - } - }, - Actions = new ToastActionsCustom() - { - Buttons = - { - new ToastButton("ClipboardCanvasCrashReportIssue".GetLocalized2(), Constants.UI.Notifications.TOAST_NOTIFICATION_ERROR_ARGUMENT) - { - ActivationType = ToastActivationType.Foreground - } - } - } - }; - - // Compile the notification to native ToastNotification - ToastNotification toastNotificationNative = new ToastNotification(toastContent.GetXml()); - - // Push the native ToastNotification - ToastNotificationManager.CreateToastNotifier().Show(toastNotificationNative); - } - } -} diff --git a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-100.png b/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-100.png deleted file mode 100644 index ef35cda6..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-125.png b/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-125.png deleted file mode 100644 index 6c6e885d..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-150.png b/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-150.png deleted file mode 100644 index ba2d145a..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-200.png b/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-200.png deleted file mode 100644 index b86336b0..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-400.png b/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-400.png deleted file mode 100644 index 1679f9cc..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/LargeTile.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-100.png b/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-100.png deleted file mode 100644 index 2e2e9c2f..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-125.png b/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-125.png deleted file mode 100644 index 19c61dda..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-150.png b/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-150.png deleted file mode 100644 index dfb2782f..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-200.png b/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-200.png deleted file mode 100644 index d62de8f5..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-400.png b/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-400.png deleted file mode 100644 index 92bc4720..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SmallTile.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-100.png b/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-100.png deleted file mode 100644 index b2658bb0..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-125.png b/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-125.png deleted file mode 100644 index 574a5b52..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-150.png b/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-150.png deleted file mode 100644 index 1c842a18..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-200.png b/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-200.png deleted file mode 100644 index ea15e888..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-400.png b/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-400.png deleted file mode 100644 index 4d74d48f..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/SplashScreen.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-100.png b/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-100.png deleted file mode 100644 index becd9a34..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-125.png b/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-125.png deleted file mode 100644 index 2fdbe33e..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-150.png b/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-150.png deleted file mode 100644 index b5ef2a1d..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-200.png b/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-200.png deleted file mode 100644 index 6c6ecb2a..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-400.png b/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-400.png deleted file mode 100644 index f88a3650..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square150x150Logo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-16.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-16.png deleted file mode 100644 index 5ba88c56..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-16.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-24.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-24.png deleted file mode 100644 index 0453592a..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-24.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-256.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-256.png deleted file mode 100644 index 0c6ac8ce..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-256.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-32.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-32.png deleted file mode 100644 index fa39f134..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-32.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-48.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-48.png deleted file mode 100644 index 27765d40..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-lightunplated_targetsize-48.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-16.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-16.png deleted file mode 100644 index 5ba88c56..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-16.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-24.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-24.png deleted file mode 100644 index 0453592a..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-24.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-256.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-256.png deleted file mode 100644 index 0c6ac8ce..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-256.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-32.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-32.png deleted file mode 100644 index fa39f134..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-32.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-48.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-48.png deleted file mode 100644 index 27765d40..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.altform-unplated_targetsize-48.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-100.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-100.png deleted file mode 100644 index ee254e63..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-125.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-125.png deleted file mode 100644 index 8d0afa2f..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-150.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-150.png deleted file mode 100644 index 94b7b62d..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-200.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-200.png deleted file mode 100644 index 0b183523..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-400.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-400.png deleted file mode 100644 index 7a0d2e6d..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-16.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-16.png deleted file mode 100644 index 5ba88c56..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-16.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-24.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-24.png deleted file mode 100644 index 0453592a..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-24.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-256.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-256.png deleted file mode 100644 index 0c6ac8ce..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-256.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-32.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-32.png deleted file mode 100644 index fa39f134..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-32.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-48.png b/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-48.png deleted file mode 100644 index 27765d40..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Square44x44Logo.targetsize-48.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-100.png b/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-100.png deleted file mode 100644 index 27f2c879..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-125.png b/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-125.png deleted file mode 100644 index b383adc0..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-150.png b/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-150.png deleted file mode 100644 index 4ce2b519..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-200.png b/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-200.png deleted file mode 100644 index 40e00991..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-400.png b/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-400.png deleted file mode 100644 index 74ef4dc0..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/StoreLogo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-100.png b/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-100.png deleted file mode 100644 index 7c89d166..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-100.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-125.png b/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-125.png deleted file mode 100644 index 93dbb92b..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-125.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-150.png b/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-150.png deleted file mode 100644 index d61f24eb..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-150.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-200.png b/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-200.png deleted file mode 100644 index b2658bb0..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-200.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-400.png b/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-400.png deleted file mode 100644 index ea15e888..00000000 Binary files a/ClipboardCanvas/Assets/AppIcon/Wide310x150Logo.scale-400.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/AppLogo.png b/ClipboardCanvas/Assets/AppLogo.png deleted file mode 100644 index f88a3650..00000000 Binary files a/ClipboardCanvas/Assets/AppLogo.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/Fonts/CalcMDL2.ttf b/ClipboardCanvas/Assets/Fonts/CalcMDL2.ttf deleted file mode 100644 index fda49927..00000000 Binary files a/ClipboardCanvas/Assets/Fonts/CalcMDL2.ttf and /dev/null differ diff --git a/ClipboardCanvas/Assets/HomepageImage.png b/ClipboardCanvas/Assets/HomepageImage.png deleted file mode 100644 index ff9ff012..00000000 Binary files a/ClipboardCanvas/Assets/HomepageImage.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/InfiniteCanvasImage.png b/ClipboardCanvas/Assets/InfiniteCanvasImage.png deleted file mode 100644 index dda2ecdd..00000000 Binary files a/ClipboardCanvas/Assets/InfiniteCanvasImage.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/NewCanvasImage.png b/ClipboardCanvas/Assets/NewCanvasImage.png deleted file mode 100644 index e9524790..00000000 Binary files a/ClipboardCanvas/Assets/NewCanvasImage.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/OOBE/OOBE_CollectionPreview.png b/ClipboardCanvas/Assets/OOBE/OOBE_CollectionPreview.png deleted file mode 100644 index e23d7756..00000000 Binary files a/ClipboardCanvas/Assets/OOBE/OOBE_CollectionPreview.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/OOBE/OOBE_Collections.png b/ClipboardCanvas/Assets/OOBE/OOBE_Collections.png deleted file mode 100644 index 8842fe3c..00000000 Binary files a/ClipboardCanvas/Assets/OOBE/OOBE_Collections.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/OOBE/OOBE_InfiniteCanvas.png b/ClipboardCanvas/Assets/OOBE/OOBE_InfiniteCanvas.png deleted file mode 100644 index a0e7fa72..00000000 Binary files a/ClipboardCanvas/Assets/OOBE/OOBE_InfiniteCanvas.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/OOBE/OOBE_OneCanvas.png b/ClipboardCanvas/Assets/OOBE/OOBE_OneCanvas.png deleted file mode 100644 index d1a331e4..00000000 Binary files a/ClipboardCanvas/Assets/OOBE/OOBE_OneCanvas.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/OOBE/OOBE_ReferenceFiles.png b/ClipboardCanvas/Assets/OOBE/OOBE_ReferenceFiles.png deleted file mode 100644 index e1b46e2b..00000000 Binary files a/ClipboardCanvas/Assets/OOBE/OOBE_ReferenceFiles.png and /dev/null differ diff --git a/ClipboardCanvas/Assets/OOBE/OOBE_Timeline.png b/ClipboardCanvas/Assets/OOBE/OOBE_Timeline.png deleted file mode 100644 index 85068ab7..00000000 Binary files a/ClipboardCanvas/Assets/OOBE/OOBE_Timeline.png and /dev/null differ diff --git a/ClipboardCanvas/AttachedProperties/BaseAttachedProperty.cs b/ClipboardCanvas/AttachedProperties/BaseAttachedProperty.cs deleted file mode 100644 index 81258754..00000000 --- a/ClipboardCanvas/AttachedProperties/BaseAttachedProperty.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using Microsoft.UI.Xaml; - -namespace ClipboardCanvas.AttachedProperties -{ - /// - /// A control tied wrapper for to attach properties - /// - /// The parent class to be the attached property - /// The type of this attached property - /// The type that this property can be attached to - public abstract class BaseAttachedProperty - where TParent : new() - where TTarget : DependencyObject - { - #region Public Events - - /// - /// Fired when the value changes - /// - public event Action ValueChanged; - - #endregion - - #region Public Properties - - /// - /// A singleton instance of our parent class - /// - public static TParent Instance { get; private set; } = new TParent(); - - #endregion - - #region Attached Property Definitions - - /// - /// The attached property for this class - /// - public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached( - "Value", - typeof(TProperty), - typeof(TTarget), - new PropertyMetadata( - default(TProperty), - new PropertyChangedCallback(OnValuePropertyChanged))); - - /// - /// The callback event when the is changed - /// - /// The UI element that had it's property changed - /// The arguments for the event - private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - // Call the parent function - (Instance as BaseAttachedProperty)?.OnValueChanged(d, e); - - // Call event listeners - (Instance as BaseAttachedProperty)?.ValueChanged?.Invoke(d, e); - } - - /// - /// Gets the attached property - /// - /// The element to get the property from - /// - public static TProperty GetValue(DependencyObject d) => (TProperty)d.GetValue(ValueProperty); - - /// - /// Sets the attached property - /// - /// The element to get the property from - /// The value to set the property to - public static void SetValue(DependencyObject d, TProperty value) => d.SetValue(ValueProperty, value); - - #endregion - - #region Event Methods - - /// - /// The method that is called when any attached property of this type is changed - /// - /// The UI element that this property was changed for - /// The arguments for this event - public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - this.OnValueChanged((TTarget)sender, (TProperty)e.NewValue); - } - - protected abstract void OnValueChanged(TTarget sender, TProperty newValue); - - #endregion - } -} diff --git a/ClipboardCanvas/AttachedProperties/BaseGenericAttachedProperty.cs b/ClipboardCanvas/AttachedProperties/BaseGenericAttachedProperty.cs deleted file mode 100644 index efe4b3f5..00000000 --- a/ClipboardCanvas/AttachedProperties/BaseGenericAttachedProperty.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using Microsoft.UI.Xaml; - -namespace ClipboardCanvas.AttachedProperties -{ - /// - /// Generic control tied wrapper for to attach properties - /// - /// The parent class to be the attached property - /// The type of this attached property - public abstract class BaseGenericAttachedProperty : BaseAttachedProperty - where TParent : new() - { - } -} diff --git a/ClipboardCanvas/AttachedProperties/BaseObservableCollectionAttachedProperty.cs b/ClipboardCanvas/AttachedProperties/BaseObservableCollectionAttachedProperty.cs deleted file mode 100644 index a74933ce..00000000 --- a/ClipboardCanvas/AttachedProperties/BaseObservableCollectionAttachedProperty.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.UI.Xaml; -using System.Collections.Specialized; -using System.Collections.ObjectModel; - -namespace ClipboardCanvas.AttachedProperties -{ - public abstract class BaseObservableCollectionAttachedProperty : BaseAttachedProperty, TTarget> - where TParent : new() - where TTarget : DependencyObject - { - private ObservableCollection _collection; - - private TTarget _sender; - - protected override void OnValueChanged(TTarget sender, ObservableCollection newValue) - { - this._collection = newValue; - this._sender = sender; - } - - public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - if (e.OldValue is INotifyCollectionChanged notifyCollectionChangedOld) - { - notifyCollectionChangedOld.CollectionChanged -= ObservableCollection_CollectionChangedInternal; - } - - if (e.NewValue is INotifyCollectionChanged notifyCollectionChangedNew) - { - notifyCollectionChangedNew.CollectionChanged -= ObservableCollection_CollectionChangedInternal; - notifyCollectionChangedNew.CollectionChanged += ObservableCollection_CollectionChangedInternal; - } - - base.OnValueChanged(sender, e); - } - - private void ObservableCollection_CollectionChangedInternal(object sender, NotifyCollectionChangedEventArgs e) - { - ObservableCollection_CollectionChanged(this._sender, this._collection, e); - } - - protected abstract void ObservableCollection_CollectionChanged(object sender, ObservableCollection collection, NotifyCollectionChangedEventArgs e); - } -} diff --git a/ClipboardCanvas/AttachedProperties/FrameAttachedProperties.cs b/ClipboardCanvas/AttachedProperties/FrameAttachedProperties.cs deleted file mode 100644 index c3bcc099..00000000 --- a/ClipboardCanvas/AttachedProperties/FrameAttachedProperties.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Pages.SettingsPages; -using ClipboardCanvas.DataModels.Navigation; - -namespace ClipboardCanvas.AttachedProperties -{ - public class SettingsFrameNavigationAttachedProperty : BaseAttachedProperty - { - protected override void OnValueChanged(Frame sender, SettingsFrameNavigationDataModel newValue) - { - switch (newValue.pageType) - { - case SettingsPageType.General: - { - sender.Navigate(typeof(SettingsGeneralPage), newValue, newValue.transitionInfo); - break; - } - - case SettingsPageType.Pasting: - { - sender.Navigate(typeof(SettingsPastingPage), newValue, newValue.transitionInfo); - break; - } - - case SettingsPageType.Notifications: - { - sender.Navigate(typeof(SettingsNotificationsPage), newValue, newValue.transitionInfo); - break; - } - - case SettingsPageType.About: - { - sender.Navigate(typeof(SettingsAboutPage), newValue, newValue.transitionInfo); - break; - } - } - } - } -} diff --git a/ClipboardCanvas/AttachedProperties/InAppNotificationAttachedProperties.cs b/ClipboardCanvas/AttachedProperties/InAppNotificationAttachedProperties.cs deleted file mode 100644 index b19b97d6..00000000 --- a/ClipboardCanvas/AttachedProperties/InAppNotificationAttachedProperties.cs +++ /dev/null @@ -1,19 +0,0 @@ -using CommunityToolkit.WinUI.UI.Controls; - -namespace ClipboardCanvas.AttachedProperties -{ - public class InAppNotificationShowHideControlAttachedProperty : BaseAttachedProperty - { - protected override void OnValueChanged(InAppNotification sender, bool newValue) - { - if (newValue) - { - sender.Show(); - } - else - { - sender.Dismiss(); - } - } - } -} diff --git a/ClipboardCanvas/AttachedProperties/MenuFlyoutAttachedProperties.cs b/ClipboardCanvas/AttachedProperties/MenuFlyoutAttachedProperties.cs deleted file mode 100644 index b439564e..00000000 --- a/ClipboardCanvas/AttachedProperties/MenuFlyoutAttachedProperties.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Microsoft.UI.Xaml.Controls; -using System.Collections.Specialized; -using System.Collections; -using System.Linq; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ViewModels.ContextMenu; - -namespace ClipboardCanvas.AttachedProperties -{ - public class FlyoutItemsSourceAttachedProperty : BaseObservableCollectionAttachedProperty - { - protected override void ObservableCollection_CollectionChanged(object sender, ObservableCollection collection, NotifyCollectionChangedEventArgs e) - { - if (sender is not MenuFlyout menuFlyout || collection == null) - { - return; - } - - UpdateMenuFlyoutItems(menuFlyout, collection, e.NewItems); - } - - protected override void OnValueChanged(MenuFlyout sender, ObservableCollection newValue) - { - base.OnValueChanged(sender, newValue); - - UpdateMenuFlyoutItems(sender, newValue, newValue); - } - - private void UpdateMenuFlyoutItems(MenuFlyout menuFlyout, IList collection, IList newItems) - { - if (newItems == null || newItems.Count == 0) - { - menuFlyout.Items.Clear(); - return; - } - - IEnumerable flyoutItems = FlyoutHelpers.GetMenuFlyoutItems(collection); - - menuFlyout.Items.Clear(); - foreach (var item in flyoutItems) - { - menuFlyout.Items.Add(item); - } - } - } -} diff --git a/ClipboardCanvas/AttachedProperties/TextBoxAttachedProperties.cs b/ClipboardCanvas/AttachedProperties/TextBoxAttachedProperties.cs deleted file mode 100644 index 9245d15e..00000000 --- a/ClipboardCanvas/AttachedProperties/TextBoxAttachedProperties.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace ClipboardCanvas.AttachedProperties -{ - public class TextBoxFocusAttachedProperty : BaseGenericAttachedProperty - { - protected override void OnValueChanged(DependencyObject sender, bool newValue) - { - if (sender is not TextBox textBox) - { - return; - } - - // Focus - if (newValue) - { - textBox.Focus(FocusState.Programmatic); - textBox.SelectAll(); - } - else // Unfocus - { - // Cannot be unfocused - } - } - } -} diff --git a/ClipboardCanvas/AttachedProperties/ViewModelAttachedProperties.cs b/ClipboardCanvas/AttachedProperties/ViewModelAttachedProperties.cs deleted file mode 100644 index 84cca8dc..00000000 --- a/ClipboardCanvas/AttachedProperties/ViewModelAttachedProperties.cs +++ /dev/null @@ -1,15 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using Microsoft.UI.Xaml; - -namespace ClipboardCanvas.AttachedProperties -{ - public class BaseViewModelAttachedProperty : BaseAttachedProperty, TViewModel, TTarget> - where TViewModel : ObservableObject - where TTarget : FrameworkElement - { - protected override void OnValueChanged(TTarget sender, TViewModel newValue) - { - sender.DataContext = newValue; - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/BasePasteModel.cs b/ClipboardCanvas/CanavsPasteModels/BasePasteModel.cs deleted file mode 100644 index 7bfadd55..00000000 --- a/ClipboardCanvas/CanavsPasteModels/BasePasteModel.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ReferenceItems; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.CanvasLoadModels; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Extensions; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public abstract class BasePasteModel : IPasteModel, ILoadModel - { - protected IStorageItem pastedItem; - - protected string customName; - - protected ICanvasItemReceiverModel canvasItemReceiver; - - protected IOperationContext operationContext; - - protected IOperationContextReceiver operationContextReceiver; - - protected CancellationToken cancellationToken; - - protected CanvasItem canvasItem; - - protected IStorageItem associatedItem => canvasItem.AssociatedItem; - - protected StorageFile associatedFile => associatedItem as StorageFile; - - protected Task sourceItem => canvasItem.SourceItem; - - protected Task sourceFile => Task.Run(async () => (await sourceItem) as StorageFile); - - protected readonly SafeWrapperResult ItemIsNotAFileResult = new SafeWrapperResult(OperationErrorCode.InvalidArgument, new ArgumentException(), "The provided item is not a file."); - - public bool IsContentAsReference { get; protected set; } - - public bool CanPasteReference { get; protected set; } - - #region Events - - public event EventHandler OnTipTextUpdateRequestedEvent; - - #endregion - - public BasePasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - { - this.canvasItemReceiver = canvasFileReceiver; - this.operationContextReceiver = operationContextReceiver; - } - - public virtual async Task> PasteData(DataPackageView dataPackage, bool pasteAsReference, CancellationToken cancellationToken) - { - SafeWrapperResult result; - - this.cancellationToken = cancellationToken; - this.IsContentAsReference = pasteAsReference; - - result = await SetDataFromDataPackageInternal(dataPackage); - if (!result) - { - return (null, result); - } - - result = await SetCanvasItemInternal(); - if (!result) - { - return (null, result); - } - - result = await SaveDataToFileInternal(); - if (!result) - { - return (null, result); - } - - return (canvasItem, result); - } - - protected async Task SetDataFromDataPackageInternal(DataPackageView dataPackage) - { - if (dataPackage.AvailableFormats.ContainsOnly(StandardDataFormats.StorageItems)) - { - SafeWrapper> items = await dataPackage.SafeGetStorageItemsAsync(); - - if (!items) - { - return items; - } - - this.pastedItem = items.Result.First(); - - return await SetDataFromExistingItem(pastedItem); - } - else - { - IsContentAsReference = false; - return await SetDataFromDataPackage(dataPackage); - } - } - - protected async Task SetCanvasItemInternal() - { - SafeWrapper canvasItem; - - if (IsContentAsReference && pastedItem != null) - { - canvasItem = await canvasItemReceiver.CreateNewCanvasItemFromExtension(Constants.FileSystem.REFERENCE_FILE_EXTENSION); - } - else - { - if (!string.IsNullOrWhiteSpace(customName)) - { - canvasItem = await canvasItemReceiver.CreateNewCanvasItem(customName); - } - else - { - canvasItem = await GetCanvasFileFromExtension(canvasItemReceiver); - } - } - - this.canvasItem = canvasItem; - return canvasItem; - } - - protected async Task SaveDataToFileInternal() - { - if (IsContentAsReference && await sourceItem == null) - { - // We need to update the reference file because the one we created is empty - ReferenceFile referenceFile = await ReferenceFile.CreateReferenceFileFromFile(associatedFile, pastedItem); - return referenceFile.LastError; - } - else - { - // If pasting a file and not raw data from clipboard... - if (pastedItem is StorageFile pastedFile && pastedFile.Path != associatedItem.Path) - { - // Signalize that the file is being pasted - RaiseOnTipTextUpdateRequestedEvent(this, new TipTextUpdateRequestedEventArgs("The file is being pasted, please wait.", TimeSpan.FromMilliseconds(Constants.UI.CanvasContent.FILE_PASTING_TIP_DELAY))); - - this.operationContext = operationContextReceiver.GetOperationContext("Pasting file", StatusCenterOperationType.Paste); - - // Copy the file data directly when pasting a file and not raw data from clipboard - return await FilesystemOperations.CopyFileAsync(pastedFile, associatedFile, operationContext); - } - else - { - return await SaveDataToFile(); - } - } - } - - public virtual bool CheckCanPasteReference() - { - return true; - } - - protected abstract Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver); - - protected abstract Task SetDataFromDataPackage(DataPackageView dataPackage); - - protected abstract Task SaveDataToFile(); - - public abstract Task SetDataFromExistingItem(IStorageItem item); - - #region Event Raisers - - protected void RaiseOnTipTextUpdateRequestedEvent(object s, TipTextUpdateRequestedEventArgs e) => OnTipTextUpdateRequestedEvent?.Invoke(s, e); - - #endregion - - public virtual void Dispose() - { - // TODO: Should anything be put here? - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/FallbackPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/FallbackPasteModel.cs deleted file mode 100644 index da2f0b97..00000000 --- a/ClipboardCanvas/CanavsPasteModels/FallbackPasteModel.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using Windows.Storage.FileProperties; -using Microsoft.UI.Xaml.Media.Imaging; -using System.IO; - -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class FallbackPasteModel : BasePasteModel - { - private bool _isFolder; - - public StorageItemThumbnail ItemThumbnail { get; private set; } - - public string FileName { get; private set; } - - public string FilePath { get; private set; } - - public DateTime DateCreated { get; private set; } - - public DateTime DateModified { get; private set; } - - public BitmapImage FileIcon { get; private set; } - - public FallbackPasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base(canvasFileReceiver, operationContextReceiver) - { - } - - protected override Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - return Task.FromResult>((null, SafeWrapperResult.SUCCESS)); - } - - protected override Task SaveDataToFile() - { - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override Task SetDataFromDataPackage(DataPackageView dataPackage) - { - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - public override async Task SetDataFromExistingItem(IStorageItem item) - { - // Read file properties - if (item is StorageFile file) - { - ItemThumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem); - } - else if (item is StorageFolder folder) - { - _isFolder = true; - ItemThumbnail = await folder.GetThumbnailAsync(ThumbnailMode.SingleItem); - } - - this.FileName = item.Name; - this.FilePath = item.Path; - this.DateCreated = item.DateCreated.DateTime; - - var properties = await item.GetBasicPropertiesAsync(); - this.DateModified = properties.DateModified.DateTime; - - FileIcon = new BitmapImage(); - await FileIcon.SetSourceAsync(ItemThumbnail); - - return SafeWrapperResult.SUCCESS; - } - - public override bool CheckCanPasteReference() - { - return !_isFolder; - } - - public void UpdatePathProperty(string newPath) - { - this.FilePath = newPath; - this.FileName = Path.GetFileName(newPath); - } - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - ItemThumbnail?.Dispose(); - - ItemThumbnail = null; - FileIcon = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/IPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/IPasteModel.cs deleted file mode 100644 index 27ee3386..00000000 --- a/ClipboardCanvas/CanavsPasteModels/IPasteModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.DataModels; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public interface IPasteModel : IDisposable - { - bool IsContentAsReference { get; } - - Task> PasteData(DataPackageView dataPackage, bool pasteAsReference, CancellationToken cancellationToken); - - bool CheckCanPasteReference(); - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/ImagePasteModel.cs b/ClipboardCanvas/CanavsPasteModels/ImagePasteModel.cs deleted file mode 100644 index 7fc13b6f..00000000 --- a/ClipboardCanvas/CanavsPasteModels/ImagePasteModel.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Graphics.Imaging; -using Windows.Storage; -using Windows.Storage.Streams; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using Microsoft.UI.Xaml.Media.Imaging; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; -using System.IO; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class ImagePasteModel : BasePasteModel - { - private bool _wasPastedAsReference; - - public SoftwareBitmap SoftwareBitmap { get; private set; } - - public BitmapImage GifBitmapImage; - - public ImagePasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base (canvasFileReceiver, operationContextReceiver) - { - } - - public override Task> PasteData(DataPackageView dataPackage, bool pasteAsReference, CancellationToken cancellationToken) - { - _wasPastedAsReference = pasteAsReference; - return base.PasteData(dataPackage, pasteAsReference, cancellationToken); - } - - protected override async Task SetDataFromDataPackage(DataPackageView dataPackage) - { - SafeWrapper openedStream = null; - - if (dataPackage.Contains(StandardDataFormats.Text)) // Url to file - { - if (dataPackage.Contains(StandardDataFormats.StorageItems)) // Url to StorageFile - { - SafeWrapper> items = await dataPackage.SafeGetStorageItemsAsync(); - - if (!items) - { - return items; - } - - StorageFile imageFile = items.Result.First() as StorageFile; - customName = imageFile.Name; - - openedStream = await SafeWrapperRoutines.SafeWrapAsync( - () => imageFile.OpenReadAsync().AsTask()); - } - else // Download from url - { - SafeWrapper url = await dataPackage.SafeGetTextAsync(); - - if (!url) - { - return url; - } - - openedStream = await SafeWrapperRoutines.SafeWrapAsync( - async () => await (RandomAccessStreamReference.CreateFromUri(new Uri(url))).OpenReadAsync()); - } - } - else if (dataPackage.Contains(StandardDataFormats.Bitmap)) // Just image - { - SafeWrapper bitmap = await dataPackage.SafeGetBitmapAsync(); - SafeWrapper uri = await dataPackage.SafeGetUriAsync(); - - if (uri) - { - customName = Path.GetFileName(uri.Result.LocalPath); - if (!Path.HasExtension(customName)) - { - customName = $"{customName}.png"; - } - } - - if (!bitmap) - { - return bitmap; - } - - openedStream = await SafeWrapperRoutines.SafeWrapAsync( - () => bitmap.Result.OpenReadAsync().AsTask()); - - } - else if (dataPackage.Contains(StandardDataFormats.StorageItems)) // File to image - { - SafeWrapper> items = await dataPackage.SafeGetStorageItemsAsync(); - - if (!items) - { - return items; - } - - IsContentAsReference = _wasPastedAsReference; - - this.pastedItem = items.Result.First(); - return await SetDataFromExistingItem(pastedItem); - } - - openedStream ??= new SafeWrapper(null, ItemIsNotAFileResult); - if (!openedStream) - { - openedStream.Result?.Dispose(); - return openedStream; - } - - return await SafeWrapperRoutines.SafeWrapAsync(async () => - { - using (openedStream.Result) - { - BitmapDecoder bitmapDecoder = await BitmapDecoder.CreateAsync(openedStream.Result); - SoftwareBitmap = await bitmapDecoder.GetSoftwareBitmapAsync(); - } - }); - } - - protected override async Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - return await canvasFileReceiver.CreateNewCanvasItemFromExtension(".png"); - } - - protected override async Task SaveDataToFile() - { - SafeWrapperResult result; - - BitmapEncoder bitmapEncoder = null; - result = await SafeWrapperRoutines.SafeWrapAsync(async () => - { - using (IRandomAccessStream fileStream = await (await sourceFile).OpenAsync(FileAccessMode.ReadWrite)) - { - bitmapEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream); - bitmapEncoder.SetSoftwareBitmap(SoftwareBitmap); - await bitmapEncoder.FlushAsync(); - } - }); - - if (!result) - { - const int WINCODEC_ERR_UNSUPPORTEDOPERATION = unchecked((int)0x88982F81); - int hresult = result.Exception.HResult; - - result = await SafeWrapperRoutines.SafeWrapAsync(async () => - { - if (hresult == WINCODEC_ERR_UNSUPPORTEDOPERATION) - { - using (IRandomAccessStream fileStream = await (await sourceFile).OpenAsync(FileAccessMode.ReadWrite)) - { - bitmapEncoder.IsThumbnailGenerated = false; - await bitmapEncoder.FlushAsync(); - } - } - }); - } - - return result; - } - - public override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper openedStream = await SafeWrapperRoutines.SafeWrapAsync( - () => file.OpenAsync(FileAccessMode.Read).AsTask()); - - if (!openedStream) - { - return openedStream; - } - - return await SafeWrapperRoutines.SafeWrapAsync(async () => - { - using (openedStream.Result) - { - if (FileHelpers.IsPathEqualExtension(item.Path, ".gif")) - { - GifBitmapImage = new BitmapImage(); - await GifBitmapImage.SetSourceAsync(openedStream.Result); - } - else - { - BitmapDecoder bitmapDecoder = await BitmapDecoder.CreateAsync(openedStream.Result); - SoftwareBitmap = await bitmapDecoder.GetSoftwareBitmapAsync(); - } - } - }); - } - - public override void Dispose() - { - base.Dispose(); - - SoftwareBitmap?.Dispose(); - SoftwareBitmap = null; - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/MarkdownPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/MarkdownPasteModel.cs deleted file mode 100644 index 8352ef18..00000000 --- a/ClipboardCanvas/CanavsPasteModels/MarkdownPasteModel.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using ClipboardCanvas.CanvasFileReceivers; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class MarkdownPasteModel : BasePasteModel - { - public string MarkdownText { get; private set; } - - public MarkdownPasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base(canvasFileReceiver, operationContextReceiver) - { - } - - protected override async Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - return await canvasFileReceiver.CreateNewCanvasItemFromExtension(".md"); - } - - protected async override Task SaveDataToFile() - { - return await FilesystemOperations.WriteFileText(await sourceFile, MarkdownText); - } - - protected override async Task SetDataFromDataPackage(DataPackageView dataPackage) - { - SafeWrapper text = await dataPackage.SafeGetTextAsync(); - - MarkdownText = text; - - return text; - } - - public override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - this.MarkdownText = text; - - return text; - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/MediaPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/MediaPasteModel.cs deleted file mode 100644 index 19287a16..00000000 --- a/ClipboardCanvas/CanavsPasteModels/MediaPasteModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Contexts.Operations; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class MediaPasteModel : BasePasteModel - { - public MediaPasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base(canvasFileReceiver, operationContextReceiver) - { - } - - protected override Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - return Task.FromResult>((null, SafeWrapperResult.SUCCESS)); - } - - protected override Task SaveDataToFile() - { - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override Task SetDataFromDataPackage(DataPackageView dataPackage) - { - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - public override Task SetDataFromExistingItem(IStorageItem item) - { - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/TextPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/TextPasteModel.cs deleted file mode 100644 index 574532e6..00000000 --- a/ClipboardCanvas/CanavsPasteModels/TextPasteModel.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class TextPasteModel : BasePasteModel - { - public string Text { get; private set; } - - public TextPasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base(canvasFileReceiver, operationContextReceiver) - { - } - - protected async override Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - return await canvasFileReceiver.CreateNewCanvasItemFromExtension(".txt"); - } - - protected override async Task SaveDataToFile() - { - return await FilesystemOperations.WriteFileText(await sourceFile, Text); - } - - protected async override Task SetDataFromDataPackage(DataPackageView dataPackage) - { - SafeWrapper text = await dataPackage.SafeGetTextAsync(); - - Text = text; - - return text; - } - - public async override Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - this.Text = text; - - return text; - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/UrlPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/UrlPasteModel.cs deleted file mode 100644 index 62044308..00000000 --- a/ClipboardCanvas/CanavsPasteModels/UrlPasteModel.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class UrlPasteModel : BasePasteModel - { - public string Url { get; private set; } - - public UrlPasteModel(ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base(canvasFileReceiver, operationContextReceiver) - { - } - - public override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper url = await FilesystemOperations.ReadFileText(file); - - this.Url = url; - - return url; - } - - protected override async Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - return await canvasFileReceiver.CreateNewCanvasItemFromExtension(Constants.FileSystem.URL_CANVAS_FILE_EXTENSION); - } - - protected override async Task SaveDataToFile() - { - return await FilesystemOperations.WriteFileText(await sourceFile, Url); - } - - protected override async Task SetDataFromDataPackage(DataPackageView dataPackage) - { - SafeWrapper url = await dataPackage.SafeGetTextAsync(); - - Url = url; - - return url; - } - } -} diff --git a/ClipboardCanvas/CanavsPasteModels/WebViewPasteModel.cs b/ClipboardCanvas/CanavsPasteModels/WebViewPasteModel.cs deleted file mode 100644 index d5059fe3..00000000 --- a/ClipboardCanvas/CanavsPasteModels/WebViewPasteModel.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.CanavsPasteModels -{ - public class WebViewPasteModel : BasePasteModel - { - private readonly WebViewCanvasMode _mode; - - public string HtmlText { get; private set; } - - public string Source { get; private set; } - - public WebViewPasteModel(WebViewCanvasMode mode, ICanvasItemReceiverModel canvasFileReceiver, IOperationContextReceiver operationContextReceiver) - : base(canvasFileReceiver, operationContextReceiver) - { - this._mode = mode; - } - - public override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - if (_mode == WebViewCanvasMode.ReadWebsite) - { - Source = text; - } - else - { - HtmlText = text; - } - - return text; - } - - protected override async Task> GetCanvasFileFromExtension(ICanvasItemReceiverModel canvasFileReceiver) - { - if (_mode == WebViewCanvasMode.ReadWebsite) - { - return await canvasFileReceiver.CreateNewCanvasItemFromExtension(Constants.FileSystem.WEBSITE_LINK_FILE_EXTENSION); - } - else - { - return await canvasFileReceiver.CreateNewCanvasItemFromExtension(".html"); - } - } - - protected override async Task SaveDataToFile() - { - SafeWrapperResult result; - - if (associatedFile == null) - { - return ItemIsNotAFileResult; - } - - if (_mode == WebViewCanvasMode.ReadWebsite) - { - result = await FilesystemOperations.WriteFileText(associatedFile, Source); - } - else - { - result = await FilesystemOperations.WriteFileText(associatedFile, HtmlText); - } - - return result; - } - - protected override async Task SetDataFromDataPackage(DataPackageView dataPackage) - { - SafeWrapper text = await dataPackage.SafeGetTextAsync(); - - if (_mode == WebViewCanvasMode.ReadWebsite) - { - Source = text; - } - else - { - HtmlText = text; - } - - return text; - } - } -} diff --git a/ClipboardCanvas/CanvasFileReceivers/ICanvasItemReceiverModel.cs b/ClipboardCanvas/CanvasFileReceivers/ICanvasItemReceiverModel.cs deleted file mode 100644 index b99476ef..00000000 --- a/ClipboardCanvas/CanvasFileReceivers/ICanvasItemReceiverModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.CanvasFileReceivers -{ - public interface ICanvasItemReceiverModel - { - Task> CreateNewCanvasFolder(string folderName = null); - - Task> CreateNewCanvasItemFromExtension(string extension); - - Task> CreateNewCanvasItem(string fileName); - - Task DeleteItem(IStorageItem itemToDelete, bool permanently); - } -} diff --git a/ClipboardCanvas/CanvasFileReceivers/InfiniteCanvasFileReceiver.cs b/ClipboardCanvas/CanvasFileReceivers/InfiniteCanvasFileReceiver.cs deleted file mode 100644 index c936d83e..00000000 --- a/ClipboardCanvas/CanvasFileReceivers/InfiniteCanvasFileReceiver.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.CanvasFileReceivers -{ - public class InfiniteCanvasFileReceiver : ICanvasItemReceiverModel - { - private CanvasItem _infiniteCanvasFolder; - - public InfiniteCanvasFileReceiver(CanvasItem infiniteCanvasFolder) - { - this._infiniteCanvasFolder = infiniteCanvasFolder; - } - - public Task> CreateNewCanvasFolder(string folderName = null) - { - // TODO: In the future, allow cascading Infinite Canvases - return Task.FromResult(new SafeWrapper(null, new SafeWrapperResult(OperationErrorCode.InvalidOperation, new InvalidOperationException(), "Cannot create folders inside Infinite Canvas."))); - } - - public async Task> CreateNewCanvasItemFromExtension(string extension) - { - string fileName = DateTime.Now.ToString(Constants.FileSystem.CANVAS_FILE_FILENAME_DATE_FORMAT); - fileName = $"{fileName}{extension}"; - - return await CreateNewCanvasItem(fileName); - } - - public async Task> CreateNewCanvasItem(string fileName) - { - if (_infiniteCanvasFolder == null || await _infiniteCanvasFolder.SourceItem is not StorageFolder folder) - { - return new SafeWrapper(null, OperationErrorCode.NotFound, new DirectoryNotFoundException(), "The Infinite Canvas folder was not found."); - } - - SafeWrapper file = await FilesystemOperations.CreateFile(folder, fileName); - - return (new CanvasItem(file.Result), file.Details); - } - - public async Task DeleteItem(IStorageItem itemToDelete, bool permanently) - { - return await FilesystemOperations.DeleteItem(itemToDelete, permanently); - } - } -} diff --git a/ClipboardCanvas/CanvasLoadModels/ILoadModel.cs b/ClipboardCanvas/CanvasLoadModels/ILoadModel.cs deleted file mode 100644 index 828840e4..00000000 --- a/ClipboardCanvas/CanvasLoadModels/ILoadModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.CanvasLoadModels -{ - public interface ILoadModel - { - Task SetDataFromExistingItem(IStorageItem item); - } -} diff --git a/ClipboardCanvas/ClipboardCanvas.csproj b/ClipboardCanvas/ClipboardCanvas.csproj deleted file mode 100644 index 41cc1338..00000000 --- a/ClipboardCanvas/ClipboardCanvas.csproj +++ /dev/null @@ -1,63 +0,0 @@ - - - WinExe - net6.0-windows10.0.20348.0 - 10.0.17763.0 - ClipboardCanvas - en-US - Scale|DXFeatureLevel - Language=en-US;de-DE;pt-PT;ro-RO;ru-RU;zh-CN - app.manifest - x86;x64;arm64 - win10-x86;win10-x64;win10-arm64 - true - True - false - False - False - True - False - Always - x86|x64|arm64 - 0 - - - 4.0 - en-US - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MSBuild:Compile - - - \ No newline at end of file diff --git a/ClipboardCanvas/Constants.cs b/ClipboardCanvas/Constants.cs deleted file mode 100644 index 3de378a3..00000000 --- a/ClipboardCanvas/Constants.cs +++ /dev/null @@ -1,129 +0,0 @@ -namespace ClipboardCanvas -{ - public static class Constants - { - public static class ClipboardCanvasRepository - { - public const string REPOSITORY_OWNER = "d2dyno1"; - - public const string REPOSITORY_NAME = "ClipboardCanvas"; - - public const string PRIVACY_POLICY_FILENAME = "Privacy.md"; - } - - public static class LocalSettings - { - public const string SETTINGS_FOLDERNAME = "app_settings"; - - public const string HTML_TEMPDATA_FOLDERNAME = "tmp_htmlfiles"; - - public const string USER_SETTINGS_FILENAME = "user_settings.json"; - - public const string COLLECTION_SETTINGS_FILENAME = "collections_settings.json"; - - public const string TIMELINE_SETTINGS_FILENAME = "timeline_settings.json"; - - public const string CANVAS_SETTINGS_FILENAME = "canvas_settings.json"; - - public const string AUTOPASTE_SETTINGS_FILENAME = "autopaste_settings.json"; - - public const string APPLICATION_SETTINGS_FILENAME = "application_settings.json"; - } - - public static class UI - { - public const int CONTROL_LOAD_DELAY = 50; - - public const bool USE_GETLOCALIZED2 = true; - - public static class CanvasContent - { - public const long FALLBACK_TEXTLOAD_MAX_FILESIZE = 1048576L; - - public const int SHOW_LOADING_RING_DELAY = 100; - - public const int COLLECTION_RELOADING_TIP_DELAY = 400; - - public const int FILE_PASTING_TIP_DELAY = 150; - - public const uint SIMPLE_CANVAS_THUMBNAIL_SIZE = 128u; - - public const int INFINITE_CANVAS_SAVE_INTERVAL = 800; - - public const int INFINITE_CANVAS_ERROR_SHOW_TIME = 2000; - - public const string INFINITE_CANVAS_DRAGGED_OBJECT_ID = "clipboard_canvas__dragged_control_object"; - - public static class UrlCanvas - { - public const int MAX_IMAGES_TO_DISPLAY = 4; - } - } - - public static class Imaging - { - public const int IMAGE_FROM_URI_TIMEOUT = 5000; - } - - public static class Notifications - { - public const int NOTIFICATION_PROGRESSBAR_REFRESH_INTERVAL = 50; - - public const int NOTIFICATION_DEFAULT_SHOW_TIME = 4000; - - public const string TOAST_NOTIFICATION_ERROR_ARGUMENT = "clipboard_canvas__report_error"; - } - - public static class Animations - { - public const string CONNECTED_ANIMATION_COLLECTION_PREVIEW_ITEM_OPEN_REQUESTED_TOKEN = "collection_preview_item_opening_connected_animation"; - } - - public static class Timeline - { - public const int MAX_ITEMS_PER_SECTION = 10; - - public const int MAX_SECTIONS = 10; - } - } - - public static class FileSystem - { - public const string EXCEPTIONLOG_FILENAME = "clipboardcanvas_exceptionlog.log"; - - public const string COLLECTION_ICONS_FOLDERNAME = "collections_icons"; - - public const string REFERENCE_FILE_EXTENSION = ".ccvr"; - - public const string WEBSITE_LINK_FILE_EXTENSION = ".ccvwl"; - - public const string URL_CANVAS_FILE_EXTENSION = ".ccvurl"; - - public const string INFINITE_CANVAS_EXTENSION = ".ccvic"; - - public const string INFINITE_CANVAS_CONFIGURATION_FILE_EXTENSION = ".ccviccfg"; - - public const string INFINITE_CANVAS_CONFIGURATION_FILENAME = "infinite_canvas_configuration.ccviccfg"; - - public const string INFINITE_CANVAS_PREVIEW_IMAGE_FILENAME = "infinite_canvas_preview.png"; - - public const string CANVAS_FILE_FILENAME_DATE_FORMAT = "dd.MM.yyyy HH_mm_ss"; - - public const string EXCEPTION_BLOCK_DATE_FORMAT = "dd.MM.yyyy HH_mm_ss"; - - public const int COPY_FILE_BUFFER_SIZE = 1024 * 1024; // 1mb - } - - public static class Collections - { - public const string DEFAULT_COLLECTION_TOKEN = "$DEFAULT_COLLECTION$"; - - public const int DOUBLE_CLICK_DELAY_MILLISECONDS = 300; - } - - public static class Debugging - { - public const bool FIRST_CHANCE_EXCEPTION_DEBUGGING = false; - } - } -} diff --git a/ClipboardCanvas/Contexts/Operations/IOperationContext.cs b/ClipboardCanvas/Contexts/Operations/IOperationContext.cs deleted file mode 100644 index 7eb7077e..00000000 --- a/ClipboardCanvas/Contexts/Operations/IOperationContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Threading; - -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.Contexts.Operations -{ - public interface IOperationContext - { - event EventHandler OnOperationFinishedEvent; - - bool IsOperationStarted { get; } - - bool IsOperationFinished { get; } - - CancellationToken CancellationToken { get; } - - IProgress OperationProgress { get; } - - void StartOperation(); - - void FinishOperation(SafeWrapperResult result); - } -} diff --git a/ClipboardCanvas/Contexts/Operations/IOperationContextReceiver.cs b/ClipboardCanvas/Contexts/Operations/IOperationContextReceiver.cs deleted file mode 100644 index e53f8568..00000000 --- a/ClipboardCanvas/Contexts/Operations/IOperationContextReceiver.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Contexts.Operations -{ - public interface IOperationContextReceiver - { - IOperationContext GetOperationContext(string operationName, StatusCenterOperationType operationType); - } -} diff --git a/ClipboardCanvas/Contexts/Operations/OperationContext.cs b/ClipboardCanvas/Contexts/Operations/OperationContext.cs deleted file mode 100644 index 7cfce87c..00000000 --- a/ClipboardCanvas/Contexts/Operations/OperationContext.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Threading; - -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.Contexts.Operations -{ - public sealed class OperationContext : IOperationContext - { - public event EventHandler OnOperationFinishedEvent; - - public bool IsEventAlreadyHooked { get; set; } - - public bool IsOperationStarted { get; set; } - - public CancellationToken CancellationToken { get; set; } - - public bool IsOperationFinished { get; private set; } - - IProgress IOperationContext.OperationProgress { get; } - - public void FinishOperation(SafeWrapperResult result) - { - IsOperationFinished = true; - IsOperationStarted = false; - - OnOperationFinishedEvent?.Invoke(this, new OperationFinishedEventArgs(result)); - } - - public void StartOperation() - { - if (IsOperationFinished) - { - IsOperationStarted = false; - return; - } - - IsOperationStarted = true; - } - } -} diff --git a/ClipboardCanvas/Contexts/Operations/StatusCenterOperationReceiver.cs b/ClipboardCanvas/Contexts/Operations/StatusCenterOperationReceiver.cs deleted file mode 100644 index b6cd6fbf..00000000 --- a/ClipboardCanvas/Contexts/Operations/StatusCenterOperationReceiver.cs +++ /dev/null @@ -1,19 +0,0 @@ -using CommunityToolkit.Mvvm.DependencyInjection; -using System; -using System.Threading; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.Contexts.Operations -{ - public sealed class StatusCenterOperationReceiver : IOperationContextReceiver - { - private IStatusCenterService StatusCenterService { get; } = Ioc.Default.GetService(); - - public IOperationContext GetOperationContext(string operationName, StatusCenterOperationType operationType) - { - return StatusCenterService.AppendOperationBanner(operationName, operationType, new CancellationTokenSource(), TimeSpan.FromMilliseconds(850)); - } - } -} diff --git a/ClipboardCanvas/Contexts/SearchContext.cs b/ClipboardCanvas/Contexts/SearchContext.cs deleted file mode 100644 index 0d786230..00000000 --- a/ClipboardCanvas/Contexts/SearchContext.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace ClipboardCanvas.Contexts -{ - public sealed class SearchContext - { - public readonly string phrase; - - public readonly int indexInSearch; - - public SearchContext(string phrase, int indexInSearch) - { - this.phrase = phrase; - this.indexInSearch = indexInSearch; - } - } -} diff --git a/ClipboardCanvas/DataModels/AppLanguageModel.cs b/ClipboardCanvas/DataModels/AppLanguageModel.cs deleted file mode 100644 index df600007..00000000 --- a/ClipboardCanvas/DataModels/AppLanguageModel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using ClipboardCanvas.GlobalizationExtensions; -using System; -using System.Globalization; - -using ClipboardCanvas.Extensions; - -namespace ClipboardCanvas.DataModels -{ - [Serializable] - public sealed class AppLanguageModel - { - public string Id { get; set; } - - public string Name { get; set; } - - public AppLanguageModel(string id) - { - if (!string.IsNullOrEmpty(id)) - { - var info = new CultureInfo(id); - Id = info.Name; - Name = info.NativeName.FirstToUpper(); - } - else - { - Id = string.Empty; - var systemDefaultLanguageOptionStr = "SettingsGeneralPageDefaultLanguage".GetLocalized2(); - Name = string.IsNullOrEmpty(systemDefaultLanguageOptionStr) ? "System Default" : systemDefaultLanguageOptionStr; - } - } - - public override string ToString() - { - return Name; - } - } -} diff --git a/ClipboardCanvas/DataModels/BaseAdditionalData.cs b/ClipboardCanvas/DataModels/BaseAdditionalData.cs deleted file mode 100644 index 0b7d9b38..00000000 --- a/ClipboardCanvas/DataModels/BaseAdditionalData.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ClipboardCanvas.DataModels -{ - /// - /// Abstract base class to implement for storing any type of data - /// - public abstract class BaseAdditionalData - { - public abstract object GetData(); - } -} diff --git a/ClipboardCanvas/DataModels/CanvasItem.cs b/ClipboardCanvas/DataModels/CanvasItem.cs deleted file mode 100644 index e86ecbe6..00000000 --- a/ClipboardCanvas/DataModels/CanvasItem.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Threading.Tasks; -using Windows.Storage; -using ClipboardCanvas.ReferenceItems; - -namespace ClipboardCanvas.DataModels -{ - public class CanvasItem - { - #region Protected Members - - protected IStorageItem sourceItem; - - #endregion - - #region Public Properties - - public IStorageItem AssociatedItem { get; protected set; } - - public Task SourceItem => GetSourceItem(); - - public bool IsFileAsReference => AssociatedItem is StorageFile file && ReferenceFile.IsReferenceFile(file); - - #endregion - - #region Constructor - - public CanvasItem(IStorageItem associatedItem) - : this(associatedItem, null) - { - } - - public CanvasItem(IStorageItem associatedItem, IStorageItem sourceItem) - { - this.AssociatedItem = associatedItem; - this.sourceItem = sourceItem; - } - - #endregion - - #region Helpers - - protected virtual async Task GetSourceItem() - { - if (sourceItem != null) - { - return sourceItem; - } - - if (AssociatedItem is StorageFile file && ReferenceFile.IsReferenceFile(file)) - { - ReferenceFile referenceFile = await ReferenceFile.GetReferenceFile(file); - sourceItem = referenceFile.ReferencedItem; - } - else - { - sourceItem = AssociatedItem; - } - - return sourceItem; - } - - public virtual void DangerousUpdateItem(IStorageItem newAssociatedItem, IStorageItem sourceItem = null) - { - this.AssociatedItem = newAssociatedItem; - this.sourceItem = sourceItem; - } - - #endregion - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/BaseContentTypeModel.cs b/ClipboardCanvas/DataModels/ContentDataModels/BaseContentTypeModel.cs deleted file mode 100644 index 0bada4c5..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/BaseContentTypeModel.cs +++ /dev/null @@ -1,275 +0,0 @@ -using CommunityToolkit.Mvvm.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ReferenceItems; -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay; -using ClipboardCanvas.Extensions; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public abstract class BaseContentTypeModel - { - public static readonly SafeWrapperResult CannotDisplayContentForTypeResult = new SafeWrapperResult(OperationErrorCode.InvalidOperation, new InvalidOperationException(), "Couldn't display content for this file"); - - public static readonly SafeWrapperResult CannotReceiveClipboardDataResult = new SafeWrapperResult(OperationErrorCode.AccessUnauthorized, "Couldn't retrieve clipboard data"); - - public static async Task GetContentType(CanvasItem canvasFile, BaseContentTypeModel contentType) - { - if (contentType is InvalidContentTypeDataModel invalidContentType) - { - if (!invalidContentType.needsReinitialization) - { - return invalidContentType; - } - } - - if (contentType != null) - { - return contentType; - } - - if ((await canvasFile.SourceItem) is StorageFolder folder) - { - if (FileHelpers.IsPathEqualExtension(folder.Path, Constants.FileSystem.INFINITE_CANVAS_EXTENSION)) - { - return new InfiniteCanvasContentType(); - } - else - { - return new FallbackContentType(); - } - } - else if ((await canvasFile.SourceItem) is StorageFile file) - { - string ext = Path.GetExtension(file.Path); - - return await GetContentTypeFromExtension(file, ext); - } - else // The sourceFile was null - { - return new InvalidContentTypeDataModel(CannotDisplayContentForTypeResult, false); - } - } - - public static async Task GetContentType(IStorageItem item, BaseContentTypeModel contentType) - { - if (contentType is InvalidContentTypeDataModel invalidContentType) - { - if (!invalidContentType.needsReinitialization) - { - return invalidContentType; - } - } - - if (contentType != null) - { - return contentType; - } - - if (item is StorageFile file) - { - string ext = Path.GetExtension(file.Path); - - if (ReferenceFile.IsReferenceFile(file)) - { - // Reference File, get the destination file extension - ReferenceFile referenceFile = await ReferenceFile.GetReferenceFile(file); - - if (referenceFile.ReferencedItem == null) - { - return new InvalidContentTypeDataModel(referenceFile.LastError, false); - } - - return await GetContentType(referenceFile.ReferencedItem, contentType); - } - - return await GetContentTypeFromExtension(file, ext); - } - else if (item is StorageFolder) - { - IUserSettingsService userSettingsService = Ioc.Default.GetService(); - IApplicationService applicationService = Ioc.Default.GetService(); - - if (userSettingsService.AlwaysPasteFilesAsReference && !applicationService.IsInRestrictedAccessMode) - { - return new FallbackContentType(); - } - else - { - return new InvalidContentTypeDataModel(new SafeWrapperResult(OperationErrorCode.InvalidOperation | OperationErrorCode.NotAFile, new InvalidOperationException(), "Cannot paste folders without Reference Files enabled in Settings.")); - } - } - else - { - return new InvalidContentTypeDataModel(CannotDisplayContentForTypeResult, false); - } - } - - public static async Task GetContentTypeFromExtension(IStorageItem item, string ext) - { - if (item is StorageFolder folder) - { - if (FileHelpers.IsPathEqualExtension(folder.Path, Constants.FileSystem.INFINITE_CANVAS_EXTENSION)) - { - return new InfiniteCanvasContentType(); - } - else - { - return new FallbackContentType(); - } - } - - if (item is not StorageFile file) - { - // Shouldn't happen - return null; - } - - // Image - if (ImageCanvasViewModel.Extensions.Contains(ext)) - { - return new ImageContentType(); - } - - // Text - if (TextCanvasViewModel.Extensions.Contains(ext)) - { - return new TextContentType(); - } - - // Media - if (MediaCanvasViewModel.Extensions.Contains(ext)) - { - return new MediaContentType(); - } - - // WebView - if (WebViewCanvasViewModel.Extensions.Contains(ext)) - { - if (ext == Constants.FileSystem.WEBSITE_LINK_FILE_EXTENSION) - { - return new WebViewContentType(WebViewCanvasMode.ReadWebsite); - } - - return new WebViewContentType(WebViewCanvasMode.ReadHtml); - } - - // Markdown - if (MarkdownCanvasViewModel.Extensions.Contains(ext)) - { - return new MarkdownContentType(); - } - - // URL preview - if (UrlSimpleCanvasViewModel.Extensions.Contains(ext)) // TODO change this later to UrlCanvasViewModel.Extensions - { - return new UrlPreviewContentType(); - } - - // Default, try as text - if (await TextCanvasViewModel.CanLoadAsText(file)) - { - return new TextContentType(); - } - - // Use fallback - return new FallbackContentType(); - } - - public static async Task GetContentTypeFromDataPackage(DataPackageView dataPackage) - { - IUserSettingsService userSettings = Ioc.Default.GetService(); - - // Decide content type and initialize view model - - // From raw clipboard data - if (dataPackage.Contains("Art::GVML ClipFormat") || (dataPackage.Contains(StandardDataFormats.Bitmap) && !dataPackage.Contains("PowerPoint 12.0 Internal Theme"))) - { - // Image - return new ImageContentType(); - } - else if (dataPackage.Contains("Art::Text ClipFormat") || (dataPackage.Contains(StandardDataFormats.Text) && !dataPackage.Contains("PowerPoint 12.0 Internal Theme"))) - { - SafeWrapper text = await dataPackage.SafeGetTextAsync(); - - if (!text) - { - Debugger.Break(); // What!? - return new InvalidContentTypeDataModel(text); - } - - // Check if it's url - if (WebHelpers.IsUrl(text)) - { - // The url may point to image - if (await WebHelpers.IsUrlImage(text)) - { - // Image - return new ImageContentType(); - } - else - { - if (await WebHelpers.IsValidUrl(text)) - { - // Url preview - return new UrlPreviewContentType(); - } - } - } - - // Fallback to text - if (userSettings.PrioritizeMarkdownOverText) - { - // Markdown - return new MarkdownContentType(); - } - else - { - // Normal text - return new TextContentType(); - } - } - else if (dataPackage.Contains(StandardDataFormats.StorageItems)) // From clipboard storage items - { - SafeWrapper> items = await dataPackage.SafeGetStorageItemsAsync(); - - if (items && !items.Result.IsEmpty()) - { - // One item, decide contentType for it - IStorageItem item = items.Result.First(); - - BaseContentTypeModel contentType = await BaseContentTypeModel.GetContentType(item, null); - - if (contentType is InvalidContentTypeDataModel invalidContentType && invalidContentType.error == null) - { - return new InvalidContentTypeDataModel(CannotReceiveClipboardDataResult); - } - else - { - return contentType; - } - } - else - { - // No items - return new InvalidContentTypeDataModel(CannotReceiveClipboardDataResult); - } - } - - return new InvalidContentTypeDataModel(CannotReceiveClipboardDataResult); - } - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/FallbackContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/FallbackContentType.cs deleted file mode 100644 index f2f3f641..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/FallbackContentType.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class FallbackContentType : BaseContentTypeModel - { - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/ImageContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/ImageContentType.cs deleted file mode 100644 index a9ceb9d7..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/ImageContentType.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - /// - /// Used for images that are directly copied from clipboard - /// - public sealed class ImageContentType : BaseContentTypeModel - { - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/InfiniteCanvasContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/InfiniteCanvasContentType.cs deleted file mode 100644 index 45fcf6a8..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/InfiniteCanvasContentType.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class InfiniteCanvasContentType : BaseContentTypeModel - { - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/InvalidContentTypeDataModel.cs b/ClipboardCanvas/DataModels/ContentDataModels/InvalidContentTypeDataModel.cs deleted file mode 100644 index 9c2b0384..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/InvalidContentTypeDataModel.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class InvalidContentTypeDataModel : BaseContentTypeModel - { - public readonly SafeWrapperResult error; - - public readonly bool needsReinitialization; - - public InvalidContentTypeDataModel(SafeWrapperResult error) - : this(error, false) - { - } - - public InvalidContentTypeDataModel(SafeWrapperResult error, bool needsReinitialization) - { - this.error = error; - this.needsReinitialization = needsReinitialization; - } - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/MarkdownContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/MarkdownContentType.cs deleted file mode 100644 index 1ce21758..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/MarkdownContentType.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class MarkdownContentType : BaseContentTypeModel - { - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/MediaContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/MediaContentType.cs deleted file mode 100644 index f2929a8f..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/MediaContentType.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class MediaContentType : BaseContentTypeModel - { - public TimeSpan savedPosition = TimeSpan.Zero; - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/TextContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/TextContentType.cs deleted file mode 100644 index 605c4c03..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/TextContentType.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class TextContentType : BaseContentTypeModel - { - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/UrlPreviewContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/UrlPreviewContentType.cs deleted file mode 100644 index 9e5a29e8..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/UrlPreviewContentType.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class UrlPreviewContentType : BaseContentTypeModel - { - } -} diff --git a/ClipboardCanvas/DataModels/ContentDataModels/WebViewContentType.cs b/ClipboardCanvas/DataModels/ContentDataModels/WebViewContentType.cs deleted file mode 100644 index 1bb638a3..00000000 --- a/ClipboardCanvas/DataModels/ContentDataModels/WebViewContentType.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.DataModels.ContentDataModels -{ - public sealed class WebViewContentType : BaseContentTypeModel - { - public readonly WebViewCanvasMode mode; - - public WebViewContentType(WebViewCanvasMode mode) - { - this.mode = mode; - } - } -} diff --git a/ClipboardCanvas/DataModels/InfiniteCanvasItem.cs b/ClipboardCanvas/DataModels/InfiniteCanvasItem.cs deleted file mode 100644 index b06a2028..00000000 --- a/ClipboardCanvas/DataModels/InfiniteCanvasItem.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Enums; -using System.IO; - -namespace ClipboardCanvas.DataModels -{ - public class InfiniteCanvasItem : CanvasItem - { - public StorageFile ConfigurationFile { get; private set; } - - public StorageFile CanvasPreviewImageFile { get; private set; } - - public InfiniteCanvasItem(IStorageItem associatedItem) - : base(associatedItem) - { - } - - public InfiniteCanvasItem(IStorageItem associatedItem, IStorageItem sourceItem) - : base(associatedItem, sourceItem) - { - } - - public async Task InitializeCanvasFolder() - { - if ((await SourceItem) is not StorageFolder infiniteCanvasFolder) - { - return new SafeWrapperResult(OperationErrorCode.AccessUnauthorized, new UnauthorizedAccessException(), "Couldn't initialize Infinite Canvas folder."); - } - - string configurationFileName = Constants.FileSystem.INFINITE_CANVAS_CONFIGURATION_FILENAME; - string canvasPreviewImageFileName = Constants.FileSystem.INFINITE_CANVAS_PREVIEW_IMAGE_FILENAME; - - SafeWrapper result = await FilesystemOperations.CreateFile(infiniteCanvasFolder, configurationFileName, CreationCollisionOption.OpenIfExists); - ConfigurationFile = result; - - if (!result) - { - return result; - } - - result = await FilesystemOperations.CreateFile(infiniteCanvasFolder, canvasPreviewImageFileName, CreationCollisionOption.OpenIfExists); - CanvasPreviewImageFile = result.Result; - - return result; - } - - public static bool IsInfiniteCanvasAsParent(CanvasItem canvasItem) - { - string parentPath = Path.GetDirectoryName(canvasItem.AssociatedItem.Path); - return FileHelpers.IsPathEqualExtension(parentPath, Constants.FileSystem.INFINITE_CANVAS_EXTENSION); - } - } -} diff --git a/ClipboardCanvas/DataModels/InteractableCanvasDataPackageComparisionDataModel.cs b/ClipboardCanvas/DataModels/InteractableCanvasDataPackageComparisionDataModel.cs deleted file mode 100644 index 05a2e96c..00000000 --- a/ClipboardCanvas/DataModels/InteractableCanvasDataPackageComparisionDataModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Windows.ApplicationModel.DataTransfer; -using Windows.Foundation; - -namespace ClipboardCanvas.DataModels -{ - public sealed class InteractableCanvasDataPackageComparisionDataModel - { - public readonly DataPackageView dataPackage; - - public readonly Point dropPoint; - - public InteractableCanvasDataPackageComparisionDataModel(DataPackageView dataPackage, Point dropPoint) - { - this.dataPackage = dataPackage; - this.dropPoint = dropPoint; - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/BaseDisplayFrameParameterDataModel.cs b/ClipboardCanvas/DataModels/Navigation/BaseDisplayFrameParameterDataModel.cs deleted file mode 100644 index dfff3656..00000000 --- a/ClipboardCanvas/DataModels/Navigation/BaseDisplayFrameParameterDataModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public abstract class BaseDisplayFrameParameterDataModel - { - public readonly ICollectionModel collectionModel; - - public readonly CanvasType canvasType; - - public BaseDisplayFrameParameterDataModel(ICollectionModel collectionModel, CanvasType canvasType) - { - this.collectionModel = collectionModel; - this.canvasType = canvasType; - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/CanvasPageNavigationParameterModel.cs b/ClipboardCanvas/DataModels/Navigation/CanvasPageNavigationParameterModel.cs deleted file mode 100644 index 37bb5f27..00000000 --- a/ClipboardCanvas/DataModels/Navigation/CanvasPageNavigationParameterModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -using ClipboardCanvas.Models; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public class CanvasPageNavigationParameterModel : BaseDisplayFrameParameterDataModel - { - public IDisposable CollectionPreviewIDisposable { get; set; } - - public CanvasPageNavigationParameterModel(ICollectionModel collectionModel, CanvasType canvasType) - : base(collectionModel, canvasType) - { - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/CollectionPreviewPageNavigationParameterModel.cs b/ClipboardCanvas/DataModels/Navigation/CollectionPreviewPageNavigationParameterModel.cs deleted file mode 100644 index 9c1892d7..00000000 --- a/ClipboardCanvas/DataModels/Navigation/CollectionPreviewPageNavigationParameterModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public class CollectionPreviewPageNavigationParameterModel : BaseDisplayFrameParameterDataModel - { - public readonly CanvasItem itemToSelect; - - public CollectionPreviewPageNavigationParameterModel(ICollectionModel collectionModel, CanvasType canvasType, CanvasItem itemToSelect = null) - : base(collectionModel, canvasType) - { - this.itemToSelect = itemToSelect; - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/DisplayFrameNavigationDataModel.cs b/ClipboardCanvas/DataModels/Navigation/DisplayFrameNavigationDataModel.cs deleted file mode 100644 index 722effdf..00000000 --- a/ClipboardCanvas/DataModels/Navigation/DisplayFrameNavigationDataModel.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.UI.Xaml.Media.Animation; - -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public class DisplayFrameNavigationDataModel - { - public readonly DisplayPageType pageType; - - public readonly NavigationTransitionInfo transitionInfo; - - public readonly BaseDisplayFrameParameterDataModel parameter; - - public bool simulateNavigation; - - public DisplayFrameNavigationDataModel(DisplayPageType pageType, BaseDisplayFrameParameterDataModel parameter, bool simulateNavigation = false) - : this(pageType, parameter, new DrillInNavigationTransitionInfo(), simulateNavigation) - { - } - - public DisplayFrameNavigationDataModel(DisplayPageType pageType, BaseDisplayFrameParameterDataModel parameter, NavigationTransitionInfo transitionInfo, bool simulateNavigation) - { - this.pageType = pageType; - this.parameter = parameter; - this.transitionInfo = transitionInfo; - this.simulateNavigation = simulateNavigation; - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/FromAutopasteHomepageNavigationParameterModel.cs b/ClipboardCanvas/DataModels/Navigation/FromAutopasteHomepageNavigationParameterModel.cs deleted file mode 100644 index 1a873034..00000000 --- a/ClipboardCanvas/DataModels/Navigation/FromAutopasteHomepageNavigationParameterModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public class FromAutopasteHomepageNavigationParameterModel : HomepageNavigationParameterModel - { - public FromAutopasteHomepageNavigationParameterModel(CanvasType canvasType) - : base(canvasType) - { - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/HomepageNavigationParameterModel.cs b/ClipboardCanvas/DataModels/Navigation/HomepageNavigationParameterModel.cs deleted file mode 100644 index 63ade7de..00000000 --- a/ClipboardCanvas/DataModels/Navigation/HomepageNavigationParameterModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public class HomepageNavigationParameterModel : BaseDisplayFrameParameterDataModel - { - public HomepageNavigationParameterModel(CanvasType canvasType, ICollectionModel collectionModel = null) - : base(collectionModel, canvasType) - { - } - } -} diff --git a/ClipboardCanvas/DataModels/Navigation/SettingsFrameNavigationDataModel.cs b/ClipboardCanvas/DataModels/Navigation/SettingsFrameNavigationDataModel.cs deleted file mode 100644 index b826dce8..00000000 --- a/ClipboardCanvas/DataModels/Navigation/SettingsFrameNavigationDataModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Media.Animation; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.DataModels.Navigation -{ - public class SettingsFrameNavigationDataModel : IEquatable - { - public readonly SettingsPageType pageType; - - public readonly NavigationTransitionInfo transitionInfo; - - public SettingsFrameNavigationDataModel(SettingsPageType pageType) - : this(pageType, new EntranceNavigationTransitionInfo()) - { - } - - public SettingsFrameNavigationDataModel(SettingsPageType pageType, NavigationTransitionInfo transitionInfo) - { - this.pageType = pageType; - this.transitionInfo = transitionInfo; - } - - public bool Equals(SettingsFrameNavigationDataModel other) - { - if ( - this.pageType == other.pageType - ) - { - return true; - } - - return false; - } - } -} diff --git a/ClipboardCanvas/DataModels/SiteMetadata.cs b/ClipboardCanvas/DataModels/SiteMetadata.cs deleted file mode 100644 index 67a5e530..00000000 --- a/ClipboardCanvas/DataModels/SiteMetadata.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.DataModels -{ - public sealed class SiteMetadata - { - public string SiteUrl { get; set; } - - public string Title { get; set; } - - public string Description { get; set; } - - public string Keywords { get; set; } - - public string IconUrl { get; set; } - - public string SiteName { get; set; } - - public List ImageUrls { get; set; } - - public bool HasAnyData { get; set; } - - public SiteMetadata() - { - ImageUrls = new List(); - } - } -} diff --git a/ClipboardCanvas/Dialogs/DeleteConfirmationDialog.xaml b/ClipboardCanvas/Dialogs/DeleteConfirmationDialog.xaml deleted file mode 100644 index ec4c044e..00000000 --- a/ClipboardCanvas/Dialogs/DeleteConfirmationDialog.xaml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - diff --git a/ClipboardCanvas/Dialogs/DeleteConfirmationDialog.xaml.cs b/ClipboardCanvas/Dialogs/DeleteConfirmationDialog.xaml.cs deleted file mode 100644 index 8d20ccf6..00000000 --- a/ClipboardCanvas/Dialogs/DeleteConfirmationDialog.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ModelViews; - -// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Dialogs -{ - public sealed partial class DeleteConfirmationDialog : ContentDialog, IDialog, IDialogView - { - public DeleteConfirmationDialogViewModel ViewModel - { - get => (DeleteConfirmationDialogViewModel)DataContext; - set => DataContext = value; - } - - public DeleteConfirmationDialog() - { - this.InitializeComponent(); - } - - public async new Task ShowAsync() => (await base.ShowAsync()).ToDialogResult(); - } -} diff --git a/ClipboardCanvas/Dialogs/FileSystemAccessDialog.xaml b/ClipboardCanvas/Dialogs/FileSystemAccessDialog.xaml deleted file mode 100644 index 3aa00c4b..00000000 --- a/ClipboardCanvas/Dialogs/FileSystemAccessDialog.xaml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Dialogs/FileSystemAccessDialog.xaml.cs b/ClipboardCanvas/Dialogs/FileSystemAccessDialog.xaml.cs deleted file mode 100644 index 98a15899..00000000 --- a/ClipboardCanvas/Dialogs/FileSystemAccessDialog.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.ModelViews; - -// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Dialogs -{ - public sealed partial class FileSystemAccessDialog : ContentDialog, IDialog, IDialogView - { - public FileSystemAccessDialogViewModel ViewModel - { - get => (FileSystemAccessDialogViewModel)DataContext; - set => DataContext = value; - } - - public async new Task ShowAsync() => (await base.ShowAsync()).ToDialogResult(); - - public FileSystemAccessDialog() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/Dialogs/SettingsDialog.xaml b/ClipboardCanvas/Dialogs/SettingsDialog.xaml deleted file mode 100644 index ff97b524..00000000 --- a/ClipboardCanvas/Dialogs/SettingsDialog.xaml +++ /dev/null @@ -1,126 +0,0 @@ - - - - - 1300 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Dialogs/SettingsDialog.xaml.cs b/ClipboardCanvas/Dialogs/SettingsDialog.xaml.cs deleted file mode 100644 index 34e2c51d..00000000 --- a/ClipboardCanvas/Dialogs/SettingsDialog.xaml.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; -using System.Threading.Tasks; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ModelViews; - -// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Dialogs -{ - public sealed partial class SettingsDialog : ContentDialog, IDialog, ISettingsDialogView, IDialogView - { - public SettingsDialogViewModel ViewModel - { - get => (SettingsDialogViewModel)DataContext; - set => DataContext = value; - } - - public SettingsDialog() - { - this.InitializeComponent(); - } - - private void ContentDialog_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - if (ViewModel != null) - { - ViewModel.View = this; - } - } - - private void SettingsNavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) - { - var selectedItem = args.SelectedItem as NavigationViewItem; - int tag = Convert.ToInt32(selectedItem.Tag); - - switch (tag) - { - default: - case 0: - { - this.ViewModel.UpdateNavigation(SettingsPageType.General); - break; - } - - case 1: - { - this.ViewModel.UpdateNavigation(SettingsPageType.Pasting); - break; - } - - case 2: - { - this.ViewModel.UpdateNavigation(SettingsPageType.Notifications); - break; - } - - case 3: - { - this.ViewModel.UpdateNavigation(SettingsPageType.About); - break; - } - } - } - - public async new Task ShowAsync() => (await base.ShowAsync()).ToDialogResult(); - - public void CloseDialog() - { - this.Hide(); - } - } -} diff --git a/ClipboardCanvas/Dialogs/UpdateChangeLogDialog.xaml b/ClipboardCanvas/Dialogs/UpdateChangeLogDialog.xaml deleted file mode 100644 index c001ef31..00000000 --- a/ClipboardCanvas/Dialogs/UpdateChangeLogDialog.xaml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Dialogs/UpdateChangeLogDialog.xaml.cs b/ClipboardCanvas/Dialogs/UpdateChangeLogDialog.xaml.cs deleted file mode 100644 index 9c4c32f9..00000000 --- a/ClipboardCanvas/Dialogs/UpdateChangeLogDialog.xaml.cs +++ /dev/null @@ -1,34 +0,0 @@ -using ClipboardCanvas.ViewModels.Dialogs; -using System.Threading.Tasks; -using Microsoft.UI.Xaml.Controls; -using System; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ModelViews; - -// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Dialogs -{ - public sealed partial class UpdateChangeLogDialog : ContentDialog, IDialog, IDialogView - { - public UpdateChangeLogDialogViewModel ViewModel - { - get => (UpdateChangeLogDialogViewModel)DataContext; - set => DataContext = value; - } - - public UpdateChangeLogDialog() - { - this.InitializeComponent(); - } - - public async new Task ShowAsync() => (await base.ShowAsync()).ToDialogResult(); - - // TODO: Move to view model - private async void ContentDialog_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - await ViewModel?.LoadUpdateDataFromGitHub(false); - } - } -} diff --git a/ClipboardCanvas/Enums/CanvasNavigationDirection.cs b/ClipboardCanvas/Enums/CanvasNavigationDirection.cs deleted file mode 100644 index 0416e0fc..00000000 --- a/ClipboardCanvas/Enums/CanvasNavigationDirection.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum CanvasNavigationDirection - { - Forward = 0, - Backward = 1 - } -} diff --git a/ClipboardCanvas/Enums/CanvasType.cs b/ClipboardCanvas/Enums/CanvasType.cs deleted file mode 100644 index f13b70f3..00000000 --- a/ClipboardCanvas/Enums/CanvasType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum CanvasType - { - OneCanvas = 0, - InfiniteCanvas = 1 - } -} diff --git a/ClipboardCanvas/Enums/DialogResult.cs b/ClipboardCanvas/Enums/DialogResult.cs deleted file mode 100644 index 7c1138fc..00000000 --- a/ClipboardCanvas/Enums/DialogResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum DialogResult - { - Primary = 0, - Secondary = 1, - Cancel = 2 - } -} diff --git a/ClipboardCanvas/Enums/DisplayPageType.cs b/ClipboardCanvas/Enums/DisplayPageType.cs deleted file mode 100644 index a997e584..00000000 --- a/ClipboardCanvas/Enums/DisplayPageType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum DisplayPageType - { - Homepage = 0, - CanvasPage = 1, - CollectionPreviewPage = 2 - } -} diff --git a/ClipboardCanvas/Enums/DragDataType.cs b/ClipboardCanvas/Enums/DragDataType.cs deleted file mode 100644 index 0e656f60..00000000 --- a/ClipboardCanvas/Enums/DragDataType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum DragDataType - { - StorageItems = 0, - Text = 1 - } -} diff --git a/ClipboardCanvas/Enums/InAppNotificationButtonType.cs b/ClipboardCanvas/Enums/InAppNotificationButtonType.cs deleted file mode 100644 index 33254130..00000000 --- a/ClipboardCanvas/Enums/InAppNotificationButtonType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum InAppNotificationButtonType - { - OkButton = 0, - YesButton = 1, - NoButton = 2 - } -} diff --git a/ClipboardCanvas/Enums/NavigationTransitionType.cs b/ClipboardCanvas/Enums/NavigationTransitionType.cs deleted file mode 100644 index 4fce0054..00000000 --- a/ClipboardCanvas/Enums/NavigationTransitionType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum NavigationTransitionType - { - Suppress = 0, - DrillInTransition = 1, - EntranceTransition = 2 - } -} diff --git a/ClipboardCanvas/Enums/OperationStatus.cs b/ClipboardCanvas/Enums/OperationStatus.cs deleted file mode 100644 index c6b24979..00000000 --- a/ClipboardCanvas/Enums/OperationStatus.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - /// - /// Contains all kinds of return statuses - /// - public enum OperationErrorCode : uint - { - Success = 0, - UnknownFailed = 1, - Canceled = 2, - AccessUnauthorized = 4, - NotFound = 8, - AlreadyExists = 16, - NotAFolder = 32, - NotAFile = 64, - InProgress = 128, - InvalidArgument = 256, - InvalidOperation = 512 - } -} diff --git a/ClipboardCanvas/Enums/SettingsPageType.cs b/ClipboardCanvas/Enums/SettingsPageType.cs deleted file mode 100644 index 39bbce77..00000000 --- a/ClipboardCanvas/Enums/SettingsPageType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum SettingsPageType - { - General = 0, - Pasting = 1, - Notifications = 2, - About = 3 - } -} diff --git a/ClipboardCanvas/Enums/StatusCenterOperationType.cs b/ClipboardCanvas/Enums/StatusCenterOperationType.cs deleted file mode 100644 index d8659c54..00000000 --- a/ClipboardCanvas/Enums/StatusCenterOperationType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum StatusCenterOperationType - { - Info = 0, - Paste = 1, - OverrideReference = 2 - } -} diff --git a/ClipboardCanvas/Enums/WebViewCanvasMode.cs b/ClipboardCanvas/Enums/WebViewCanvasMode.cs deleted file mode 100644 index dec97ca2..00000000 --- a/ClipboardCanvas/Enums/WebViewCanvasMode.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Enums -{ - public enum WebViewCanvasMode - { - Unknown = 0, - ReadHtml = 0, - ReadWebsite = 1 - } -} diff --git a/ClipboardCanvas/EventArguments/CanvasControlEventArgs.cs b/ClipboardCanvas/EventArguments/CanvasControlEventArgs.cs deleted file mode 100644 index 63eb4ab8..00000000 --- a/ClipboardCanvas/EventArguments/CanvasControlEventArgs.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using Windows.Storage; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.EventArguments.CanvasControl -{ - public abstract class BaseCanvasControlEventArgs : EventArgs - { - public readonly ICollectionModel collectionModel; - - public BaseCanvasControlEventArgs(ICollectionModel collectionModel) - { - this.collectionModel = collectionModel; - } - } - - public class ContentLoadedEventArgs : EventArgs - { - public readonly BaseContentTypeModel contentType; - - public readonly bool isFilled; - - public readonly bool pastedAsReference; - - public readonly bool canPasteReference; - - public ContentLoadedEventArgs(BaseContentTypeModel contentType, bool isFilled, bool pastedAsReference, bool canPasteReference) - { - this.contentType = contentType; - this.isFilled = isFilled; - this.pastedAsReference = pastedAsReference; - this.canPasteReference = canPasteReference; - } - } - - public class ContentStartedLoadingEventArgs : EventArgs - { - public readonly BaseContentTypeModel contentType; - - public ContentStartedLoadingEventArgs(BaseContentTypeModel contentType) - { - this.contentType = contentType; - } - } - - public class PasteInitiatedEventArgs : BaseCanvasControlEventArgs - { - public readonly bool pasteInNewCanvas; - - public readonly DataPackageView forwardedDataPackage; - - public readonly BaseContentTypeModel contentType; - - public PasteInitiatedEventArgs(bool pasteInNewCanvas, DataPackageView forwardedDataPackage, BaseContentTypeModel contentType, ICollectionModel collectionModel) - : base(collectionModel) - { - this.pasteInNewCanvas = pasteInNewCanvas; - this.forwardedDataPackage = forwardedDataPackage; - this.contentType = contentType; - } - } - - public class FileCreatedEventArgs : EventArgs - { - public readonly BaseContentTypeModel contentType; - - public readonly IStorageItem item; - - public FileCreatedEventArgs(BaseContentTypeModel contentType, IStorageItem item) - { - this.contentType = contentType; - this.item = item; - } - } - - public class FileModifiedEventArgs : EventArgs - { - public readonly IStorageItem item; - - public FileModifiedEventArgs(IStorageItem item) - { - this.item = item; - } - } - - public class FileDeletedEventArgs : BaseCanvasControlEventArgs - { - public readonly IStorageItem item; - - public FileDeletedEventArgs(IStorageItem item, ICollectionModel collectionModel) - : base(collectionModel) - { - this.item = item; - } - } - - public class ErrorOccurredEventArgs : EventArgs - { - public readonly SafeWrapperResult error; - - public readonly string errorMessage; - - public readonly BaseContentTypeModel contentType; - - public readonly TimeSpan errorMessageAutoHide; - - public ErrorOccurredEventArgs(SafeWrapperResult error, string errorMessage, BaseContentTypeModel contentType) - : this(error, errorMessage, contentType, TimeSpan.Zero) - { - } - - public ErrorOccurredEventArgs(SafeWrapperResult error, string errorMessage, BaseContentTypeModel contentType, TimeSpan errorMessageAutoHide) - { - this.error = error; - this.errorMessage = errorMessage; - this.contentType = contentType; - this.errorMessageAutoHide = errorMessageAutoHide; - } - } - - public class ProgressReportedEventArgs : EventArgs - { - public readonly float value; - - public readonly BaseContentTypeModel contentType; - - public ProgressReportedEventArgs(float value, BaseContentTypeModel contentType) - { - this.value = value; - this.contentType = contentType; - } - } - - public class TipTextUpdateRequestedEventArgs : EventArgs - { - public readonly string infoText; - - public readonly TimeSpan tipShowDelay; - - public TipTextUpdateRequestedEventArgs(string infoText) - : this(infoText, TimeSpan.Zero) - { - } - - public TipTextUpdateRequestedEventArgs(string infoText, TimeSpan tipShowDelay) - { - this.infoText = infoText; - this.tipShowDelay = tipShowDelay; - } - } - - public class OpenNewCanvasRequestedEventArgs : EventArgs - { - public readonly CanvasType canvasType; - - public OpenNewCanvasRequestedEventArgs() - { - this.canvasType = CanvasHelpers.GetDefaultCanvasType(); - } - - public OpenNewCanvasRequestedEventArgs(CanvasType canvasType) - { - this.canvasType = canvasType; - } - } -} diff --git a/ClipboardCanvas/EventArguments/CollectionPreviewEventArgs.cs b/ClipboardCanvas/EventArguments/CollectionPreviewEventArgs.cs deleted file mode 100644 index ed8fd446..00000000 --- a/ClipboardCanvas/EventArguments/CollectionPreviewEventArgs.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels; -using Windows.ApplicationModel.DataTransfer; - -namespace ClipboardCanvas.EventArguments.CollectionPreview -{ - public class CanvasPreviewOpenRequestedEventArgs : EventArgs - { - public readonly CollectionPreviewItemViewModel collectionPreviewItemViewModel; - - public CanvasPreviewOpenRequestedEventArgs(CollectionPreviewItemViewModel collectionPreviewItemViewModel) - { - this.collectionPreviewItemViewModel = collectionPreviewItemViewModel; - } - } - - public class CanvasPreviewSelectedItemChangedEventArgs : EventArgs - { - public readonly CollectionPreviewItemViewModel selectedItem; - - public CanvasPreviewSelectedItemChangedEventArgs(CollectionPreviewItemViewModel selectedItem) - { - this.selectedItem = selectedItem; - } - } - - public class CanvasPreviewPasteRequestedEventArgs : EventArgs - { - public readonly DataPackageView forwardedDataPackage; - - public readonly ICollectionModel collectionModel; - - public CanvasPreviewPasteRequestedEventArgs(DataPackageView forwardedDataPackage, ICollectionModel collectionModel) - { - this.forwardedDataPackage = forwardedDataPackage; - this.collectionModel = collectionModel; - } - } -} diff --git a/ClipboardCanvas/EventArguments/CollectionsEventArgs.cs b/ClipboardCanvas/EventArguments/CollectionsEventArgs.cs deleted file mode 100644 index 7d4feedd..00000000 --- a/ClipboardCanvas/EventArguments/CollectionsEventArgs.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.Collections; - -namespace ClipboardCanvas.EventArguments.Collections -{ - public abstract class BaseCollectionEventArgs : EventArgs - { - public readonly BaseCollectionViewModel baseCollectionViewModel; - - public BaseCollectionEventArgs(BaseCollectionViewModel baseCollectionViewModel) - { - this.baseCollectionViewModel = baseCollectionViewModel; - } - } - - public class CollectionItemAddedEventArgs : BaseCollectionEventArgs - { - public readonly CollectionItemViewModel itemChanged; - - public CollectionItemAddedEventArgs(BaseCollectionViewModel baseCollectionViewModel, CollectionItemViewModel itemChanged) - : base(baseCollectionViewModel) - { - this.itemChanged = itemChanged; - } - } - - public class CollectionItemRemovedEventArgs : BaseCollectionEventArgs - { - public readonly CollectionItemViewModel itemChanged; - - public CollectionItemRemovedEventArgs(BaseCollectionViewModel baseCollectionViewModel, CollectionItemViewModel itemChanged) - : base(baseCollectionViewModel) - { - this.itemChanged = itemChanged; - } - } - - public class CollectionItemRenamedEventArgs : BaseCollectionEventArgs - { - public readonly CollectionItemViewModel itemChanged; - - public readonly string oldPath; - - public CollectionItemRenamedEventArgs(BaseCollectionViewModel baseCollectionViewModel, CollectionItemViewModel itemChanged, string oldPath) - : base(baseCollectionViewModel) - { - this.itemChanged = itemChanged; - this.oldPath = oldPath; - } - } - - public class CollectionItemContentsChangedEventArgs : BaseCollectionEventArgs - { - public readonly CollectionItemViewModel itemChanged; - - public CollectionItemContentsChangedEventArgs(BaseCollectionViewModel baseCollectionViewModel, CollectionItemViewModel itemChanged) - : base(baseCollectionViewModel) - { - this.itemChanged = itemChanged; - } - } - - public class CollectionRemovedEventArgs : BaseCollectionEventArgs - { - public CollectionRemovedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class CollectionAddedEventArgs : BaseCollectionEventArgs - { - public CollectionAddedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class CollectionSelectionChangedEventArgs : BaseCollectionEventArgs - { - public CollectionSelectionChangedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class CollectionOpenRequestedEventArgs : BaseCollectionEventArgs - { - public CollectionOpenRequestedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class RemoveCollectionRequestedEventArgs : BaseCollectionEventArgs - { - public RemoveCollectionRequestedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class CheckRenameCollectionRequestedEventArgs : BaseCollectionEventArgs - { - public readonly string newName; - - public bool canRename; - - public CheckRenameCollectionRequestedEventArgs(BaseCollectionViewModel baseCollectionViewModel, string newName) - : base(baseCollectionViewModel) - { - this.newName = newName; - } - } - - public class CollectionItemsInitializationStartedEventArgs : BaseCollectionEventArgs - { - public CollectionItemsInitializationStartedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class CollectionItemsInitializationFinishedEventArgs : BaseCollectionEventArgs - { - public CollectionItemsInitializationFinishedEventArgs(BaseCollectionViewModel baseCollectionViewModel) - : base(baseCollectionViewModel) - { - } - } - - public class CollectionErrorRaisedEventArgs : EventArgs - { - public readonly SafeWrapperResult safeWrapperResult; - - public CollectionErrorRaisedEventArgs(SafeWrapperResult safeWrapperResult) - { - this.safeWrapperResult = safeWrapperResult; - } - } - - public class CanvasLoadFailedEventArgs : EventArgs - { - public readonly SafeWrapperResult error; - - public CanvasLoadFailedEventArgs(SafeWrapperResult error = null) - { - this.error = error; - } - } - - public class GoToHomepageRequestedEventArgs : EventArgs - { - public GoToHomepageRequestedEventArgs() - { - } - } -} diff --git a/ClipboardCanvas/EventArguments/DisplayFrameEventArgs.cs b/ClipboardCanvas/EventArguments/DisplayFrameEventArgs.cs deleted file mode 100644 index c9ddfe3e..00000000 --- a/ClipboardCanvas/EventArguments/DisplayFrameEventArgs.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.Collections; - -namespace ClipboardCanvas.DisplayFrameEventArgs -{ - public class NavigationStartedEventArgs : BaseDisplayFrameNavigationEventArgs - { - public NavigationStartedEventArgs(ICollectionModel collection, CanvasType canvasType, DisplayPageType pageType) - : base(collection, canvasType, pageType) - { - } - } - - public class NavigationFinishedEventArgs : BaseDisplayFrameNavigationEventArgs - { - public readonly bool success; - - public readonly CollectionItemViewModel collectionItemToLoad; - - public NavigationFinishedEventArgs(bool success, CollectionItemViewModel collectionItemToLoad, ICollectionModel collection, CanvasType canvasType, DisplayPageType pageType) - : base(collection, canvasType, pageType) - { - this.success = success; - this.collectionItemToLoad = collectionItemToLoad; - } - } - - public abstract class BaseDisplayFrameNavigationEventArgs : EventArgs - { - public readonly ICollectionModel collection; - - public readonly CanvasType canvasType; - - public readonly DisplayPageType pageType; - - public BaseDisplayFrameNavigationEventArgs(ICollectionModel collection, CanvasType canvasType, DisplayPageType pageType) - { - this.collection = collection; - this.canvasType = canvasType; - this.pageType = pageType; - } - } -} diff --git a/ClipboardCanvas/EventArguments/InAppNotificationEventArgs.cs b/ClipboardCanvas/EventArguments/InAppNotificationEventArgs.cs deleted file mode 100644 index dbf94831..00000000 --- a/ClipboardCanvas/EventArguments/InAppNotificationEventArgs.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.EventArguments -{ - public class InAppNotificationDismissedEventArgs - { - public readonly InAppNotificationButtonType notificationResult; - - public InAppNotificationDismissedEventArgs(InAppNotificationButtonType notificationResult) - { - this.notificationResult = notificationResult; - } - } -} diff --git a/ClipboardCanvas/EventArguments/InfiniteCanvasEventArgs.cs b/ClipboardCanvas/EventArguments/InfiniteCanvasEventArgs.cs deleted file mode 100644 index b5ac8416..00000000 --- a/ClipboardCanvas/EventArguments/InfiniteCanvasEventArgs.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Windows.Storage.Streams; - -using ClipboardCanvas.ViewModels.UserControls; - -namespace ClipboardCanvas.EventArguments.InfiniteCanvasEventArgs -{ - public class InfiniteCanvasSaveRequestedEventArgs : EventArgs - { - public readonly IBuffer canvasImageBuffer; - - public readonly uint pixelWidth; - - public readonly uint pixelHeight; - - public InfiniteCanvasSaveRequestedEventArgs(IBuffer canvasImageBuffer, uint pixelWidth, uint pixelHeight) - { - this.canvasImageBuffer = canvasImageBuffer; - this.pixelWidth = pixelWidth; - this.pixelHeight = pixelHeight; - } - } - - public class InfiniteCanvasItemRemovalRequestedEventArgs : EventArgs - { - public readonly InteractableCanvasControlItemViewModel itemToRemove; - - public InfiniteCanvasItemRemovalRequestedEventArgs(InteractableCanvasControlItemViewModel itemToRemove) - { - this.itemToRemove = itemToRemove; - } - } -} diff --git a/ClipboardCanvas/EventArguments/JsonSettingsEventArgs.cs b/ClipboardCanvas/EventArguments/JsonSettingsEventArgs.cs deleted file mode 100644 index ae46d9aa..00000000 --- a/ClipboardCanvas/EventArguments/JsonSettingsEventArgs.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace ClipboardCanvas.EventArguments -{ - public sealed class SettingChangedEventArgs : EventArgs - { - public readonly string settingName; - - public readonly object newValue; - - public SettingChangedEventArgs(string settingName, object newValue) - { - this.settingName = settingName; - this.newValue = newValue; - } - } -} diff --git a/ClipboardCanvas/EventArguments/OperationContextEventArgs.cs b/ClipboardCanvas/EventArguments/OperationContextEventArgs.cs deleted file mode 100644 index 6585de7c..00000000 --- a/ClipboardCanvas/EventArguments/OperationContextEventArgs.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.EventArguments -{ - public class OperationFinishedEventArgs : EventArgs - { - public readonly SafeWrapperResult result; - - public OperationFinishedEventArgs(SafeWrapperResult result) - { - this.result = result; - } - } -} diff --git a/ClipboardCanvas/EventArguments/SearchControlEventArgs.cs b/ClipboardCanvas/EventArguments/SearchControlEventArgs.cs deleted file mode 100644 index be9cb616..00000000 --- a/ClipboardCanvas/EventArguments/SearchControlEventArgs.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace ClipboardCanvas.EventArguments -{ - public class SearchCloseRequestedEventArgs : EventArgs - { - public SearchCloseRequestedEventArgs() - { - } - } -} diff --git a/ClipboardCanvas/EventArguments/TimelineWidgetEventArgs.cs b/ClipboardCanvas/EventArguments/TimelineWidgetEventArgs.cs deleted file mode 100644 index 74f9b608..00000000 --- a/ClipboardCanvas/EventArguments/TimelineWidgetEventArgs.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -using ClipboardCanvas.ViewModels.Widgets.Timeline; - -namespace ClipboardCanvas.EventArguments -{ - public class RemoveSectionItemRequestedEventArgs : EventArgs - { - public readonly TimelineSectionItemViewModel itemViewModel; - - public RemoveSectionItemRequestedEventArgs(TimelineSectionItemViewModel itemViewModel) - { - this.itemViewModel = itemViewModel; - } - } - - public class RemoveSectionRequestedEventArgs : EventArgs - { - public readonly TimelineSectionViewModel sectionViewModel; - - public RemoveSectionRequestedEventArgs(TimelineSectionViewModel sectionViewModel) - { - this.sectionViewModel = sectionViewModel; - } - } -} diff --git a/ClipboardCanvas/Exceptions/ReferencedFileNotFoundException.cs b/ClipboardCanvas/Exceptions/ReferencedFileNotFoundException.cs deleted file mode 100644 index 573c8adf..00000000 --- a/ClipboardCanvas/Exceptions/ReferencedFileNotFoundException.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.IO; - -namespace ClipboardCanvas.Exceptions -{ - public class ReferencedFileNotFoundException : Exception - { - public ReferencedFileNotFoundException() - : base(new FileNotFoundException().Message) - { - } - } -} diff --git a/ClipboardCanvas/Extensions/CollectionExtensions.cs b/ClipboardCanvas/Extensions/CollectionExtensions.cs deleted file mode 100644 index 6ee8bc1b..00000000 --- a/ClipboardCanvas/Extensions/CollectionExtensions.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Collections; - -namespace ClipboardCanvas.Extensions -{ - public static class CollectionExtensions - { - public static int IndexFitBounds(int itemsCount, int wantedIndex) => wantedIndex < 0 ? 0 : (wantedIndex >= itemsCount ? (itemsCount == 0 ? 0 : (itemsCount - 1)) : wantedIndex); - - public static void AddFront(this IList list, T item) => list.Insert(0, item); - - public static bool ContainsOnly(this IEnumerable enumerable, T item) - { - return enumerable.Count() == 1 && enumerable.Contains(item); - } - - public static bool AddIfNotPresent(this IList list, T item) - { - if (!list.Contains(item)) - { - list.Add(item); - return true; - } - - return false; - } - - public static void RemoveFront(this IList list) - { - if (!list.IsEmpty()) - { - list.RemoveAt(0); - } - } - - public static void RemoveBack(this IList list) - { - if (!list.IsEmpty()) - { - list.RemoveAt(list.Count - 1); - } - } - - public static void DisposeClear(this ICollection collection) - { - if (collection == null) - { - return; - } - - collection.DisposeAll(); - collection.Clear(); - } - - public static void DisposeAll(this IEnumerable enumerable) - { - if (enumerable == null) - { - return; - } - - foreach (var item in enumerable) - { - (item as IDisposable)?.Dispose(); - } - } - } -} diff --git a/ClipboardCanvas/Extensions/EnumExtensions.cs b/ClipboardCanvas/Extensions/EnumExtensions.cs deleted file mode 100644 index 6b16cb50..00000000 --- a/ClipboardCanvas/Extensions/EnumExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ClipboardCanvas.Extensions -{ - public static class EnumExtensions - { - public static T NextEnumValue(T enumerate) where T : Enum - { - IEnumerable values = Enum.GetValues(typeof(T)).Cast(); - - bool returnNext = false; - foreach (T item in values) - { - if (returnNext) - { - return item; - } - else if (item.GenericEquals(enumerate)) - { - returnNext = true; - } - } - // End of sequence - - return values.First(); - } - } -} diff --git a/ClipboardCanvas/Extensions/GenericsExtensions.cs b/ClipboardCanvas/Extensions/GenericsExtensions.cs deleted file mode 100644 index eb9f990e..00000000 --- a/ClipboardCanvas/Extensions/GenericsExtensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ClipboardCanvas.Extensions -{ - public static class GenericsExtensions - { - /// - /// Converts given to provided - /// - /// The generic type to convert to - /// The type to convert from - /// The value - /// - /// The must implement - /// - /// Converted - public static TRequested ConvertValue(this TSource value) => - (TRequested)Convert.ChangeType(value, typeof(TRequested)); - - /// - /// Compares two generic types - /// - /// - /// The first value - /// The second value - /// true if both and are equal, otherwise false - public static bool GenericEquals(this T value1, T value2) => - EqualityComparer.Default.Equals(value1, value2); - - /// - /// Determines whether is null - /// - /// - /// - /// if is null, otherwise false - public static bool IsNull(this T value) => GenericEquals(value, default); - } -} diff --git a/ClipboardCanvas/Extensions/LinqExtensions.cs b/ClipboardCanvas/Extensions/LinqExtensions.cs deleted file mode 100644 index 55781dbd..00000000 --- a/ClipboardCanvas/Extensions/LinqExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Linq; -using System.Collections.Generic; -using System.Collections; - -namespace ClipboardCanvas.Extensions -{ - public static class LinqExtensions - { - /// - /// Determines whether is empty or not. - ///

- /// Remarks: - ///
- /// This function is faster than enumerable.Count() == 0 since it'll only iterate one element instead of all elements. - ///
- /// This function is null-safe. - ///
- /// - /// - /// - public static bool IsEmpty(this IEnumerable enumerable) => enumerable == null || !enumerable.Any(); - - public static bool CheckEveryNotNull(this IEnumerable enumerable) => !(enumerable == null || enumerable.Any((item) => item.IsNull())); - - public static List ToListSingle(this T element) => new List() { element }; - - public static T Next(this IEnumerable enumerable, int currentIndex) => (currentIndex + 1) >= enumerable.Count() ? default : enumerable.ElementAt(currentIndex + 1); - } -} diff --git a/ClipboardCanvas/Extensions/RangeObservableCollection.cs b/ClipboardCanvas/Extensions/RangeObservableCollection.cs deleted file mode 100644 index c77955b6..00000000 --- a/ClipboardCanvas/Extensions/RangeObservableCollection.cs +++ /dev/null @@ -1,670 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; - -#nullable enable -namespace ClipboardCanvas.Extensions -{ - // Licensed to the .NET Foundation under one or more agreements. - // The .NET Foundation licenses this file to you under the MIT license. - - // Source: https://gist.github.com/weitzhandler/65ac9113e31d12e697cb58cd92601091 - // Author: https://gist.github.com/weitzhandler - // The above information was disclosed on 2021.07.14 - - /// - /// Implementation of a dynamic data collection based on generic Collection<T>, - /// implementing INotifyCollectionChanged to notify listeners - /// when items get added, removed or the whole list is refreshed. - /// - public class RangeObservableCollection : ObservableCollection - { - //------------------------------------------------------ - // - // Private Fields - // - //------------------------------------------------------ - - #region Private Fields - [NonSerialized] - private DeferredEventsCollection? _deferredEvents; - #endregion Private Fields - - - //------------------------------------------------------ - // - // Constructors - // - //------------------------------------------------------ - - #region Constructors - /// - /// Initializes a new instance of ObservableCollection that is empty and has default initial capacity. - /// - public RangeObservableCollection() { } - - /// - /// Initializes a new instance of the ObservableCollection class that contains - /// elements copied from the specified collection and has sufficient capacity - /// to accommodate the number of elements copied. - /// - /// The collection whose elements are copied to the new list. - /// - /// The elements are copied onto the ObservableCollection in the - /// same order they are read by the enumerator of the collection. - /// - /// collection is a null reference - public RangeObservableCollection(IEnumerable collection) : base(collection) { } - - /// - /// Initializes a new instance of the ObservableCollection class - /// that contains elements copied from the specified list - /// - /// The list whose elements are copied to the new list. - /// - /// The elements are copied onto the ObservableCollection in the - /// same order they are read by the enumerator of the list. - /// - /// list is a null reference - public RangeObservableCollection(List list) : base(list) { } - - #endregion Constructors - - //------------------------------------------------------ - // - // Public Properties - // - //------------------------------------------------------ - - #region Public Properties - EqualityComparer? _Comparer; - public EqualityComparer Comparer - { - get => _Comparer ??= EqualityComparer.Default; - private set => _Comparer = value; - } - - /// - /// Gets or sets a value indicating whether this collection acts as a , - /// disallowing duplicate items, based on . - /// This might indeed consume background performance, but in the other hand, - /// it will pay off in UI performance as less required UI updates are required. - /// - public bool AllowDuplicates { get; set; } = true; - - #endregion Public Properties - - //------------------------------------------------------ - // - // Public Methods - // - //------------------------------------------------------ - - #region Public Methods - - /// - /// Adds the elements of the specified collection to the end of the . - /// - /// - /// The collection whose elements should be added to the end of the . - /// The collection itself cannot be null, but it can contain elements that are null, if type T is a reference type. - /// - /// is null. - public void AddRange(IEnumerable collection) - { - InsertRange(Count, collection); - } - - /// - /// Inserts the elements of a collection into the at the specified index. - /// - /// The zero-based index at which the new elements should be inserted. - /// The collection whose elements should be inserted into the List. - /// The collection itself cannot be null, but it can contain elements that are null, if type T is a reference type. - /// is null. - /// is not in the collection range. - public void InsertRange(int index, IEnumerable collection) - { - if (collection == null) - throw new ArgumentNullException(nameof(collection)); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - if (index > Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - if (!AllowDuplicates) - collection = - collection - .Distinct(Comparer) - .Where(item => !Items.Contains(item, Comparer)) - .ToList(); - - if (collection is ICollection countable) - { - if (countable.Count == 0) - return; - } - else if (!collection.Any()) - return; - - CheckReentrancy(); - - //expand the following couple of lines when adding more constructors. - var target = (List)Items; - target.InsertRange(index, collection); - - OnEssentialPropertiesChanged(); - - if (!(collection is IList list)) - list = new List(collection); - - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, list, index)); - } - - /// - /// Removes the first occurence of each item in the specified collection from the . - /// - /// The items to remove. - /// is null. - public void RemoveRange(IEnumerable collection) - { - if (collection == null) - throw new ArgumentNullException(nameof(collection)); - - if (Count == 0) - return; - else if (collection is ICollection countable) - { - if (countable.Count == 0) - return; - else if (countable.Count == 1) - using (IEnumerator enumerator = countable.GetEnumerator()) - { - enumerator.MoveNext(); - Remove(enumerator.Current); - return; - } - } - else if (!collection.Any()) - return; - - CheckReentrancy(); - - var clusters = new Dictionary>(); - var lastIndex = -1; - List? lastCluster = null; - foreach (T item in collection) - { - var index = IndexOf(item); - if (index < 0) - continue; - - Items.RemoveAt(index); - - if (lastIndex == index && lastCluster != null) - lastCluster.Add(item); - else - clusters[lastIndex = index] = lastCluster = new List { item }; - } - - OnEssentialPropertiesChanged(); - - if (Count == 0) - OnCollectionReset(); - else - foreach (KeyValuePair> cluster in clusters) - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, cluster.Value, cluster.Key)); - - } - - /// - /// Iterates over the collection and removes all items that satisfy the specified match. - /// - /// The complexity is O(n). - /// - /// Returns the number of elements that where - /// is null. - public int RemoveAll(Predicate match) - { - return RemoveAll(0, Count, match); - } - - /// - /// Iterates over the specified range within the collection and removes all items that satisfy the specified match. - /// - /// The complexity is O(n). - /// The index of where to start performing the search. - /// The number of items to iterate on. - /// - /// Returns the number of elements that where - /// is out of range. - /// is out of range. - /// is null. - public int RemoveAll(int index, int count, Predicate match) - { - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - if (index + count > Count) - throw new ArgumentOutOfRangeException(nameof(index)); - if (match == null) - throw new ArgumentNullException(nameof(match)); - - if (Count == 0) - return 0; - - List? cluster = null; - var clusterIndex = -1; - var removedCount = 0; - - using (BlockReentrancy()) - using (DeferEvents()) - { - for (var i = 0; i < count; i++, index++) - { - T item = Items[index]; - if (match(item)) - { - Items.RemoveAt(index); - removedCount++; - - if (clusterIndex == index) - { - Debug.Assert(cluster != null); - cluster!.Add(item); - } - else - { - cluster = new List { item }; - clusterIndex = index; - } - - index--; - } - else if (clusterIndex > -1) - { - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, cluster, clusterIndex)); - clusterIndex = -1; - cluster = null; - } - } - - if (clusterIndex > -1) - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, cluster, clusterIndex)); - } - - if (removedCount > 0) - OnEssentialPropertiesChanged(); - - return removedCount; - } - - /// - /// Removes a range of elements from the >. - /// - /// The zero-based starting index of the range of elements to remove. - /// The number of elements to remove. - /// The specified range is exceeding the collection. - public void RemoveRange(int index, int count) - { - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - if (index + count > Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - if (count == 0) - return; - - if (count == 1) - { - RemoveItem(index); - return; - } - - //Items will always be List, see constructors - var items = (List)Items; - List removedItems = items.GetRange(index, count); - - CheckReentrancy(); - - items.RemoveRange(index, count); - - OnEssentialPropertiesChanged(); - - if (Count == 0) - OnCollectionReset(); - else - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removedItems, index)); - } - - /// - /// Clears the current collection and replaces it with the specified collection, - /// using . - /// - /// The items to fill the collection with, after clearing it. - /// is null. - public void ReplaceRange(IEnumerable collection) - { - ReplaceRange(0, Count, collection); - } - - /// - /// Removes the specified range and inserts the specified collection in its position, leaving equal items in equal positions intact. - /// - /// The index of where to start the replacement. - /// The number of items to be replaced. - /// The collection to insert in that location. - /// is out of range. - /// is out of range. - /// is null. - /// is null. - public void ReplaceRange(int index, int count, IEnumerable collection) - { - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - if (index + count > Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - if (collection == null) - throw new ArgumentNullException(nameof(collection)); - - if (!AllowDuplicates) - collection = - collection - .Distinct(Comparer) - .ToList(); - - if (collection is ICollection countable) - { - if (countable.Count == 0) - { - RemoveRange(index, count); - return; - } - } - else if (!collection.Any()) - { - RemoveRange(index, count); - return; - } - - if (index + count == 0) - { - InsertRange(0, collection); - return; - } - - if (!(collection is IList list)) - list = new List(collection); - - using (BlockReentrancy()) - using (DeferEvents()) - { - var rangeCount = index + count; - var addedCount = list.Count; - - var changesMade = false; - List? - newCluster = null, - oldCluster = null; - - - int i = index; - for (; i < rangeCount && i - index < addedCount; i++) - { - //parallel position - T old = this[i], @new = list[i - index]; - if (Comparer.Equals(old, @new)) - { - OnRangeReplaced(i, newCluster!, oldCluster!); - continue; - } - else - { - Items[i] = @new; - - if (newCluster == null) - { - Debug.Assert(oldCluster == null); - newCluster = new List { @new }; - oldCluster = new List { old }; - } - else - { - newCluster.Add(@new); - oldCluster!.Add(old); - } - - changesMade = true; - } - } - - OnRangeReplaced(i, newCluster!, oldCluster!); - - //exceeding position - if (count != addedCount) - { - var items = (List)Items; - if (count > addedCount) - { - var removedCount = rangeCount - addedCount; - T[] removed = new T[removedCount]; - items.CopyTo(i, removed, 0, removed.Length); - items.RemoveRange(i, removedCount); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed, i)); - } - else - { - var k = i - index; - T[] added = new T[addedCount - k]; - for (int j = k; j < addedCount; j++) - { - T @new = list[j]; - added[j - k] = @new; - } - items.InsertRange(i, added); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added, i)); - } - - OnEssentialPropertiesChanged(); - } - else if (changesMade) - { - OnIndexerPropertyChanged(); - } - } - } - - #endregion Public Methods - - - //------------------------------------------------------ - // - // Protected Methods - // - //------------------------------------------------------ - - #region Protected Methods - - /// - /// Called by base class Collection<T> when the list is being cleared; - /// raises a CollectionChanged event to any listeners. - /// - protected override void ClearItems() - { - if (Count == 0) - return; - - CheckReentrancy(); - base.ClearItems(); - OnEssentialPropertiesChanged(); - OnCollectionReset(); - } - - /// - protected override void InsertItem(int index, T item) - { - if (!AllowDuplicates && Items.Contains(item)) - return; - - base.InsertItem(index, item); - } - - /// - protected override void SetItem(int index, T item) - { - if (AllowDuplicates) - { - if (Comparer.Equals(this[index], item)) - return; - } - else - if (Items.Contains(item, Comparer)) - return; - - CheckReentrancy(); - T oldItem = this[index]; - base.SetItem(index, item); - - OnIndexerPropertyChanged(); - OnCollectionChanged(NotifyCollectionChangedAction.Replace, oldItem!, item!, index); - } - - /// - /// Raise CollectionChanged event to any listeners. - /// Properties/methods modifying this ObservableCollection will raise - /// a collection changed event through this virtual method. - /// - /// - /// When overriding this method, either call its base implementation - /// or call to guard against reentrant collection changes. - /// - protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) - { - if (_deferredEvents != null) - { - _deferredEvents.Add(e); - return; - } - base.OnCollectionChanged(e); - } - - protected virtual IDisposable DeferEvents() => new DeferredEventsCollection(this); - - #endregion Protected Methods - - - //------------------------------------------------------ - // - // Private Methods - // - //------------------------------------------------------ - - #region Private Methods - - /// - /// Helper to raise Count property and the Indexer property. - /// - void OnEssentialPropertiesChanged() - { - OnPropertyChanged(EventArgsCache.CountPropertyChanged); - OnIndexerPropertyChanged(); - } - - /// - /// /// Helper to raise a PropertyChanged event for the Indexer property - /// /// - void OnIndexerPropertyChanged() => - OnPropertyChanged(EventArgsCache.IndexerPropertyChanged); - - /// - /// Helper to raise CollectionChanged event to any listeners - /// - void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index) => - OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index)); - - /// - /// Helper to raise CollectionChanged event with action == Reset to any listeners - /// - void OnCollectionReset() => - OnCollectionChanged(EventArgsCache.ResetCollectionChanged); - - /// - /// Helper to raise event for clustered action and clear cluster. - /// - /// The index of the item following the replacement block. - /// - /// - //TODO should have really been a local method inside ReplaceRange(int index, int count, IEnumerable collection, IEqualityComparer comparer), - //move when supported language version updated. - void OnRangeReplaced(int followingItemIndex, ICollection newCluster, ICollection oldCluster) - { - if (oldCluster == null || oldCluster.Count == 0) - { - Debug.Assert(newCluster == null || newCluster.Count == 0); - return; - } - - OnCollectionChanged( - new NotifyCollectionChangedEventArgs( - NotifyCollectionChangedAction.Replace, - new List(newCluster), - new List(oldCluster), - followingItemIndex - oldCluster.Count)); - - oldCluster.Clear(); - newCluster.Clear(); - } - - #endregion Private Methods - - //------------------------------------------------------ - // - // Private Types - // - //------------------------------------------------------ - - #region Private Types - sealed class DeferredEventsCollection : List, IDisposable - { - readonly RangeObservableCollection _collection; - public DeferredEventsCollection(RangeObservableCollection collection) - { - Debug.Assert(collection != null); - Debug.Assert(collection._deferredEvents == null); - _collection = collection; - _collection._deferredEvents = this; - } - - public void Dispose() - { - _collection._deferredEvents = null; - foreach (var args in this) - _collection.OnCollectionChanged(args); - } - } - - #endregion Private Types - - } - - /// - /// To be kept outside , since otherwise, a new instance will be created for each generic type used. - /// - internal static class EventArgsCache - { - internal static readonly PropertyChangedEventArgs CountPropertyChanged = new PropertyChangedEventArgs("Count"); - internal static readonly PropertyChangedEventArgs IndexerPropertyChanged = new PropertyChangedEventArgs("Item[]"); - internal static readonly NotifyCollectionChangedEventArgs ResetCollectionChanged = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset); - } -} diff --git a/ClipboardCanvas/Extensions/SafetyExtensions.cs b/ClipboardCanvas/Extensions/SafetyExtensions.cs deleted file mode 100644 index 75dc5cec..00000000 --- a/ClipboardCanvas/Extensions/SafetyExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using ClipboardCanvas.UnsafeNative; -using Microsoft.Win32.SafeHandles; -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace ClipboardCanvas.Extensions -{ - public static class SafetyExtensions - { - public static T PreventNull(this T element, T defaultValue, bool throwOnNullDefaultValue = true) - { - if (element.IsNull()) // Is null - { - if (defaultValue.IsNull() && throwOnNullDefaultValue) // Default value is null - { - Debugger.Break(); - throw new NullReferenceException($"[PreventNull] Provided defautValue was null! Type: {typeof(T)}"); - } - else - { - return defaultValue; - } - } - else - { - return element; - } - } - - public static TSafeHandle ToSafeHandle(this IntPtr unsafeHandle, Func createSafeHandle) where TSafeHandle : SafeHandle => - createSafeHandle(unsafeHandle); - - public static SafeFileHandle ToSafeFileHandle(this IntPtr unsafeHandle, bool ownsHandle = true) => - ToSafeHandle(unsafeHandle, (h) => new SafeFileHandle(h, ownsHandle)); - - public static bool CloseFileHandle(this IntPtr unsafeFileHandle) => - UnsafeNativeApis.CloseHandle(unsafeFileHandle); - } -} diff --git a/ClipboardCanvas/Extensions/StringExtensions.cs b/ClipboardCanvas/Extensions/StringExtensions.cs deleted file mode 100644 index 0515b746..00000000 --- a/ClipboardCanvas/Extensions/StringExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ClipboardCanvas.Extensions -{ - public static class StringExtensions - { - public static string FirstToUpper(this string str) - { - return $"{str[0].ToString().ToUpper()}{str.Substring(1, str.Length - 1)}"; - } - } -} diff --git a/ClipboardCanvas/Extensions/TaskExtensions.cs b/ClipboardCanvas/Extensions/TaskExtensions.cs deleted file mode 100644 index 0e859a48..00000000 --- a/ClipboardCanvas/Extensions/TaskExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Extensions -{ - public static class TaskExtensions - { - public static async Task> WaitAll(this IEnumerable> tasks) - { - IList results = new List(); - - foreach (var task in tasks) - { - results.Add(await task); - } - - return results; - } - } -} diff --git a/ClipboardCanvas/GlobalizationExtensions/LocalizationExtensions.cs b/ClipboardCanvas/GlobalizationExtensions/LocalizationExtensions.cs deleted file mode 100644 index 23b96c1d..00000000 --- a/ClipboardCanvas/GlobalizationExtensions/LocalizationExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Windows.UI; -using Windows.ApplicationModel.Resources; - -namespace ClipboardCanvas.GlobalizationExtensions -{ - public static class LocalizationExtensions - { - private static readonly ResourceLoader IndependentLoader; - - static LocalizationExtensions() - { - IndependentLoader = ResourceLoader.GetForViewIndependentUse(); - } - - public static string GetLocalized2(this string resourceKey, UIContext uiContext = null) - { - if (Constants.UI.USE_GETLOCALIZED2) - { - return GetLocalized2Internal(resourceKey, uiContext); - } - else - { - return CommunityToolkit.WinUI.StringExtensions.GetLocalized(resourceKey); - } - } - - private static string GetLocalized2Internal(this string resourceKey, UIContext uiContext = null) - { - if (uiContext is not null) - { - return ResourceLoader.GetForUIContext(uiContext).GetString(resourceKey); - } - - return IndependentLoader?.GetString(resourceKey); - } - } -} diff --git a/ClipboardCanvas/GlobalizationExtensions/ResourceString.cs b/ClipboardCanvas/GlobalizationExtensions/ResourceString.cs deleted file mode 100644 index d90b0a19..00000000 --- a/ClipboardCanvas/GlobalizationExtensions/ResourceString.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Windows.ApplicationModel.Resources; -using Microsoft.UI.Xaml.Markup; - -namespace ClipboardCanvas.GlobalizationExtensions -{ - [MarkupExtensionReturnType(ReturnType = typeof(string))] - public sealed class ResourceString : MarkupExtension - { - private static readonly ResourceLoader ResourceLoader = new ResourceLoader(); - - public string Name { get; set; } - - protected override object ProvideValue() - { - return ResourceLoader.GetString(Name); - } - } -} diff --git a/ClipboardCanvas/Helpers/AdaptiveActionsHelpers.cs b/ClipboardCanvas/Helpers/AdaptiveActionsHelpers.cs deleted file mode 100644 index b5ff9447..00000000 --- a/ClipboardCanvas/Helpers/AdaptiveActionsHelpers.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Collections.Generic; -using CommunityToolkit.Mvvm.Input; -using Windows.ApplicationModel.DataTransfer; -using System.Threading; - -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ViewModels.UserControls; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.ViewModels.UserControls.CanvasPreview; - -namespace ClipboardCanvas.Helpers -{ - public static class SuggestedActionsHelpers - { - public static IEnumerable GetActionsForInvalidReference(ICanvasPreviewModel pasteCanvasModel) - { - List actions = new List(); - - var action_deleteReference = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - await pasteCanvasModel.TryDeleteData(true); - }), "DeleteReference".GetLocalized2(), "\uE738"); - - actions.Add(action_deleteReference); - - return actions; - } - - public static IEnumerable GetActionsForEmptyCanvasPage(ICanvasPreviewModel pasteCanvasControlModel) - { - List actions = new List(); - - var action_paste = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - BaseReadOnlyCanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource.Cancel(); - BaseReadOnlyCanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource = new CancellationTokenSource(); - - SafeWrapper dataPackage = ClipboardHelpers.GetClipboardData(); - - await pasteCanvasControlModel.TryPasteData(dataPackage, BaseReadOnlyCanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource.Token); - }), "PasteFromClipboard".GetLocalized2(), "\uE77F"); - - actions.Add(action_paste); - - return actions; - } - - public static IEnumerable GetActionsForHomepage() - { - List actions = new List(); - - var action_addCollection = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - await CollectionsWidgetViewModel.AddCollectionViaUi(); - }), "AddCollection".GetLocalized2(), "\uE710"); - - actions.Add(action_addCollection); - - return actions; - } - - public static IEnumerable GetActionsForCollectionPreviewPage() - { - List actions = new List(); - - return actions; - } - } -} diff --git a/ClipboardCanvas/Helpers/AnimationHelpers.cs b/ClipboardCanvas/Helpers/AnimationHelpers.cs deleted file mode 100644 index f8749eef..00000000 --- a/ClipboardCanvas/Helpers/AnimationHelpers.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.UI.Xaml.Media.Animation; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Helpers -{ - public static class AnimationHelpers - { - public static NavigationTransitionInfo ToNavigationTransition(this NavigationTransitionType transitionType) - { - switch (transitionType) - { - default: - case NavigationTransitionType.Suppress: - return new SuppressNavigationTransitionInfo(); - - case NavigationTransitionType.DrillInTransition: - return new DrillInNavigationTransitionInfo(); - - case NavigationTransitionType.EntranceTransition: - return new EntranceNavigationTransitionInfo(); - } - } - } -} diff --git a/ClipboardCanvas/Helpers/ApplicationHelpers.cs b/ClipboardCanvas/Helpers/ApplicationHelpers.cs deleted file mode 100644 index 276213df..00000000 --- a/ClipboardCanvas/Helpers/ApplicationHelpers.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Windows.ApplicationModel; -using Windows.Foundation; -using Windows.Services.Store; -using Windows.Storage; -using Windows.Storage.Streams; -using Windows.System; -using Microsoft.UI.Xaml.Media.Imaging; -using ClipboardCanvas.Extensions; - -namespace ClipboardCanvas.Helpers -{ - public static class ApplicationHelpers - { - [Obsolete] - public static async Task<(BitmapImage icon, string appName)> GetIconFromFileHandlingApp(StorageFile file, string fileExtension) - { - IReadOnlyList apps = await Launcher.FindFileHandlersAsync(fileExtension); - - AppInfo app = apps.FirstOrDefault(); - - if (app == null) - { - return (null, null); - } - - RandomAccessStreamReference stream = app.DisplayInfo.GetLogo(new Size(256, 256)); - - BitmapImage bitmap = await ImagingHelpers.ToBitmapAsync(await stream.OpenReadAsync()); - - return (bitmap, app.DisplayInfo.DisplayName); - } - - public static async Task IsStoreUpdateAvailable() - { - try - { - IReadOnlyList updates = await StoreContext.GetDefault().GetAppAndOptionalStorePackageUpdatesAsync(); - - return !updates.IsEmpty(); - } - catch - { - return false; - } - } - } -} diff --git a/ClipboardCanvas/Helpers/CanvasHelpers.cs b/ClipboardCanvas/Helpers/CanvasHelpers.cs deleted file mode 100644 index cd38814e..00000000 --- a/ClipboardCanvas/Helpers/CanvasHelpers.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Windows.Storage; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.Services; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.ViewModels.Widgets.Timeline; - -namespace ClipboardCanvas.Helpers -{ - public static class CanvasHelpers - { - public static async Task DeleteCanvasFile(ICanvasItemReceiverModel canvasItemReceiverModel, CanvasItem canvasItem, bool hideConfirmation = false) - { - if (canvasItemReceiverModel == null || canvasItem == null) - { - return new SafeWrapperResult(OperationErrorCode.InvalidArgument, new NullReferenceException(), $"{nameof(canvasItemReceiverModel)} or/and {nameof(canvasItem)} were null."); - } - - IUserSettingsService userSettingsService = Ioc.Default.GetService(); - - bool deletePermanently = userSettingsService.DeletePermanentlyAsDefault; - if (userSettingsService.ShowDeleteConfirmationDialog && !hideConfirmation) - { - IDialogService dialogService = Ioc.Default.GetService(); - - DeleteConfirmationDialogViewModel deleteConfirmationDialogViewModel = new DeleteConfirmationDialogViewModel(Path.GetFileName(canvasItem.AssociatedItem.Path), deletePermanently); - DialogResult dialogOption = await dialogService.ShowDialog(deleteConfirmationDialogViewModel); - - if (dialogOption != DialogResult.Primary) - { - return SafeWrapperResult.CANCEL; - } - - deletePermanently = deleteConfirmationDialogViewModel.PermanentlyDelete; - } - else if (hideConfirmation) - { - deletePermanently = true; - } - - // Also remove it from Timeline - ITimelineService timelineService = Ioc.Default.GetService(); - (TimelineSectionViewModel section, TimelineSectionItemViewModel sectionItem) = timelineService.FindTimelineSectionItem(canvasItem); - if (section != null && sectionItem != null) - { - timelineService.RemoveItemFromSection(section, sectionItem); - } - - // Delete! - return await canvasItemReceiverModel.DeleteItem(canvasItem.AssociatedItem, deletePermanently); - } - - public static CanvasType GetDefaultCanvasType() - { - IUserSettingsService userSettings = Ioc.Default.GetService(); - - if (userSettings.UseInfiniteCanvasAsDefault) - { - return CanvasType.InfiniteCanvas; - } - else - { - return CanvasType.OneCanvas; - } - } - - public static IPasteModel GetPasteModelFromContentType(this BaseContentTypeModel contentType, ICanvasItemReceiverModel canvasItemReceiverModel, IOperationContextReceiver operationContextReceiver) - { - switch (contentType) - { - case ImageContentType: - return new ImagePasteModel(canvasItemReceiverModel, operationContextReceiver); - - case TextContentType: - return new TextPasteModel(canvasItemReceiverModel, operationContextReceiver); - - case MediaContentType: - return new MediaPasteModel(canvasItemReceiverModel, operationContextReceiver); - - case MarkdownContentType: - return new MarkdownPasteModel(canvasItemReceiverModel, operationContextReceiver); - - case WebViewContentType webViewContentType: - return new WebViewPasteModel(webViewContentType.mode, canvasItemReceiverModel, operationContextReceiver); - - case UrlPreviewContentType: - return new UrlPasteModel(canvasItemReceiverModel, operationContextReceiver); - - default: - case FallbackContentType: - return new FallbackPasteModel(canvasItemReceiverModel, operationContextReceiver); - } - } - - public static async Task> PasteOverrideReference(CanvasItem canvasItem, ICanvasItemReceiverModel canvasItemReceiverModel, IOperationContextReceiver operationContextReceiver) - { - if (await canvasItem.SourceItem == null) - { - return (null, BaseReadOnlyCanvasViewModel.ReferencedFileNotFoundResult); - } - - IStorageItem savedSourceItem = await canvasItem.SourceItem; - - // Create new empty file - string fileName = (await canvasItem.SourceItem).Name; - SafeWrapper newCanvasItemResult = await canvasItemReceiverModel.CreateNewCanvasItem(fileName); - if (!newCanvasItemResult) - { - return newCanvasItemResult; - } - - CanvasItem newCanvasItem = newCanvasItemResult.Result; - - // Copy item - SafeWrapperResult copyResult = await FilesystemOperations.CopyFileAsync(savedSourceItem as StorageFile, newCanvasItem.AssociatedItem as StorageFile, operationContextReceiver.GetOperationContext("Overriding Reference", StatusCenterOperationType.OverrideReference)); - if (!copyResult) - { - // Failed - return (canvasItem, copyResult); - } - - // Delete reference file - SafeWrapperResult deletionResult = await canvasItemReceiverModel.DeleteItem(canvasItem.AssociatedItem, true); - if (!deletionResult) - { - return (canvasItem, deletionResult); - } - - return (newCanvasItem, SafeWrapperResult.SUCCESS); - } - - public static async Task SafeGetCanvasItemPath(CanvasItem canvasItem) - { - if (canvasItem == null || canvasItem.SourceItem == null) - { - return "Invalid file"; - } - - IStorageItem sourceItem = await canvasItem.SourceItem; - - return sourceItem != null ? sourceItem.Path : (canvasItem.AssociatedItem != null ? canvasItem.AssociatedItem.Path : "Invalid file"); - } - } -} diff --git a/ClipboardCanvas/Helpers/ClipboardHelpers.cs b/ClipboardCanvas/Helpers/ClipboardHelpers.cs deleted file mode 100644 index 7c26c474..00000000 --- a/ClipboardCanvas/Helpers/ClipboardHelpers.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using System.Threading.Tasks; -using System; -using System.Collections.Generic; -using Windows.Storage; -using Windows.Storage.Streams; -using System.Linq; - -namespace ClipboardCanvas.Helpers -{ - public static class ClipboardHelpers - { - private static readonly object clipboardLock = new object(); - - public static void CopyDataPackage(DataPackage data) - { - if (data != null) - { - lock (clipboardLock) - { - data.RequestedOperation = DataPackageOperation.Copy; - Clipboard.SetContent(data); - Clipboard.Flush(); - } - } - } - - public static SafeWrapper GetClipboardData() - { - return SafeWrapperRoutines.SafeWrap(Clipboard.GetContent); - } - - public static async Task> SafeGetTextAsync(this DataPackageView dataPackage) - { - // TODO: Add dataPackage.RequestAccessAsync() - return await SafeWrapperRoutines.SafeWrapAsync(() => dataPackage.GetTextAsync().AsTask()); - } - - public static async Task>> SafeGetStorageItemsAsync(this DataPackageView dataPackage) - { - return await SafeWrapperRoutines.SafeWrapAsync(() => dataPackage.GetStorageItemsAsync().AsTask()); - } - - public static async Task> SafeGetBitmapAsync(this DataPackageView dataPackage) - { - return await SafeWrapperRoutines.SafeWrapAsync(() => dataPackage.GetBitmapAsync().AsTask()); - } - - public static async Task> SafeGetUriAsync(this DataPackageView dataPackage) - { - return await SafeWrapperRoutines.SafeWrapAsync(() => dataPackage.GetUriAsync().AsTask()); - } - } -} diff --git a/ClipboardCanvas/Helpers/DebugHelpers.cs b/ClipboardCanvas/Helpers/DebugHelpers.cs deleted file mode 100644 index ec263de6..00000000 --- a/ClipboardCanvas/Helpers/DebugHelpers.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Helpers -{ - public static class DebugHelpers - { - public static void PrintEnumerable(this IEnumerable enumerable) - { -#if !DEBUG - return; -#endif - - foreach (var item in enumerable) - { - Debug.WriteLine(item); - } - } - } -} diff --git a/ClipboardCanvas/Helpers/DialogHelpers.cs b/ClipboardCanvas/Helpers/DialogHelpers.cs deleted file mode 100644 index 1c8e6694..00000000 --- a/ClipboardCanvas/Helpers/DialogHelpers.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml; -using System.Linq; - -using ClipboardCanvas.Enums; -using System.Collections.Generic; -using Microsoft.UI.Xaml.Controls.Primitives; - -namespace ClipboardCanvas.Helpers -{ - public static class DialogHelpers - { - public static DialogResult ToDialogResult(this ContentDialogResult contentDialogResult) - { - switch (contentDialogResult) - { - case ContentDialogResult.Primary: - return DialogResult.Primary; - - case ContentDialogResult.Secondary: - return DialogResult.Secondary; - - default: - case ContentDialogResult.None: - return DialogResult.Cancel; - } - } - - public static bool IsAnyContentDialogOpen() - { - var openedDialogs = VisualTreeHelper.GetOpenPopups(MainWindow.Instance); - return openedDialogs.Any((item) => item.Child is ContentDialog); - } - - public static void CloseCurrentDialog() - { - var openedDialogs = VisualTreeHelper.GetOpenPopups(MainWindow.Instance); - - foreach (var item in openedDialogs) - { - if (item.Child is ContentDialog dialog) - { - dialog.Hide(); - } - } - } - } -} diff --git a/ClipboardCanvas/Helpers/DoubleClickWrapper.cs b/ClipboardCanvas/Helpers/DoubleClickWrapper.cs deleted file mode 100644 index 033d8b6d..00000000 --- a/ClipboardCanvas/Helpers/DoubleClickWrapper.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using Microsoft.UI.Xaml; - -namespace ClipboardCanvas.Helpers -{ - /// - /// A wrapper for click event to implement double click - /// - public class DoubleClickWrapper : IDisposable - { - private readonly TimeSpan _timeBetweenClicks; - - private readonly DispatcherTimer _timer; - - private Action _doubleClickAction; - - private bool _canExecute; - - public DoubleClickWrapper(Action doubleClickAction, TimeSpan timeBetweenClicks) - { - this._doubleClickAction = doubleClickAction; - this._timeBetweenClicks = timeBetweenClicks; - - this._timer = new DispatcherTimer(); - this._timer.Interval = _timeBetweenClicks; - this._timer.Tick += Timer_Tick; - this._timer.Start(); - } - - private void Timer_Tick(object sender, object e) - { - _canExecute = false; - _timer.Stop(); - } - - /// - /// The click action to signalize the click to the wrapper - /// - public void Click() - { - _timer.Start(); - - if (_canExecute) - { - _doubleClickAction?.Invoke(); - } - else - { - _canExecute = true; - } - } - - public void Dispose() - { - this._doubleClickAction = null; - - this._timer.Stop(); - this._timer.Tick -= Timer_Tick; - } - } -} diff --git a/ClipboardCanvas/Helpers/Filesystem/DangerousStorageFileExtensions.cs b/ClipboardCanvas/Helpers/Filesystem/DangerousStorageFileExtensions.cs deleted file mode 100644 index 5efb7da8..00000000 --- a/ClipboardCanvas/Helpers/Filesystem/DangerousStorageFileExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.Helpers.Filesystem -{ - internal static class DangerousStorageFileExtensions - { - internal static async Task DangerousGetStorageFolder(string path) - { - StorageFolder dangerousFolder = await StorageFolder.GetFolderFromPathAsync(path); - - return dangerousFolder; - } - - internal static async Task DangerousGetStorageFile(string path) - { - StorageFile dangerousFile = await StorageFile.GetFileFromPathAsync(path); - - return dangerousFile; - } - } -} diff --git a/ClipboardCanvas/Helpers/Filesystem/FileHelpers.cs b/ClipboardCanvas/Helpers/Filesystem/FileHelpers.cs deleted file mode 100644 index 78a35dbd..00000000 --- a/ClipboardCanvas/Helpers/Filesystem/FileHelpers.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.IO; - -namespace ClipboardCanvas.Helpers.Filesystem -{ - public static class FileHelpers - { - public static bool IsPathEqualExtension(string path, string extension) - { - if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(extension)) - { - return false; - } - - string pathExtension = Path.GetExtension(path); - - return pathExtension.Equals(extension, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/ClipboardCanvas/Helpers/Filesystem/FilesystemOperations.cs b/ClipboardCanvas/Helpers/Filesystem/FilesystemOperations.cs deleted file mode 100644 index 9c6d7fe2..00000000 --- a/ClipboardCanvas/Helpers/Filesystem/FilesystemOperations.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Win32.SafeHandles; -using Windows.Storage; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.UnsafeNative; - -namespace ClipboardCanvas.Helpers.Filesystem -{ - public static class FilesystemOperations - { - public static async Task CopyFileAsync(IStorageFile source, IStorageFile destination, IOperationContext operationContext) - { - long fileSize = await StorageHelpers.GetFileSize(source); - byte[] buffer = new byte[Constants.FileSystem.COPY_FILE_BUFFER_SIZE]; - - SafeWrapperResult result = SafeWrapperResult.SUCCESS; - - operationContext?.StartOperation(); - - SafeFileHandle hFileSource = source.CreateSafeFileHandle(FileAccess.Read); - SafeFileHandle hFileDestination = destination.CreateSafeFileHandle(FileAccess.ReadWrite); - - if (hFileSource.IsInvalid || hFileDestination.IsInvalid) - { - return SafeWrapperResult.UNKNOWN_FAIL; - } - - using (Stream sourceStream = new FileStream(hFileSource, FileAccess.Read)) - { - using (Stream destinationStream = new FileStream(hFileDestination, FileAccess.ReadWrite)) - { - long bytesTransferred = 0L; - int currentBlockSize = 0; - - while ((currentBlockSize = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) > 0) - { - bytesTransferred += currentBlockSize; - float percentage = (float)bytesTransferred * 100.0f / (float)fileSize; - - await destinationStream.WriteAsync(buffer, 0, currentBlockSize); - operationContext?.OperationProgress?.Report(percentage); - - if (operationContext?.CancellationToken.IsCancellationRequested ?? false) - { - result = SafeWrapperResult.CANCEL; - - // Delete copied file if it was canceled - await DeleteItem(destination, true); - - break; - } - } - } - } - - operationContext?.FinishOperation(result); - - return result; - } - - public static async Task> ReadFileText(IStorageFile file) - { - if (file == null) - { - return (null, new SafeWrapperResult(OperationErrorCode.InvalidArgument, new NullReferenceException(), "Provided file is null.")); - } - - SafeWrapper result = await SafeWrapperRoutines.SafeWrapAsync(() => FileIO.ReadTextAsync(file).AsTask()); - - return result; - } - - public static async Task WriteFileText(IStorageFile file, string text) - { - if (file == null) - { - return new SafeWrapperResult(OperationErrorCode.InvalidArgument, new NullReferenceException(), "Provided file is null."); - } - - SafeWrapperResult result = await SafeWrapperRoutines.SafeWrapAsync(() => FileIO.WriteTextAsync(file, text).AsTask()); - - return result; - } - - public static string ReadFileTexth(string path) - { - return UnsafeNativeHelpers.ReadStringFromFile(path); - } - - public static bool WriteFileTexth(string path, string text) - { - return UnsafeNativeHelpers.WriteStringToFile(path, text); - } - - public static async Task RenameItem(IStorageItem item, string newName, NameCollisionOption collision = NameCollisionOption.GenerateUniqueName) - { - SafeWrapperResult result = await SafeWrapperRoutines.SafeWrapAsync(async () => await item.RenameAsync(newName, collision).AsTask()); - return result; - } - - public static async Task DeleteItem(IStorageItem item, bool permanently = false) - { - if (item == null) - { - return new SafeWrapperResult(OperationErrorCode.InvalidArgument, new ArgumentNullException(), "The provided storage item is null."); - } - - SafeWrapperResult result = await SafeWrapperRoutines.SafeWrapAsync( - () => item.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask()); - - return result; - } - - public static async Task> CreateFile(string path, CreationCollisionOption collision = CreationCollisionOption.GenerateUniqueName) - { - string parentFolderPath = Path.GetDirectoryName(path); - SafeWrapper parentFolder = await StorageHelpers.ToStorageItemWithError(parentFolderPath); - - if (!parentFolder) - { - return new SafeWrapper(null, parentFolder.Details); - } - - string fileName = RemoveIllegalFileNameCharacters(Path.GetFileName(path)); - - return await CreateFile(parentFolder, fileName, collision); - } - - public static async Task> CreateFile(StorageFolder parentFolder, string fileName, CreationCollisionOption collision = CreationCollisionOption.GenerateUniqueName) - { - if (parentFolder == null) - { - return new SafeWrapper(null, OperationErrorCode.InvalidArgument, new ArgumentNullException(), "The provided folder is null."); - } - - return await SafeWrapperRoutines.SafeWrapAsync(() => parentFolder.CreateFileAsync(RemoveIllegalFileNameCharacters(fileName), collision).AsTask()); - } - - public static async Task> CreateFolder(string path, CreationCollisionOption collision = CreationCollisionOption.GenerateUniqueName) - { - string parentFolderPath = Path.GetDirectoryName(path); - SafeWrapper parentFolder = await StorageHelpers.ToStorageItemWithError(parentFolderPath); - - if (!parentFolder) - { - return parentFolder; - } - - string folderName = Path.GetFileName(path); - - return await CreateFolder(parentFolder, folderName, collision); - } - - public static async Task> CreateFolder(StorageFolder parentFolder, string name, CreationCollisionOption collision = CreationCollisionOption.GenerateUniqueName) - { - if (parentFolder == null) - { - return new SafeWrapper(null, OperationErrorCode.InvalidArgument, new ArgumentNullException(), "The provided folder is null."); - } - - return await SafeWrapperRoutines.SafeWrapAsync(() => parentFolder.CreateFolderAsync(name, collision).AsTask()); - } - - private static string RemoveIllegalFileNameCharacters(string dangerousFileName) - { - return string.Join("_", dangerousFileName.Split(Path.GetInvalidFileNameChars())); - } - } -} diff --git a/ClipboardCanvas/Helpers/Filesystem/StorageHelpers.cs b/ClipboardCanvas/Helpers/Filesystem/StorageHelpers.cs deleted file mode 100644 index 0b98e41b..00000000 --- a/ClipboardCanvas/Helpers/Filesystem/StorageHelpers.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.FileProperties; -using System.IO; -using CommunityToolkit.Mvvm.DependencyInjection; -using Windows.System; -using Microsoft.Win32.SafeHandles; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.UnsafeNative; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.Helpers.Filesystem -{ - public static class StorageHelpers - { - public static async Task ToStorageItem(string path) where TRequested : IStorageItem - { - return (await ToStorageItemWithError(path)).Result; - } - - public static async Task> ToStorageItemWithError(string path) where TRequested : IStorageItem - { - SafeWrapper file = null; - SafeWrapper folder = null; - - if (string.IsNullOrWhiteSpace(path)) - { - return new SafeWrapper(default, OperationErrorCode.InvalidArgument, new ArgumentException(), "Provided path is either empty or null."); - } - - // Check if path is to .lnk or .url file - if (FileHelpers.IsPathEqualExtension(path, ".lnk") || FileHelpers.IsPathEqualExtension(path, ".url")) - { - return new SafeWrapper(default, OperationErrorCode.InvalidOperation, new InvalidOperationException(), "Function ToStorageItem() does not support converting from .lnk nor .url files."); - } - - // Fast get attributes - bool exists = UnsafeNativeApis.GetFileAttributesExFromApp(path, UnsafeNativeDataModels.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, out UnsafeNativeDataModels.WIN32_FILE_ATTRIBUTE_DATA itemAttributes); - if (!exists) - { - uint hresult = UnsafeNativeApis.GetLastError(); - return new SafeWrapper(default, OperationErrorCode.NotFound, new FileNotFoundException($"The file was not found. Actual HRESULT:{hresult}"), "Couldn't resolve item associated with path."); - } - - // Directory - if (itemAttributes.dwFileAttributes.HasFlag(System.IO.FileAttributes.Directory)) - { - if (typeof(IStorageFile).IsAssignableFrom(typeof(TRequested))) // Wanted file - { - return new SafeWrapper(default, OperationErrorCode.NotAFile, $"The item at path does not match requested type parameter (TRequested: {typeof(TRequested)})"); - } - else // Just get the directory - { - await GetFolder(); - } - } - else // File - { - if (typeof(IStorageFolder).IsAssignableFrom(typeof(TRequested))) // Wanted directory - { - return new SafeWrapper(default, OperationErrorCode.NotAFile, $"The item at path does not match requested type parameter (TRequested: {typeof(TRequested)})"); - } - else // Just get the file - { - await GetFile(); - } - } - - if (file != null && file) - { - return new SafeWrapper((TRequested)(IStorageItem)file.Result, file); - } - else if (folder != null && folder) - { - return new SafeWrapper((TRequested)(IStorageItem)folder.Result, folder); - } - - return file as SafeWrapper ?? (folder as SafeWrapper ?? new SafeWrapper(default, OperationErrorCode.UnknownFailed, "The operation to get file/folder failed all attempts.")); - - - async Task GetFile() - { - file = await SafeWrapperRoutines.SafeWrapAsync(() => DangerousStorageFileExtensions.DangerousGetStorageFile(path)); - } - - async Task GetFolder() - { - folder = await SafeWrapperRoutines.SafeWrapAsync(() => DangerousStorageFileExtensions.DangerousGetStorageFolder(path)); - } - } - - public static FileStream OpenFileStreamh(this IStorageFile file, FileAccess fileAccess = FileAccess.ReadWrite) - { - SafeFileHandle hFile = file.CreateSafeFileHandle(fileAccess); - FileStream fileStream = new FileStream(hFile, fileAccess); - - return fileStream; - } - - public static async Task GetFileSize(this IStorageFile file) - { - if (file == null) - { - return -1L; - } - - BasicProperties properties = await file.GetBasicPropertiesAsync(); - return (long)properties.Size; - } - - public static bool Existsh(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - return false; - } - - return UnsafeNativeApis.GetFileAttributesExFromApp(path, UnsafeNativeDataModels.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, out _); - } - - public static async Task> GetAppSettingsFolder() - { - return await FilesystemOperations.CreateFile(ApplicationData.Current.LocalFolder, Constants.LocalSettings.SETTINGS_FOLDERNAME, CreationCollisionOption.OpenIfExists); - } - - public static async Task> GetCollectionIconsFolder() - { - return await FilesystemOperations.CreateFolder(ApplicationData.Current.LocalFolder, Constants.FileSystem.COLLECTION_ICONS_FOLDERNAME, CreationCollisionOption.OpenIfExists); - } - - public static async Task> GetExceptionLogFile() - { - string exceptionLogFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.FileSystem.EXCEPTIONLOG_FILENAME); - - return await ToStorageItemWithError(exceptionLogFilePath); - } - - public static async Task OpenFile(IStorageItem item) - { - if (item == null) - { - return false; - } - - StorageFile file = item as StorageFile; - if (file != null && FileHelpers.IsPathEqualExtension(item.Path, ".exe")) - { - IDialogService dialogService = Ioc.Default.GetService(); - - IInAppNotification notification = dialogService.GetNotification(); - notification.ViewModel.NotificationText = "UWP cannot open executable (.exe) files"; - notification.ViewModel.ShownButtons = InAppNotificationButtonType.OkButton; - - notification.Show(Constants.UI.Notifications.NOTIFICATION_DEFAULT_SHOW_TIME); - return false; - } - else - { - if (file != null) - { - await Launcher.LaunchFileAsync(file); - return true; - } - else if (item is StorageFolder folder) - { - await Launcher.LaunchFolderAsync(folder); - return true; - } - else - { - return false; - } - } - } - - public static async Task OpenContainingFolder(IStorageItem item) - { - if (item == null) - { - return false; - } - - SafeWrapper parentFolder; - - string parentFolderPath = Path.GetDirectoryName(item.Path); - parentFolder = await StorageHelpers.ToStorageItemWithError(parentFolderPath); - - if (!parentFolder || parentFolder?.Result == null) - { - return false; - } - - FolderLauncherOptions launcherOptions = new FolderLauncherOptions(); - launcherOptions.ItemsToSelect.Add(item); - - await Launcher.LaunchFolderAsync(parentFolder.Result, launcherOptions); - return true; - } - } -} diff --git a/ClipboardCanvas/Helpers/FilesystemChangeWatcher.cs b/ClipboardCanvas/Helpers/FilesystemChangeWatcher.cs deleted file mode 100644 index a44e5b5c..00000000 --- a/ClipboardCanvas/Helpers/FilesystemChangeWatcher.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.Search; - -namespace ClipboardCanvas.Helpers -{ - public sealed class ChangeRegisteredEventArgs : EventArgs - { - public readonly StorageLibraryChangeTracker filesystemChangeTracker; - - public readonly StorageLibraryChangeReader filesystemChangeReader; - - public ChangeRegisteredEventArgs(StorageLibraryChangeTracker filesystemChangeTracker, StorageLibraryChangeReader filesystemChangeReader) - { - this.filesystemChangeTracker = filesystemChangeTracker; - this.filesystemChangeReader = filesystemChangeReader; - } - } - - public sealed class ChangeRegisteredEventArgs2 : EventArgs - { - public string? OldPath { get; } - - public string FullPath { get; } - - public WatcherChangeTypes ChangeType { get; } - - public ChangeRegisteredEventArgs2(string fullPath, WatcherChangeTypes changeType, string oldPath = null) - { - FullPath = fullPath; - ChangeType = changeType; - OldPath = oldPath; - } - } - - public sealed class FilesystemChangeWatcher2 : IDisposable - { - private readonly FileSystemWatcher _fileSystemWatcher; - - public event EventHandler OnChangeRegisteredEvent; - - public FilesystemChangeWatcher2(string path) - { - _fileSystemWatcher = new FileSystemWatcher(path); - _fileSystemWatcher.EnableRaisingEvents = true; - - _fileSystemWatcher.Created += FileSystemWatcher_Created; - _fileSystemWatcher.Deleted += FileSystemWatcher_Deleted; - _fileSystemWatcher.Renamed += FileSystemWatcher_Renamed; - _fileSystemWatcher.Changed += FileSystemWatcher_Changed; - } - - private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e) - { - OnChangeRegisteredEvent?.Invoke(this, new(e.FullPath, e.ChangeType)); - } - - private void FileSystemWatcher_Renamed(object sender, RenamedEventArgs e) - { - OnChangeRegisteredEvent?.Invoke(this, new(e.FullPath, e.ChangeType, e.OldFullPath)); - } - - private void FileSystemWatcher_Deleted(object sender, FileSystemEventArgs e) - { - OnChangeRegisteredEvent?.Invoke(this, new(e.FullPath, e.ChangeType)); - } - - private void FileSystemWatcher_Created(object sender, FileSystemEventArgs e) - { - OnChangeRegisteredEvent?.Invoke(this, new(e.FullPath, e.ChangeType)); - } - - public void Dispose() - { - _fileSystemWatcher.Created -= FileSystemWatcher_Created; - _fileSystemWatcher.Deleted -= FileSystemWatcher_Deleted; - _fileSystemWatcher.Dispose(); - } - } - - public sealed class FilesystemChangeWatcher : IDisposable - { - private bool _isStarted; - - private readonly StorageFolder _watchedFolder; - - private StorageItemQueryResult _filesystemWatcherQuery; - - private StorageLibraryChangeTracker _filesystemChangeTracker; - - private StorageLibraryChangeReader _filesystemChangeReader; - - public event EventHandler OnChangeRegisteredEvent; - - private FilesystemChangeWatcher(StorageFolder watchedFolder) - { - this._watchedFolder = watchedFolder; - } - - public static async Task CreateNew(StorageFolder folderToWatch) - { - var filesystemChangeWatcher = new FilesystemChangeWatcher(folderToWatch); - await filesystemChangeWatcher.StartWatching(); - - return filesystemChangeWatcher; - } - - private async Task StartWatching() - { - try - { - _isStarted = true; - - // 1. Prepare query - listen for changes - QueryOptions queryOptions = new QueryOptions(CommonFolderQuery.DefaultQuery); - queryOptions.FolderDepth = FolderDepth.Shallow; - queryOptions.IndexerOption = IndexerOption.UseIndexerWhenAvailable; - - _filesystemWatcherQuery = _watchedFolder.CreateItemQueryWithOptions(queryOptions); - - // Indicate to the system the app is ready to change track - await _filesystemWatcherQuery.GetItemsAsync(0, 1); - - _filesystemWatcherQuery.ContentsChanged += FilesystemWatcherQuery_ContentsChanged; - - // 2. Get change tracker - _filesystemChangeTracker = _watchedFolder.TryGetChangeTracker(); - _filesystemChangeTracker.Enable(); - - _filesystemChangeReader = _filesystemChangeTracker.GetChangeReader(); - - return true; - } - catch - { - _isStarted = false; - } - - return false; - } - - private async void FilesystemWatcherQuery_ContentsChanged(IStorageQueryResultBase sender, object args) - { - OnChangeRegisteredEvent?.Invoke(this, new ChangeRegisteredEventArgs(_filesystemChangeTracker, _filesystemChangeReader)); - } - - #region IDisposable - - public void Dispose() - { - if (_isStarted) - { - _isStarted = false; - _filesystemWatcherQuery.ContentsChanged -= FilesystemWatcherQuery_ContentsChanged; - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/Helpers/FlyoutHelpers.cs b/ClipboardCanvas/Helpers/FlyoutHelpers.cs deleted file mode 100644 index fbb28199..00000000 --- a/ClipboardCanvas/Helpers/FlyoutHelpers.cs +++ /dev/null @@ -1,113 +0,0 @@ -using ClipboardCanvas.Extensions; -using ClipboardCanvas.ViewModels.ContextMenu; -using System.Collections.Generic; -using Microsoft.UI.Xaml.Controls; - -namespace ClipboardCanvas.Helpers -{ - public class FlyoutHelpers - { - public static IList GetMenuFlyoutItems(IList items) - { - List flyoutItems = new List(); - IList filtered = FilterItems(items); - - foreach (var item in filtered) - { - flyoutItems.Add(GetMenuItem(item)); - } - - return flyoutItems; - } - - public static MenuFlyoutItemBase GetMenuItem(BaseMenuFlyoutItemViewModel item) - { - if (item is MenuFlyoutSeparatorViewModel) - { - return new MenuFlyoutSeparator() - { - Tag = item.Tag, - IsEnabled = item.IsEnabled - }; - } - else - { - return GetFlyoutItem(item); - } - } - - public static MenuFlyoutItemBase GetFlyoutItem(BaseMenuFlyoutItemViewModel item) - { - if (item is MenuFlyoutSubItemViewModel subItemViewModel) - { - MenuFlyoutSubItem flyoutSubItem = new MenuFlyoutSubItem() - { - Text = subItemViewModel.Text, - Tag = subItemViewModel.Tag, - IsEnabled = subItemViewModel.IsEnabled, - Icon = new FontIcon() { Glyph = subItemViewModel.IconGlyph.PreventNull(string.Empty) } - }; - - foreach (var item2 in subItemViewModel.SubItems) - { - flyoutSubItem.Items.Add(GetMenuItem(item2)); - } - - return flyoutSubItem; - } - else - { - return GetStandardItem(item); - } - } - - public static MenuFlyoutItemBase GetStandardItem(BaseMenuFlyoutItemViewModel item) - { - MenuFlyoutItemBase flyoutItem; - - if (item is MenuFlyoutToggleItemViewModel flyoutItemToggleViewModel) - { - flyoutItem = new ToggleMenuFlyoutItem() - { - Command = flyoutItemToggleViewModel.Command, - CommandParameter = flyoutItemToggleViewModel.CommandParameter, - Text = flyoutItemToggleViewModel.Text, - Tag = flyoutItemToggleViewModel.Tag, - IsChecked = flyoutItemToggleViewModel.IsChecked - }; - } - else - { - MenuFlyoutItemViewModel flyoutItemViewModel = item as MenuFlyoutItemViewModel; - - flyoutItem = new MenuFlyoutItem() - { - Command = flyoutItemViewModel.Command, - CommandParameter = flyoutItemViewModel.CommandParameter, - Text = flyoutItemViewModel.Text, - Tag = flyoutItemViewModel.Tag, - Icon = new FontIcon() { Glyph = flyoutItemViewModel.IconGlyph.PreventNull(string.Empty) } - }; - } - - flyoutItem.IsEnabled = item.IsEnabled; - - return flyoutItem; - } - - public static IList FilterItems(IList items) - { - List filtered = new List(); - - for (int i = 0; i < items.Count; i++) - { - if (items[i].IsShown?.Invoke() ?? false) - { - filtered.Add(items[i]); - } - } - - return filtered; - } - } -} diff --git a/ClipboardCanvas/Helpers/ImagingHelpers.cs b/ClipboardCanvas/Helpers/ImagingHelpers.cs deleted file mode 100644 index 39464ef9..00000000 --- a/ClipboardCanvas/Helpers/ImagingHelpers.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices.WindowsRuntime; -using System.Threading.Tasks; -using Windows.Graphics.Imaging; -using Windows.Storage; -using Windows.Storage.FileProperties; -using Windows.Storage.Streams; -using Microsoft.UI.Xaml.Media.Imaging; -using Microsoft.UI.Xaml.Media; -using System.Threading; - -using ClipboardCanvas.Helpers.Filesystem; - -namespace ClipboardCanvas.Helpers -{ - public static class ImagingHelpers - { - public static async Task GetTransparentThumbnail(this StorageFile file, ThumbnailMode mode, uint requestedSize, ThumbnailOptions options = ThumbnailOptions.None) - { - if (FileHelpers.IsPathEqualExtension(file.Path, ".png")) - { - // Try to create a scaled-down version of the PNG with transparency - using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read)) - { - IRandomAccessStream thumbnail = new InMemoryRandomAccessStream(); - BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream); - BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, thumbnail); - - SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(); - encoder.SetSoftwareBitmap(softwareBitmap); - - encoder.BitmapTransform.ScaledHeight = requestedSize; - encoder.BitmapTransform.ScaledWidth = (uint)(requestedSize * 1.7777d); - encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant; - - await encoder.FlushAsync(); - await thumbnail.FlushAsync(); - - softwareBitmap.Dispose(); - thumbnail.Seek(0); - - return thumbnail; - } - } - - return await file.GetThumbnailAsync(mode, requestedSize, options); - } - - public static async Task ToBitmapAsync(this byte[] data) - { - if (data == null) - { - return null; - } - - using (MemoryStream memoryStream = new MemoryStream(data)) - { - BitmapImage image = new BitmapImage(); - await image.SetSourceAsync(memoryStream.AsRandomAccessStream()); - - return image; - } - } - - public static async Task ToBitmapAsync(IRandomAccessStream stream) - { - if (stream == null) - { - return null; - } - - stream.Seek(0); - BitmapImage image = new BitmapImage(); - await image.SetSourceAsync(stream); - - return image; - } - - public static async Task ToImageAsync(Uri uri, CancellationToken cancellationToken) - { - ImageSource image = null; - - await TaskHelpers.RunTaskWithTimeout(GetImage(), TimeSpan.FromMilliseconds(Constants.UI.Imaging.IMAGE_FROM_URI_TIMEOUT), cancellationToken); - - return image; - - async Task GetImage() - { - try - { - RandomAccessStreamReference uriStream = RandomAccessStreamReference.CreateFromUri(uri); - using (IRandomAccessStream stream = await uriStream.OpenReadAsync()) - { - if (uri.AbsoluteUri.EndsWith(".svg")) - { - image = new SvgImageSource(uri); - } - else - { - image = new BitmapImage(); - await (image as BitmapImage).SetSourceAsync(stream); - } - } - } - catch { } - } - } - - public static async Task GetBytesFromSoftwareBitmap(this SoftwareBitmap softwareBitmap, Guid encoderId) - { - byte[] array = null; - - // First: Use an encoder to copy from SoftwareBitmap to an in-mem stream (FlushAsync) - // Next: Use ReadAsync on the in-mem stream to get byte[] array - - using (InMemoryRandomAccessStream imras = new InMemoryRandomAccessStream()) - { - BitmapEncoder encoder = await BitmapEncoder.CreateAsync(encoderId, imras); - if (softwareBitmap == null) - { - return new byte[] { }; - } - encoder.SetSoftwareBitmap(softwareBitmap); - - try - { - await encoder.FlushAsync(); - } - catch (Exception ex) - { - Console.WriteLine(ex); - return new byte[0]; - } - - array = new byte[imras.Size]; - await imras.ReadAsync(array.AsBuffer(), (uint)imras.Size, InputStreamOptions.None); - } - - return array; - } - } -} diff --git a/ClipboardCanvas/Helpers/InitialApplicationChecksHelpers.cs b/ClipboardCanvas/Helpers/InitialApplicationChecksHelpers.cs deleted file mode 100644 index bb388c9b..00000000 --- a/ClipboardCanvas/Helpers/InitialApplicationChecksHelpers.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Windows.ApplicationModel.Core; -using Windows.Storage; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.Services; -using CommunityToolkit.Mvvm.DependencyInjection; - -namespace ClipboardCanvas.Helpers -{ - public static class InitialApplicationChecksHelpers - { - public static async Task CheckVersionAndShowDialog() - { - try - { - IApplicationSettingsService applicationSettings = Ioc.Default.GetService(); - IApplicationService applicationService = Ioc.Default.GetService(); - IDialogService dialogService = Ioc.Default.GetService(); - - string lastVersion = applicationSettings.LastVersionNumber; - string currentVersion = applicationService.AppVersion; - - if (string.IsNullOrEmpty(lastVersion)) - { - // No version yet, Clipboard Canvas is freshly installed - // update the version setting with current version - applicationSettings.LastVersionNumber = currentVersion; - } - else - { - // Compare two versions - if (VersionHelpers.IsVersionDifferentThan(lastVersion, currentVersion)) - { - // Update the last version number to be the current number - applicationSettings.LastVersionNumber = currentVersion; - - // Show the update dialog - await dialogService.ShowDialog(new UpdateChangeLogDialogViewModel()); - } - } - } - catch (Exception ex) - { - LoggingHelpers.SafeLogExceptionToFile(ex); - } - } - - public static async Task HandleFileSystemPermissionDialog(IWindowTitleBarControlModel windowTitleBar) - { - try - { - IDialogService dialogService = Ioc.Default.GetService(); - IApplicationService applicationService = Ioc.Default.GetService(); - - string testForFolderOnFS = - Path.GetFullPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); - SafeWrapper testFolderResult = - await StorageHelpers.ToStorageItemWithError(testForFolderOnFS); - - if (!testFolderResult) - { - applicationService.IsInRestrictedAccessMode = true; - - DialogResult dialogResult = await dialogService.ShowDialog(new FileSystemAccessDialogViewModel()); - - if (dialogResult == DialogResult.Primary) - { - // Restart the app - await CoreApplication.RequestRestartAsync(string.Empty); - } - else - { - // Continue in Restricted Access - windowTitleBar.IsInRestrictedAccess = true; - } - } - else - { - return; - } - } - catch (Exception ex) - { - LoggingHelpers.SafeLogExceptionToFile(ex); - } - } - } -} diff --git a/ClipboardCanvas/Helpers/LoggingHelpers.cs b/ClipboardCanvas/Helpers/LoggingHelpers.cs deleted file mode 100644 index a31c102d..00000000 --- a/ClipboardCanvas/Helpers/LoggingHelpers.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ClipboardCanvas.Services; -using ClipboardCanvas.Services.Implementation; -using CommunityToolkit.Mvvm.DependencyInjection; - -namespace ClipboardCanvas.Helpers -{ - public static class LoggingHelpers - { - public static void SafeLogExceptionToFile(Exception ex) - { - if (ex == null) - { - return; - } - - string exceptionString = ""; - - exceptionString += DateTime.Now.ToString(Constants.FileSystem.EXCEPTION_BLOCK_DATE_FORMAT); - exceptionString += "\n"; - exceptionString += $">>> HRESULT {ex.HResult}\n"; - exceptionString += $">>> MESSAGE {ex.Message}\n"; - exceptionString += $">>> STACKTRACE {ex.StackTrace}\n"; - exceptionString += $">>> INNER {ex.InnerException}\n"; - exceptionString += $">>> SOURCE {ex.Source}\n\n"; - - ILogger logger; - try - { - logger = Ioc.Default.GetService(); // Try get Ioc logger - } - catch - { - logger = new ExceptionToFileLogger(); // Use default logger - } - - logger?.LogToFile(exceptionString); - } - } -} diff --git a/ClipboardCanvas/Helpers/ObservableUserControl.cs b/ClipboardCanvas/Helpers/ObservableUserControl.cs deleted file mode 100644 index c8d693dd..00000000 --- a/ClipboardCanvas/Helpers/ObservableUserControl.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel; -using System.Runtime.CompilerServices; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace ClipboardCanvas.Helpers -{ - public class ObservableUserControl : UserControl, INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - protected void SetValueDP(DependencyProperty dependencyProperty, object value, [CallerMemberName] string callerName = "") - { - SetValue(dependencyProperty, value); - OnPropertyChanged(callerName); - } - - protected void OnPropertyChanged([CallerMemberName] string callerName = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(callerName)); - } - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/DefaultSafeWrapperExceptionReporter.cs b/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/DefaultSafeWrapperExceptionReporter.cs deleted file mode 100644 index c3eb267f..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/DefaultSafeWrapperExceptionReporter.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.IO; -using CommunityToolkit.Mvvm.DependencyInjection; -using Windows.Storage; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters -{ - public class DefaultSafeWrapperExceptionReporter : ISafeWrapperExceptionReporter - { - // TODO: Implement proper error reporting here - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - public SafeWrapperResultDetails GetStatusResult(Exception e) - { - return GetStatusResult(e, null); - } - - public SafeWrapperResultDetails GetStatusResult(Exception e, Type callerType) - { - if (e is UnauthorizedAccessException) - { - return (OperationErrorCode.AccessUnauthorized, e, ApplicationService.IsInRestrictedAccessMode ? "Couldn't access this path because Clipboard Canvas is in Restricted Access mode. Access is unauthorized." - : "Access is unauthorized."); - } - else if (e is FileNotFoundException) // File not found - { - return (OperationErrorCode.NotFound, e, "The file was not found."); - } - else if (e is DirectoryNotFoundException) // Folder not found - { - return (OperationErrorCode.NotFound, e, "The folder was not found."); - } - else if (e is ArgumentException) // Item was invalid - { - return callerType == typeof(StorageFolder) ? - (OperationErrorCode.NotAFolder, e, "Item is not a folder.") : (OperationErrorCode.NotAFile, e, "Item is not a file."); - } - else if ((uint)e.HResult == 0x800700B7) - { - return (OperationErrorCode.AlreadyExists, e, "Item already exists."); - } - else - { - return SafeWrapperResult.UNKNOWN_FAIL.Details; - } - } - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/ISafeWrapperExceptionReporter.cs b/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/ISafeWrapperExceptionReporter.cs deleted file mode 100644 index 29d8711a..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/ISafeWrapperExceptionReporter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters -{ - public interface ISafeWrapperExceptionReporter - { - SafeWrapperResultDetails GetStatusResult(Exception e); - - SafeWrapperResultDetails GetStatusResult(Exception e, Type callerType); - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/StaticExceptionReporters.cs b/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/StaticExceptionReporters.cs deleted file mode 100644 index 156ffd3b..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/ExceptionReporters/StaticExceptionReporters.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters -{ - public static class StaticExceptionReporters - { - public static ISafeWrapperExceptionReporter DefaultSafeWrapperExceptionReporter = new DefaultSafeWrapperExceptionReporter(); - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapper.cs b/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapper.cs deleted file mode 100644 index 78eca920..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapper.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Helpers.SafetyHelpers -{ - public class SafeWrapper : SafeWrapperResult - { - public TResult Result { get; private set; } - - public SafeWrapper(TResult result, OperationErrorCode errorCode) - : this (result, errorCode, null) - { - } - - public SafeWrapper(TResult result, OperationErrorCode errorCode, string message) - : this(result, errorCode, null, message) - { - } - - public SafeWrapper(TResult result, OperationErrorCode errorCode, Exception innerException, string message) - : this(result, new SafeWrapperResultDetails(errorCode, innerException, message)) - { - this.Result = result; - } - - public SafeWrapper(TResult result, SafeWrapperResultDetails details) - : base(details) - { - this.Result = result; - } - - public static implicit operator TResult(SafeWrapper safeWrapper) => safeWrapper.Result; - - public static implicit operator SafeWrapper((TResult, SafeWrapperResult) safeWrapper) => new SafeWrapper(safeWrapper.Item1, safeWrapper.Item2.Details); - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperResult.cs b/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperResult.cs deleted file mode 100644 index 7e5bcce0..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperResult.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; - -namespace ClipboardCanvas.Helpers.SafetyHelpers -{ - public class SafeWrapperResult - { - public static readonly SafeWrapperResult SUCCESS = new SafeWrapperResult(OperationErrorCode.Success, "Operation completed successfully."); - - public static readonly SafeWrapperResult CANCEL = new SafeWrapperResult(OperationErrorCode.Canceled, "OperationCanceled".GetLocalized2()); - - public static readonly SafeWrapperResult UNKNOWN_FAIL = new SafeWrapperResult(OperationErrorCode.UnknownFailed, new Exception(), "UnknownError".GetLocalized2()); - - public string Message => Details?.message; - - public OperationErrorCode ErrorCode => Details?.errorCode ?? OperationErrorCode.UnknownFailed; - - public Exception Exception => Details?.innerException; - - public SafeWrapperResultDetails Details { get; private set; } - - public SafeWrapperResult(OperationErrorCode status, Exception innerException) - : this(status, innerException, null) - { - } - - public SafeWrapperResult(OperationErrorCode status, string message) - : this(status, null, message) - { - } - - public SafeWrapperResult(OperationErrorCode status, Exception innerException, string message) - : this(new SafeWrapperResultDetails(status, innerException, message)) - { - } - - public SafeWrapperResult(SafeWrapperResultDetails details) - { - this.Details = details; - } - - public static SafeWrapperResult FromException(Exception exception, ISafeWrapperExceptionReporter exceptionReporter = null) - { - if (exceptionReporter == null) - { - exceptionReporter = StaticExceptionReporters.DefaultSafeWrapperExceptionReporter; - } - - return exceptionReporter.GetStatusResult(exception); - } - - public static implicit operator OperationErrorCode(SafeWrapperResult wrapperResult) - => wrapperResult?.Details?.errorCode ?? OperationErrorCode.InvalidArgument; - - public static implicit operator bool(SafeWrapperResult wrapperResult) - => (wrapperResult?.Details?.errorCode ?? OperationErrorCode.UnknownFailed) == OperationErrorCode.Success; - - public static implicit operator SafeWrapperResult(bool result) - => result ? SafeWrapperResult.SUCCESS : new SafeWrapperResult(OperationErrorCode.UnknownFailed, innerException: null); - - public static implicit operator SafeWrapperResult(SafeWrapperResultDetails details) - => new SafeWrapperResult(details); - - public static implicit operator SafeWrapperResult((OperationErrorCode errorCode, Exception innerException) details) - => new SafeWrapperResult(details.errorCode, details.innerException); - - public static implicit operator SafeWrapperResult((OperationErrorCode errorCode, string message) details) - => new SafeWrapperResult(details.errorCode, details.message); - - public static implicit operator SafeWrapperResult((OperationErrorCode errorCode, Exception innerException, string message) details) - => new SafeWrapperResult(details.errorCode, details.innerException, details.message); - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperResultDetails.cs b/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperResultDetails.cs deleted file mode 100644 index 3b13dc5a..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperResultDetails.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Helpers.SafetyHelpers -{ - public sealed class SafeWrapperResultDetails - { - public readonly OperationErrorCode errorCode; - - public readonly Exception innerException; - - public readonly string message; - - public SafeWrapperResultDetails(OperationErrorCode errorCode) - : this(errorCode, null, null) - { - } - - public SafeWrapperResultDetails(OperationErrorCode errorCode, Exception innerException) - : this(errorCode, innerException, null) - { - } - - public SafeWrapperResultDetails(OperationErrorCode errorCode, string message) - : this(errorCode, null, message) - { - } - - public SafeWrapperResultDetails(OperationErrorCode errorCode, Exception innerException, string message) - { - this.errorCode = errorCode; - this.innerException = innerException; - this.message = message; - } - - public static implicit operator SafeWrapperResultDetails((OperationErrorCode errorCode, Exception innerException) details) - => new SafeWrapperResultDetails(details.errorCode, details.innerException); - - public static implicit operator SafeWrapperResultDetails((OperationErrorCode errorCode, string message) details) - => new SafeWrapperResultDetails(details.errorCode, details.message); - - public static implicit operator SafeWrapperResultDetails((OperationErrorCode errorCode, Exception innerException, string message) details) - => new SafeWrapperResultDetails(details.errorCode, details.innerException, details.message); - } -} diff --git a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperRoutines.cs b/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperRoutines.cs deleted file mode 100644 index f7dc9921..00000000 --- a/ClipboardCanvas/Helpers/SafetyHelpers/SafeWrapperRoutines.cs +++ /dev/null @@ -1,235 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; - -namespace ClipboardCanvas.Helpers.SafetyHelpers -{ - public static class SafeWrapperRoutines - { - private static readonly SafeWrapperResult NullFunctionDelegateResult = new SafeWrapperResult(OperationErrorCode.InvalidArgument, new ArgumentException(), "Passed-in function delegate is null"); - - #region SafeWrap - - public static SafeWrapper SafeWrap(Func func, ISafeWrapperExceptionReporter reporter = null) - { - if (!AssertNotNull(func)) return new SafeWrapper(default(T), NullFunctionDelegateResult); - - try - { - return (func.Invoke(), SafeWrapperResult.SUCCESS); - } - catch (Exception e) - { - reporter = TryGetReporter(reporter); - - return new SafeWrapper(default(T), reporter.GetStatusResult(e, typeof(T))); - } - } - - public static SafeWrapperResult SafeWrap(Action action, ISafeWrapperExceptionReporter reporter = null) - { - if (!AssertNotNull(action)) return NullFunctionDelegateResult; - - try - { - action.Invoke(); - return SafeWrapperResult.SUCCESS; - } - catch (Exception e) - { - reporter = TryGetReporter(reporter); - - return new SafeWrapperResult(reporter.GetStatusResult(e)); - } - } - - #endregion - - #region SafeWrapAsync - - public static async Task> SafeWrapAsync(Func> func, ISafeWrapperExceptionReporter reporter = null) - { - if (!AssertNotNull(func)) return new SafeWrapper(default(T), NullFunctionDelegateResult); - - try - { - return (await func.Invoke(), SafeWrapperResult.SUCCESS); - } - catch (Exception e) - { - reporter = TryGetReporter(reporter); - - return new SafeWrapper(default(T), reporter.GetStatusResult(e, typeof(T))); - } - } - - public static async Task SafeWrapAsync(Func func, ISafeWrapperExceptionReporter reporter = null) - { - if (!AssertNotNull(func)) return NullFunctionDelegateResult; - - try - { - await func.Invoke(); - return SafeWrapperResult.SUCCESS; - } - catch (Exception e) - { - reporter = TryGetReporter(reporter); - - return new SafeWrapperResult(reporter.GetStatusResult(e)); - } - } - - #endregion - - #region OnSuccess - - public static SafeWrapper OnSuccess(this SafeWrapper wrapped, Func, T2> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T2), NullFunctionDelegateResult); - - SafeWrapperResult result = wrapped; - - if (result) - { - return SafeWrap(() => func(wrapped)); - } - - return new SafeWrapper(default(T2), result); - } - - public static SafeWrapperResult OnSuccessResult(this SafeWrapper wrapped, Func, SafeWrapperResult> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T), NullFunctionDelegateResult); - - SafeWrapperResult result = wrapped; - - if (result) - { - return SafeWrap(() => func(wrapped)); - } - - return result; - } - - #endregion - - #region OnSuccessAsync - - public static async Task> OnSuccessAsync(this Task> wrapped, Func, Task> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T2), NullFunctionDelegateResult); - - SafeWrapper result = await wrapped; - - if (result) - { - return await SafeWrapAsync(() => func(result)); - } - - return new SafeWrapper(default(T2), result); - } - - public static async Task OnSuccessResultAsync(this Task> wrapped, Func, Task> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T), NullFunctionDelegateResult); - - SafeWrapperResult result = await wrapped; - - if (result) - { - return await SafeWrapAsync(() => func(wrapped.Result)); - } - - return result; - } - - #endregion - - #region OnFailure - - public static SafeWrapper OnFailure(this SafeWrapper wrapped, Func, T2> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T2), NullFunctionDelegateResult); - - SafeWrapperResult result = wrapped; - - if (!result) - { - return SafeWrap(() => func(wrapped)); - } - - return new SafeWrapper(default(T2), result); - } - - public static SafeWrapperResult OnFailureResult(this SafeWrapper wrapped, Func, SafeWrapperResult> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T), NullFunctionDelegateResult); - - SafeWrapperResult result = wrapped; - - if (!result) - { - return SafeWrap(() => func(wrapped)); - } - - return result; - } - - #endregion - - #region OnFailureAsync - - public static async Task> OnFailureAsync(this Task> wrapped, Func, Task> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T2), NullFunctionDelegateResult); - - SafeWrapper result = await wrapped; - - if (!result) - { - return await SafeWrapAsync(() => func(result)); - } - - return new SafeWrapper(default(T2), result); - } - - public static async Task OnFailureResultAsync(this Task> wrapped, Func, Task> func) - { - if (!AssertNotNull(wrapped, func)) return new SafeWrapper(default(T), NullFunctionDelegateResult); - - SafeWrapperResult result = await wrapped; - - if (!result) - { - return await SafeWrapAsync(() => func(wrapped.Result)); - } - - return result; - } - - #endregion - - #region Private Helpers - - private static bool AssertNotNull(params object[] objectsToCheck) - { - return !objectsToCheck.Any((item) => item == null); - } - - private static ISafeWrapperExceptionReporter TryGetReporter(ISafeWrapperExceptionReporter defaultReporter = null) - { - if (defaultReporter == null) - { - return StaticExceptionReporters.DefaultSafeWrapperExceptionReporter; - } - - return defaultReporter; - } - - #endregion - } -} diff --git a/ClipboardCanvas/Helpers/SettingsSerializationHelpers.cs b/ClipboardCanvas/Helpers/SettingsSerializationHelpers.cs deleted file mode 100644 index 64db45a4..00000000 --- a/ClipboardCanvas/Helpers/SettingsSerializationHelpers.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.Helpers -{ - public class SettingsSerializationHelpers - { - public static void UpdateUserTimelineSetting() - { - ITimelineService timelineService = Ioc.Default.GetService(); - ITimelineSettingsService timelineSettingsService = Ioc.Default.GetService(); - - var configurationModel = timelineService.ConstructConfigurationModel(); - timelineSettingsService.UserTimeline = configurationModel; - } - - public static void UpdateLastSelectedCollectionSetting(BaseCollectionViewModel collectionViewModel) - { - ICollectionsSettingsService collectionsSettings = Ioc.Default.GetService(); - - var collectionConfiguration = collectionViewModel.ConstructConfigurationModel(); - collectionsSettings.LastSelectedCollection = collectionConfiguration.collectionPath; - } - - public static void UpdateSavedCollectionsSetting() - { - ICollectionsSettingsService collectionsSettings = Ioc.Default.GetService(); - - IEnumerable configurations = CollectionsWidgetViewModel.Collections.Select((item) => item.ConstructConfigurationModel()); - collectionsSettings.SavedCollections = configurations.ToList(); - } - } -} diff --git a/ClipboardCanvas/Helpers/TaskHelpers.cs b/ClipboardCanvas/Helpers/TaskHelpers.cs deleted file mode 100644 index f0dcb4c5..00000000 --- a/ClipboardCanvas/Helpers/TaskHelpers.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Helpers -{ - public static class TaskHelpers - { - public static bool RunOperationWithTimeout(Action action, TimeSpan timeout, CancellationToken cancellationToken) - { - Task task = Task.Run(() => action, cancellationToken); - - return task.Wait(timeout); - } - - public static async Task RunTaskWithTimeout(Task task, TimeSpan timeout, CancellationToken cancellationToken) - { - if (await Task.WhenAny(task, Task.Delay(timeout, cancellationToken)) == task) - { - return true; - } - else - { - return false; - } - } - } -} diff --git a/ClipboardCanvas/Helpers/ThemeHelper.cs b/ClipboardCanvas/Helpers/ThemeHelper.cs deleted file mode 100644 index 9041a759..00000000 --- a/ClipboardCanvas/Helpers/ThemeHelper.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Windows.UI.ViewManagement; -using Microsoft.UI.Xaml; -using Microsoft.UI; - -namespace ClipboardCanvas.Helpers -{ - public static class ThemeHelper - { - public static UISettings UISettings { get; private set; } - - public static ApplicationTheme CurrentTheme => Application.Current.RequestedTheme; - - public static void Initialize() - { - // TODO: Regression - //MainWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent; - //MainWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; - - UISettings = new UISettings(); - UISettings.ColorValuesChanged += UISettings_ColorValuesChanged; - - RefreshTheme(); - } - - private static void UISettings_ColorValuesChanged(UISettings sender, object args) - { - // RefreshTheme(); - } - - public static void RefreshTheme() - { - // TODO: Regression - switch (CurrentTheme) - { - case ApplicationTheme.Light: - { - //MainWindow.TitleBar.ButtonForegroundColor = Colors.Black; - break; - } - - case ApplicationTheme.Dark: - { - //MainWindow.TitleBar.ButtonForegroundColor = Colors.White; - break; - } - } - } - } -} diff --git a/ClipboardCanvas/Helpers/TwoWayPropertyUpdater.cs b/ClipboardCanvas/Helpers/TwoWayPropertyUpdater.cs deleted file mode 100644 index 3b232ec6..00000000 --- a/ClipboardCanvas/Helpers/TwoWayPropertyUpdater.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace ClipboardCanvas.Helpers -{ - public sealed class TwoWayPropertyUpdater - { - public event EventHandler OnPropertyValueUpdatedEvent; - - public void NotifyPropertyValueUpdated(TProperty newValue) - { - OnPropertyValueUpdatedEvent?.Invoke(this, newValue); - } - } -} diff --git a/ClipboardCanvas/Helpers/VersionHelpers.cs b/ClipboardCanvas/Helpers/VersionHelpers.cs deleted file mode 100644 index cf50d8cb..00000000 --- a/ClipboardCanvas/Helpers/VersionHelpers.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Helpers -{ - public static class VersionHelpers - { - public static bool IsVersionEqualTo(string version1, string version2) - { - Version vVersion1 = new Version(version1); - Version vVersion2 = new Version(version2); - - return vVersion1 == vVersion2; - } - - public static bool IsVersionDifferentThan(string version1, string version2) - { - Version vVersion1 = new Version(version1); - Version vVersion2 = new Version(version2); - - return vVersion1 != vVersion2; - } - - public static bool IsVersionBiggerThanOrEqual(string version1, string version2) - { - Version vVersion1 = new Version(version1); - Version vVersion2 = new Version(version2); - - return vVersion1 >= vVersion2; - } - - public static bool IsVersionSmallerThan(string version1, string version2) - { - Version vVersion1 = new Version(version1); - Version vVersion2 = new Version(version2); - - return vVersion1 < vVersion2; - } - } -} diff --git a/ClipboardCanvas/Helpers/WebHelpers.cs b/ClipboardCanvas/Helpers/WebHelpers.cs deleted file mode 100644 index ad85c56d..00000000 --- a/ClipboardCanvas/Helpers/WebHelpers.cs +++ /dev/null @@ -1,295 +0,0 @@ -using HtmlAgilityPack; -using System; -using System.Collections.Generic; -using System.Net; -using System.Threading.Tasks; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.Helpers -{ - public static class WebHelpers - { - public static bool IsUrl(string str) - { - return Uri.TryCreate(str, UriKind.Absolute, out Uri uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps); - } - - public static async Task IsUrlImage(string url) - { - const string urlImageContentType = "image/"; - - try - { - HttpWebRequest request = HttpWebRequest.CreateHttp(url); - request.Method = "HEAD"; - using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) - { - if (response.StatusCode == HttpStatusCode.OK && response.ContentType.ToLowerInvariant().Contains(urlImageContentType)) - { - return true; - } - } - } - catch { } - - return false; - } - - public static async Task IsValidUrl(string url) - { - if (string.IsNullOrEmpty(url)) - { - return false; - } - - WebResponse response = null; - try - { - WebRequest request = HttpWebRequest.Create(url); - response = await request.GetResponseAsync(); - } - catch (WebException webEx) - { - if (webEx.Message.Contains("302")) // Result: "Found" - { - return true; - } - else - { - return false; - } - } - catch - { - return false; - } - finally - { - response?.Dispose(); - } - - return true; - } - - public static string AlternativeGetIcon(HtmlNodeCollection linkNodes) - { - string iconUrl = null; - - if (!linkNodes.IsEmpty()) - { - foreach (var tag in linkNodes) - { - HtmlAttribute tagRel = tag.Attributes["rel"]; - HtmlAttribute tagHref = tag.Attributes["href"]; - HtmlAttribute tagSizes = tag.Attributes["sizes"]; - - if (tagRel != null && tagHref != null) - { - switch (tagRel.Value.ToLower()) - { - case "shortcut icon": - iconUrl = string.IsNullOrEmpty(iconUrl) ? tagHref.Value : iconUrl; - break; - case "icon": - iconUrl = tagHref.Value; - break; - } - } - } - } - - return iconUrl; - } - - public static SiteMetadata GetMetadata(HtmlNodeCollection metaTags) - { - SiteMetadata metaInfo = new SiteMetadata(); - - if (!metaTags.IsEmpty()) - { - int matchCount = 0; - - foreach (var tag in metaTags) - { - HtmlAttribute tagName = tag.Attributes["name"]; - HtmlAttribute tagContent = tag.Attributes["content"]; - HtmlAttribute tagProperty = tag.Attributes["property"]; - - if (tagName != null && tagContent != null) - { - switch (tagName.Value.ToLower()) - { - case "title": - metaInfo.Title = tagContent.Value; - matchCount++; - break; - case "description": - metaInfo.Description = tagContent.Value; - matchCount++; - break; - case "twitter:title": - metaInfo.Title = string.IsNullOrEmpty(metaInfo.Title) ? tagContent.Value : metaInfo.Title; - matchCount++; - break; - case "twitter:description": - metaInfo.Description = string.IsNullOrEmpty(metaInfo.Description) ? tagContent.Value : metaInfo.Description; - matchCount++; - break; - case "keywords": - metaInfo.Keywords = tagContent.Value; - matchCount++; - break; - case "twitter:image": - metaInfo.ImageUrls.AddIfNotPresent(string.IsNullOrEmpty(metaInfo.IconUrl) ? tagContent.Value : metaInfo.IconUrl); - matchCount++; - break; - case "icon": - metaInfo.IconUrl = string.IsNullOrEmpty(metaInfo.IconUrl) ? tagContent.Value : metaInfo.IconUrl; - matchCount++; - break; - } - } - else if (tagProperty != null && tagContent != null) - { - switch (tagProperty.Value.ToLower()) - { - case "og:title": - metaInfo.Title = string.IsNullOrEmpty(metaInfo.Title) ? tagContent.Value : metaInfo.Title; - matchCount++; - break; - case "og:description": - metaInfo.Description = string.IsNullOrEmpty(metaInfo.Description) ? tagContent.Value : metaInfo.Description; - matchCount++; - break; - case "og:image": - metaInfo.ImageUrls.AddIfNotPresent(string.IsNullOrEmpty(metaInfo.IconUrl) ? tagContent.Value : metaInfo.IconUrl); - matchCount++; - break; - case "og:icon": - metaInfo.IconUrl = string.IsNullOrEmpty(metaInfo.IconUrl) ? tagContent.Value : metaInfo.IconUrl; - matchCount++; - break; - case "og:site": - case "og:site_name": - metaInfo.SiteName = tagContent.Value; - break; - } - } - } - - metaInfo.HasAnyData = matchCount > 0; - } - - return metaInfo; - } - - public static async Task> FormatImageUrls(List rawImages, string url) - { - List validImageUrls = new List(); - - foreach (string item in rawImages) - { - string formattedUrl = await FormatImageUrl(item, url); - if (!string.IsNullOrEmpty(formattedUrl)) - { - validImageUrls.Add(formattedUrl); - if (validImageUrls.Count == Constants.UI.CanvasContent.UrlCanvas.MAX_IMAGES_TO_DISPLAY) - { - break; - } - } - } - - return validImageUrls; - } - - public static async Task FormatImageUrl(string rawImageUrl, string url) - { - if (!string.IsNullOrEmpty(rawImageUrl)) - { - string formattedUrl; - - if (!rawImageUrl.Contains("http")) - { - string baseUrl = null; - if (rawImageUrl.EndsWith(".ico")) - { - string http; - if (url.Contains("https")) - { - http = "https://"; - } - else - { - http = "http://"; - } - - try - { - Uri rawImageUri = new Uri(rawImageUrl); - if (!string.IsNullOrEmpty(rawImageUri.Host)) - { - baseUrl = $"{http}{rawImageUri.Host}"; - rawImageUrl = rawImageUrl.Replace(rawImageUri.Host, string.Empty); - } - } - catch { } - - if (string.IsNullOrEmpty(baseUrl)) - { - Uri uri = new Uri(url); - baseUrl = $"{http}{uri.Host}"; - } - } - else - { - baseUrl = url; - } - - formattedUrl = ($"{baseUrl}/{rawImageUrl}").PreventNull(string.Empty).Replace("///", "/").Replace("//", "/").Replace(":/", "://"); - } - else - { - formattedUrl = rawImageUrl; - } - - if (await CheckImageUrlIfExists(formattedUrl)) - { - return formattedUrl; - } - } - - return null; - } - - public static async Task CheckImageUrlIfExists(string imageUrl) - { - SafeWrapper existsResult = await SafeWrapperRoutines.SafeWrapAsync(async () => - { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(imageUrl); - request.Method = "HEAD"; - - request.UseDefaultCredentials = true; - request.Accept = "*/*"; - request.Proxy.Credentials = CredentialCache.DefaultCredentials; - - using (WebResponse response = await request.GetResponseAsync()) - { - return true; - } - }); - - if (existsResult) - { - return existsResult.Result; - } - else - { - return false; - } - } - } -} diff --git a/ClipboardCanvas/Interfaces/Collections/ICollectionNameEditable.cs b/ClipboardCanvas/Interfaces/Collections/ICollectionNameEditable.cs deleted file mode 100644 index e3d469e6..00000000 --- a/ClipboardCanvas/Interfaces/Collections/ICollectionNameEditable.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ClipboardCanvas.EventArguments.Collections; -using System; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Interfaces.Collections -{ - public interface ICollectionNameEditable - { - event EventHandler OnCheckRenameCollectionRequestedEvent; - - void StartRename(); - - void CancelRename(); - - Task ConfirmRename(); - } -} diff --git a/ClipboardCanvas/Interfaces/Collections/ICollectionRemovable.cs b/ClipboardCanvas/Interfaces/Collections/ICollectionRemovable.cs deleted file mode 100644 index c0f7f4a0..00000000 --- a/ClipboardCanvas/Interfaces/Collections/ICollectionRemovable.cs +++ /dev/null @@ -1,12 +0,0 @@ -using ClipboardCanvas.EventArguments.Collections; -using System; - -namespace ClipboardCanvas.Interfaces.Collections -{ - public interface ICollectionRemovable - { - event EventHandler OnRemoveCollectionRequestedEvent; - - void RemoveCollection(); - } -} diff --git a/ClipboardCanvas/Interfaces/Search/ISearchItem.cs b/ClipboardCanvas/Interfaces/Search/ISearchItem.cs deleted file mode 100644 index d1bb4c06..00000000 --- a/ClipboardCanvas/Interfaces/Search/ISearchItem.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClipboardCanvas.Interfaces.Search -{ - public interface ISearchItem - { - bool IsHighlighted { get; set; } - } -} diff --git a/ClipboardCanvas/Interfaces/Search/ISearchItems.cs b/ClipboardCanvas/Interfaces/Search/ISearchItems.cs deleted file mode 100644 index 456f92de..00000000 --- a/ClipboardCanvas/Interfaces/Search/ISearchItems.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace ClipboardCanvas.Interfaces.Search -{ - public interface ISearchItems - { - int Count { get; } - - int CurrentIndex { get; } - - IEnumerable CompareItemsToPhrase(string phrase); - - int IndexOfItemInCollection(ISearchItem item); - - void SetSelectedIndex(int index); - } -} diff --git a/ClipboardCanvas/MainWindow.xaml.cs b/ClipboardCanvas/MainWindow.xaml.cs deleted file mode 100644 index 70395798..00000000 --- a/ClipboardCanvas/MainWindow.xaml.cs +++ /dev/null @@ -1,77 +0,0 @@ -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Pages; -using Microsoft.UI; -using Microsoft.UI.Windowing; -using Microsoft.UI.Xaml; -using System; -using WinRT.Interop; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace ClipboardCanvas -{ - /// - /// An empty window that can be used on its own or navigated to within a Frame. - /// - public sealed partial class MainWindow : Window - { - public static MainWindow Instance; - - public IntPtr Hwnd { get; private set; } - - public AppWindow? AppWindow { get; private set; } - - public MainWindowContentPage MainWindowContentPage => MainPageHost; - - public MainWindow() - { - Instance = this; - this.InitializeComponent(); - - EnsureSafeInitialization(); - } - - private void EnsureSafeInitialization() - { - try - { - // Get AppWindow - Hwnd = WindowNative.GetWindowHandle(this); - var mainWindowWndId = Win32Interop.GetWindowIdFromWindow(Hwnd); - AppWindow = AppWindow.GetFromWindowId(mainWindowWndId); - - // Set title - if (AppWindow is not null) - { - AppWindow.Title = "Clipboard Canvas"; - } - else - { - Title = "Clipboard Canvas"; - } - - if (AppWindowTitleBar.IsCustomizationSupported()) - { - // Extend title bar - AppWindow.TitleBar.ExtendsContentIntoTitleBar = true; - - // Set window buttons background to transparent - AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent; - AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; - } - else - { - this.ExtendsContentIntoTitleBar = true; - SetTitleBar(MainWindowContentPage.WindowTitleBar.CustomTitleBar); - } - - ThemeHelper.Initialize(); - } - catch (Exception ex) - { - LoggingHelpers.SafeLogExceptionToFile(ex); - } - } - } -} diff --git a/ClipboardCanvas/ModelViews/IBaseCanvasPreviewControlView.cs b/ClipboardCanvas/ModelViews/IBaseCanvasPreviewControlView.cs deleted file mode 100644 index 53c40acc..00000000 --- a/ClipboardCanvas/ModelViews/IBaseCanvasPreviewControlView.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ClipboardCanvas.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.ModelViews -{ - public interface IBaseCanvasPreviewControlView - { - ICollectionModel CollectionModel { get; } - } -} diff --git a/ClipboardCanvas/ModelViews/ICanvasPageView.cs b/ClipboardCanvas/ModelViews/ICanvasPageView.cs deleted file mode 100644 index be6588cb..00000000 --- a/ClipboardCanvas/ModelViews/ICanvasPageView.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.ModelViews -{ - public interface ICanvasPageView - { - ICollectionModel AssociatedCollectionModel { get; } - - ICanvasPreviewModel CanvasPreviewModel { get; } - - void FinishConnectedAnimation(); - } -} \ No newline at end of file diff --git a/ClipboardCanvas/ModelViews/ICollectionPreviewPageView.cs b/ClipboardCanvas/ModelViews/ICollectionPreviewPageView.cs deleted file mode 100644 index e66ce70f..00000000 --- a/ClipboardCanvas/ModelViews/ICollectionPreviewPageView.cs +++ /dev/null @@ -1,18 +0,0 @@ -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels; - -namespace ClipboardCanvas.ModelViews -{ - public interface ICollectionPreviewPageView - { - ICollectionModel AssociatedCollectionModel { get; } - - ISearchControlModel SearchControlModel { get; } - - void PrepareConnectedAnimation(int itemIndex); - - void ScrollItemToView(CollectionPreviewItemViewModel itemToScrollTo); - - void ScrollToItemOnInitialization(CollectionPreviewItemViewModel itemToScrollTo); - } -} diff --git a/ClipboardCanvas/ModelViews/IDialogView.cs b/ClipboardCanvas/ModelViews/IDialogView.cs deleted file mode 100644 index e7ca09cb..00000000 --- a/ClipboardCanvas/ModelViews/IDialogView.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.UI.Xaml; - -namespace ClipboardCanvas.ModelViews -{ - public interface IDialogView - { - XamlRoot XamlRoot { get; set; } - - void Hide(); - } -} diff --git a/ClipboardCanvas/ModelViews/IDisplayControlView.cs b/ClipboardCanvas/ModelViews/IDisplayControlView.cs deleted file mode 100644 index 3057dc1c..00000000 --- a/ClipboardCanvas/ModelViews/IDisplayControlView.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.ModelViews -{ - public interface IDisplayControlView - { - bool IntroductionPanelLoad { get; set; } - - IWindowTitleBarControlModel WindowTitleBarControlModel { get; } - - INavigationToolBarControlModel NavigationToolBarControlModel { get; } - - IIntroductionScreenPanelModel IntroductionScreenPanelModel { get; } - - IPasteCanvasPageModel PasteCanvasPageModel { get; } - - ICollectionPreviewPageModel CollectionPreviewPageModel { get; } - } -} diff --git a/ClipboardCanvas/ModelViews/IInfiniteCanvasControlView.cs b/ClipboardCanvas/ModelViews/IInfiniteCanvasControlView.cs deleted file mode 100644 index b6c4ad33..00000000 --- a/ClipboardCanvas/ModelViews/IInfiniteCanvasControlView.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.ModelViews -{ - public interface IInfiniteCanvasControlView - { - IInteractableCanvasControlModel InteractableCanvasModel { get; } - } -} diff --git a/ClipboardCanvas/ModelViews/IInteractableCanvasControlView.cs b/ClipboardCanvas/ModelViews/IInteractableCanvasControlView.cs deleted file mode 100644 index 751ea211..00000000 --- a/ClipboardCanvas/ModelViews/IInteractableCanvasControlView.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Numerics; -using Windows.Storage.Streams; -using System.Threading.Tasks; - -using ClipboardCanvas.ViewModels.UserControls; - -namespace ClipboardCanvas.ModelViews -{ - public interface IInteractableCanvasControlView - { - Vector2 GetItemPosition(InteractableCanvasControlItemViewModel itemViewModel); - - void SetItemPosition(InteractableCanvasControlItemViewModel itemViewModel, Vector2 position); - - Task<(IBuffer buffer, uint pixelWidth, uint pixelHeight)> GetCanvasImageBuffer(); - - void SetOnTop(InteractableCanvasControlItemViewModel itemViewModel); - - int GetCanvasTopIndex(InteractableCanvasControlItemViewModel itemViewModel); - - void SetCanvasTopIndex(InteractableCanvasControlItemViewModel itemViewModel, int topIndex); - } -} diff --git a/ClipboardCanvas/ModelViews/IIntroductionScreenPaneView.cs b/ClipboardCanvas/ModelViews/IIntroductionScreenPaneView.cs deleted file mode 100644 index 654ef4c9..00000000 --- a/ClipboardCanvas/ModelViews/IIntroductionScreenPaneView.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.ModelViews -{ - public interface IIntroductionScreenPaneView - { - bool IntroductionPanelLoad { get; set; } - - int ItemsCount { get; } - } -} diff --git a/ClipboardCanvas/ModelViews/IMediaCanvasControlView.cs b/ClipboardCanvas/ModelViews/IMediaCanvasControlView.cs deleted file mode 100644 index 0cd1c1be..00000000 --- a/ClipboardCanvas/ModelViews/IMediaCanvasControlView.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.ModelViews -{ - public interface IMediaCanvasControlView : IDisposable - { - TimeSpan Position { get; set; } - - bool IsLoopingEnabled { get; set; } - - double Volume { get; set; } - - Task LoadFromMedia(IStorageFile file); - - Task LoadFromAudio(IStorageFile file); - } -} diff --git a/ClipboardCanvas/ModelViews/ISettingsAboutPageView.cs b/ClipboardCanvas/ModelViews/ISettingsAboutPageView.cs deleted file mode 100644 index 0616359f..00000000 --- a/ClipboardCanvas/ModelViews/ISettingsAboutPageView.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClipboardCanvas.ModelViews -{ - public interface ISettingsAboutPageView - { - bool IntroductionPanelLoad { get; set; } - } -} diff --git a/ClipboardCanvas/ModelViews/ISettingsDialogView.cs b/ClipboardCanvas/ModelViews/ISettingsDialogView.cs deleted file mode 100644 index 09fc623d..00000000 --- a/ClipboardCanvas/ModelViews/ISettingsDialogView.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClipboardCanvas.ModelViews -{ - public interface ISettingsDialogView - { - void CloseDialog(); - } -} diff --git a/ClipboardCanvas/ModelViews/ITextCanvasControlView.cs b/ClipboardCanvas/ModelViews/ITextCanvasControlView.cs deleted file mode 100644 index f8e6e838..00000000 --- a/ClipboardCanvas/ModelViews/ITextCanvasControlView.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ClipboardCanvas.ModelViews -{ - public interface ITextCanvasControlView - { - bool IsTextSelected { get; } - - int SelectedTextLength { get; } - - void TextSelectAll(); - - void CopySelectedText(); - } -} diff --git a/ClipboardCanvas/ModelViews/IWebViewCanvasControlView.cs b/ClipboardCanvas/ModelViews/IWebViewCanvasControlView.cs deleted file mode 100644 index a8a16dfb..00000000 --- a/ClipboardCanvas/ModelViews/IWebViewCanvasControlView.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace ClipboardCanvas.ModelViews -{ - public interface IWebViewCanvasControlView : IDisposable - { - void NavigateToHtml(string html); - - void NavigateToSource(string source); - } -} diff --git a/ClipboardCanvas/Models/Autopaste/AutopasteTargetWrapper.cs b/ClipboardCanvas/Models/Autopaste/AutopasteTargetWrapper.cs deleted file mode 100644 index 0eb18b70..00000000 --- a/ClipboardCanvas/Models/Autopaste/AutopasteTargetWrapper.cs +++ /dev/null @@ -1,31 +0,0 @@ -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using CommunityToolkit.Mvvm.ComponentModel; -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; - -namespace ClipboardCanvas.Models.Autopaste -{ - public sealed class AutopasteTargetWrapper : ObservableObject, IAutopasteTarget - { - private readonly Func>> _pasteFunction; - - public string DisplayName { get; } - - public string TargetPath { get; } - - public AutopasteTargetWrapper(string displayName, string targetPath, Func>> pasteFunction) - { - DisplayName = displayName; - TargetPath = targetPath; - _pasteFunction = pasteFunction; - } - - public async Task> PasteData(DataPackageView dataPackage, CancellationToken cancellationToken) - { - return await _pasteFunction(dataPackage, cancellationToken); - } - } -} diff --git a/ClipboardCanvas/Models/Autopaste/IAutopasteTarget.cs b/ClipboardCanvas/Models/Autopaste/IAutopasteTarget.cs deleted file mode 100644 index d26e87fe..00000000 --- a/ClipboardCanvas/Models/Autopaste/IAutopasteTarget.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using System.ComponentModel; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.DataModels; - -namespace ClipboardCanvas.Models.Autopaste -{ - public interface IAutopasteTarget : INotifyPropertyChanged - { - string DisplayName { get; } - - string TargetPath { get; } - - Task> PasteData(DataPackageView dataPackage, CancellationToken cancellationToken); - } -} diff --git a/ClipboardCanvas/Models/Autopaste/IRuleActions.cs b/ClipboardCanvas/Models/Autopaste/IRuleActions.cs deleted file mode 100644 index 19ca6a07..00000000 --- a/ClipboardCanvas/Models/Autopaste/IRuleActions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules; - -namespace ClipboardCanvas.Models.Autopaste -{ - public interface IRuleActions - { - void SerializeRules(); - - void RemoveRule(BaseAutopasteRuleViewModel ruleViewModel); - } -} diff --git a/ClipboardCanvas/Models/Configuration/CollectionConfigurationModel.cs b/ClipboardCanvas/Models/Configuration/CollectionConfigurationModel.cs deleted file mode 100644 index 4f69ac44..00000000 --- a/ClipboardCanvas/Models/Configuration/CollectionConfigurationModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using Newtonsoft.Json; - -namespace ClipboardCanvas.Models -{ - [Serializable] - public sealed class CollectionConfigurationModel - { - public readonly string collectionPath; - - public readonly bool usesCustomIcon; - - public readonly string iconFileName; - - public CollectionConfigurationModel(string collectionPath) - : this(collectionPath, false, null) - { - } - - [JsonConstructor] - public CollectionConfigurationModel(string collectionPath, bool usesCustomIcon, string iconFileName) - { - this.collectionPath = collectionPath; - this.usesCustomIcon = usesCustomIcon; - this.iconFileName = iconFileName; - } - } -} diff --git a/ClipboardCanvas/Models/Configuration/InfiniteCanvasConfigurationModel.cs b/ClipboardCanvas/Models/Configuration/InfiniteCanvasConfigurationModel.cs deleted file mode 100644 index 2b5e06f4..00000000 --- a/ClipboardCanvas/Models/Configuration/InfiniteCanvasConfigurationModel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Numerics; -using Newtonsoft.Json; - -namespace ClipboardCanvas.Models -{ - [Serializable] - public sealed class InfiniteCanvasConfigurationModel - { - public readonly List elements; - - [JsonConstructor] - public InfiniteCanvasConfigurationModel() - { - this.elements = new List(); - } - } - - [Serializable] - public sealed class InfiniteCanvasConfigurationItemModel - { - public readonly string associatedItemPath; - - public readonly Vector2 locationVector; - - public readonly int canvasTopIndex; - - [JsonConstructor] - public InfiniteCanvasConfigurationItemModel(string associatedItemPath, Vector2 locationVector, int canvasTopIndex) - { - this.associatedItemPath = associatedItemPath; - this.locationVector = locationVector; - this.canvasTopIndex = canvasTopIndex; - } - } -} diff --git a/ClipboardCanvas/Models/Configuration/TimelineConfigurationModel.cs b/ClipboardCanvas/Models/Configuration/TimelineConfigurationModel.cs deleted file mode 100644 index 2cd5af5c..00000000 --- a/ClipboardCanvas/Models/Configuration/TimelineConfigurationModel.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace ClipboardCanvas.Models.Configuration -{ - [Serializable] - public sealed class TimelineConfigurationModel - { - public readonly List sections; - - [JsonConstructor] - public TimelineConfigurationModel() - { - this.sections = new List(); - } - } - - public sealed class TimelineSectionConfigurationModel - { - public readonly DateTime sectionDateTime; - - public readonly List items; - - [JsonConstructor] - public TimelineSectionConfigurationModel(DateTime sectionDateTime) - { - this.sectionDateTime = sectionDateTime; - this.items = new List(); - } - } - - public sealed class TimelineSectionItemConfigurationModel - { - public readonly string collectionItemPath; - - public readonly CollectionConfigurationModel collectionConfigurationModel; - - [JsonConstructor] - public TimelineSectionItemConfigurationModel(string collectionItemPath, CollectionConfigurationModel collectionConfigurationModel) - { - this.collectionItemPath = collectionItemPath; - this.collectionConfigurationModel = collectionConfigurationModel; - } - } -} diff --git a/ClipboardCanvas/Models/IAutopasteControlModel.cs b/ClipboardCanvas/Models/IAutopasteControlModel.cs deleted file mode 100644 index 594a57b8..00000000 --- a/ClipboardCanvas/Models/IAutopasteControlModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClipboardCanvas.Models -{ - public interface IAutopasteControlModel - { - bool EnableAutopaste { get; set; } - } -} diff --git a/ClipboardCanvas/Models/ICanvasPreviewModel.cs b/ClipboardCanvas/Models/ICanvasPreviewModel.cs deleted file mode 100644 index 504e04f7..00000000 --- a/ClipboardCanvas/Models/ICanvasPreviewModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using System.Threading; -using System.Collections.Generic; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ViewModels.UserControls; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.DataModels.ContentDataModels; - -namespace ClipboardCanvas.Models -{ - public interface ICanvasPreviewModel : IReadOnlyCanvasPreviewModel - { - event EventHandler OnPasteInitiatedEvent; - - event EventHandler OnFileCreatedEvent; - - event EventHandler OnFileModifiedEvent; - - /// - /// Attempts to paste data from provided - /// - /// The data to paste - /// - Task TryPasteData(DataPackageView dataPackage, CancellationToken cancellationToken); - - /// - /// Opens new canvas - /// - void OpenNewCanvas(); - - /// - /// Gets suggested actions based on this canvas - /// - /// - Task> GetSuggestedActions(); - } -} diff --git a/ClipboardCanvas/Models/ICollectionModel.cs b/ClipboardCanvas/Models/ICollectionModel.cs deleted file mode 100644 index 9ae56e4f..00000000 --- a/ClipboardCanvas/Models/ICollectionModel.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using System.Collections.ObjectModel; -using Windows.Storage; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Contexts; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.EventArguments.Collections; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Models -{ - public interface ICollectionModel : ICanvasItemReceiverModel - { - event EventHandler OnCollectionItemAddedEvent; - - event EventHandler OnCollectionItemRemovedEvent; - - event EventHandler OnCollectionItemRenamedEvent; - - event EventHandler OnCollectionItemContentsChangedEvent; - - ObservableCollection CollectionItems { get; } - - /// - /// Saved search data by the Search function - /// - SearchContext SearchContext { get; set; } - - CanvasType AssociatedCanvasType { get; set; } - - bool IsCollectionAvailable { get; } - - bool IsOnNewCanvas { get; } - - string DisplayName { get; } - - bool IsCollectionInitialized { get; } - - bool IsCollectionInitializing { get; } - - CollectionItemViewModel CurrentCollectionItemViewModel { get; } - - Task> CreateNewCollectionItemFromExtension(string extension); - - Task> CreateNewCollectionItem(string fileName); - - Task DeleteCollectionItem(CollectionItemViewModel itemToDelete, bool permanently); - - CollectionItemViewModel FindCollectionItem(CanvasItem canvasItem); - - CollectionItemViewModel FindCollectionItem(IStorageItem storageItem); - - CollectionItemViewModel FindCollectionItem(string path); - - /// - /// Navigates to new canvas - /// - void NavigateFirst(ICanvasPreviewModel pasteCanvasModel); - - /// - /// Navigates to next canvas - /// - /// - Task NavigateNext(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken); - - /// - /// Navigates to last canvas in the list - /// - Task NavigateLast(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken); - - /// - /// Navigates to back canvas - /// - /// - Task NavigateBack(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken); - - /// - /// Tries to load current canvas from collection - /// - /// - /// - /// - Task LoadCanvasFromCollection(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken, CollectionItemViewModel collectionItemViewModel = null); - - /// - /// Returns true, if it's possible to navigate canvas forward - /// - /// - bool HasNext(); - - /// - /// Returns true, if it's possible to navigate canvas back - /// - /// - bool HasBack(); - - /// - /// Sets current index at the stack end - /// - void SetIndexOnNewCanvas(); - - /// - /// Sets current index to index of - /// - /// - void UpdateIndex(CollectionItemViewModel collectionItemViewModel); - - bool IsOnOpenedCanvas(CollectionItemViewModel collectionItemViewModel); - - bool CheckCollectionAvailability(); - - CollectionConfigurationModel ConstructConfigurationModel(); - - Task InitializeCollectionItems(); - - Task InitializeCollectionFolder(); - } -} diff --git a/ClipboardCanvas/Models/ICollectionPreviewPageModel.cs b/ClipboardCanvas/Models/ICollectionPreviewPageModel.cs deleted file mode 100644 index c8922e93..00000000 --- a/ClipboardCanvas/Models/ICollectionPreviewPageModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -using ClipboardCanvas.EventArguments.CollectionPreview; -using ClipboardCanvas.ViewModels; - -namespace ClipboardCanvas.Models -{ - public interface ICollectionPreviewPageModel : IDisposable - { - event EventHandler OnCanvasPreviewSelectedItemChangedEvent; - - event EventHandler OnCanvasPreviewPasteRequestedEvent; - - CollectionPreviewItemViewModel SelectedItem { get; } - } -} diff --git a/ClipboardCanvas/Models/IDragDataProviderModel.cs b/ClipboardCanvas/Models/IDragDataProviderModel.cs deleted file mode 100644 index a380d5b7..00000000 --- a/ClipboardCanvas/Models/IDragDataProviderModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; - -namespace ClipboardCanvas.Models -{ - public interface IDragDataProviderModel - { - Task SetDragData(DataPackage data); - } -} diff --git a/ClipboardCanvas/Models/IInteractableCanvasControlItemModel.cs b/ClipboardCanvas/Models/IInteractableCanvasControlItemModel.cs deleted file mode 100644 index 8e596422..00000000 --- a/ClipboardCanvas/Models/IInteractableCanvasControlItemModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Threading.Tasks; - -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.Models -{ - public interface IInteractableCanvasControlItemModel : IDragDataProviderModel, IDisposable - { - Task LoadContent(bool withLoadDelay = false); - } -} diff --git a/ClipboardCanvas/Models/IInteractableCanvasControlModel.cs b/ClipboardCanvas/Models/IInteractableCanvasControlModel.cs deleted file mode 100644 index 87b11266..00000000 --- a/ClipboardCanvas/Models/IInteractableCanvasControlModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.EventArguments.InfiniteCanvasEventArgs; -using ClipboardCanvas.ViewModels.UserControls; - -namespace ClipboardCanvas.Models -{ - public interface IInteractableCanvasControlModel : IDisposable - { - event EventHandler OnInfiniteCanvasSaveRequestedEvent; - - Task AddItem(ICollectionModel collectionModel, BaseContentTypeModel contentType, CanvasItem canvasFile, ICanvasItemReceiverModel inifinteCanvasFileReceiver, CancellationToken cancellationToken); - - void RemoveItem(InteractableCanvasControlItemViewModel item); - - bool ContainsItem(InteractableCanvasControlItemViewModel item); - - InteractableCanvasControlItemViewModel FindItem(string path); - - InfiniteCanvasConfigurationModel ConstructConfigurationModel(); - - Task RegenerateCanvasPreview(); - - void SetConfigurationModel(InfiniteCanvasConfigurationModel canvasConfigurationModel); - - void UpdateItemPositionFromDataPackage(DataPackageView dataPackage, InteractableCanvasControlItemViewModel interactableCanvasControlItem); - - Task ResetAllItemPositions(); - } -} diff --git a/ClipboardCanvas/Models/IIntroductionScreenPanelModel.cs b/ClipboardCanvas/Models/IIntroductionScreenPanelModel.cs deleted file mode 100644 index c764264a..00000000 --- a/ClipboardCanvas/Models/IIntroductionScreenPanelModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ClipboardCanvas.Models -{ - public interface IIntroductionScreenPanelModel - { - void FinishOff(); - } -} diff --git a/ClipboardCanvas/Models/INavigationControlModel.cs b/ClipboardCanvas/Models/INavigationControlModel.cs deleted file mode 100644 index c1b6eb5a..00000000 --- a/ClipboardCanvas/Models/INavigationControlModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Models -{ - public interface INavigationControlModel - { - event EventHandler OnNavigateLastRequestedEvent; - - event EventHandler OnNavigateBackRequestedEvent; - - event EventHandler OnNavigateFirstRequestedEvent; - - event EventHandler OnNavigateForwardRequestedEvent; - - event EventHandler OnGoToHomepageRequestedEvent; - - event EventHandler OnGoToCanvasRequestedEvent; - - event EventHandler OnCollectionPreviewNavigateBackRequestedEvent; - - event EventHandler OnCollectionPreviewGoToCanvasRequestedEvent; - - bool NavigateBackEnabled { get; set; } - - bool NavigateBackLoading { get; set; } - - bool NavigateForwardEnabled { get; set; } - - bool NavigateForwardLoading { get; set; } - - bool GoToCanvasEnabled { get; set; } - - bool CollectionPreviewGoToCanvasEnabled { get; set; } - - bool CollectionPreviewGoToCanvasLoading { get; set; } - - void NotifyCurrentPageChanged(DisplayPageType pageType); - } -} diff --git a/ClipboardCanvas/Models/INavigationToolBarControlModel.cs b/ClipboardCanvas/Models/INavigationToolBarControlModel.cs deleted file mode 100644 index c40dacb5..00000000 --- a/ClipboardCanvas/Models/INavigationToolBarControlModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.Models -{ - public interface INavigationToolBarControlModel - { - INavigationControlModel NavigationControlModel { get; } - - ISuggestedActionsControlModel SuggestedActionsControlModel { get; } - - IAutopasteControlModel AutopasteControlModel { get; } - - bool IsStatusCenterButtonVisible { get; set; } - - void NotifyCurrentPageChanged(DisplayPageType pageType); - } -} diff --git a/ClipboardCanvas/Models/IPasteCanvasPageModel.cs b/ClipboardCanvas/Models/IPasteCanvasPageModel.cs deleted file mode 100644 index 11beddb0..00000000 --- a/ClipboardCanvas/Models/IPasteCanvasPageModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Models -{ - public interface IPasteCanvasPageModel : IDisposable - { - ICanvasPreviewModel PasteCanvasModel { get; } - - Task SetTipText(string text); - - Task SetTipText(string text, TimeSpan tipShowDelay); - } -} diff --git a/ClipboardCanvas/Models/IReadOnlyCanvasPreviewModel.cs b/ClipboardCanvas/Models/IReadOnlyCanvasPreviewModel.cs deleted file mode 100644 index cce9f8b7..00000000 --- a/ClipboardCanvas/Models/IReadOnlyCanvasPreviewModel.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.ViewModels.UserControls.Collections; - -namespace ClipboardCanvas.Models -{ - public interface IReadOnlyCanvasPreviewModel : IDisposable - { - event EventHandler OnContentStartedLoadingEvent; - - event EventHandler OnContentLoadedEvent; - - event EventHandler OnContentLoadFailedEvent; - - event EventHandler OnFileDeletedEvent; - - event EventHandler OnErrorOccurredEvent; - - event EventHandler OnTipTextUpdateRequestedEvent; - - event EventHandler OnProgressReportedEvent; - - /// - /// Determines whether canvas content has been loaded - /// - bool IsContentLoaded { get; } - - /// - /// Context menu options available for the canvas - /// - ObservableCollection ContextMenuItems { get; } - - ICanvasItemReceiverModel CanvasItemReceiver { get; set; } - - /// - /// Attempts to load existing data to display - /// - /// - Task TryLoadExistingData(CollectionItemViewModel itemData, CancellationToken cancellationToken); - - /// - Task TryLoadExistingData(CanvasItem canvasFile, BaseContentTypeModel contentType, CancellationToken cancellationToken); - - /// - /// Attempts to delete the file and discard data - /// - /// Hides the delete confirmation dialog, overrides if necessary - /// - Task TryDeleteData(bool hideConfirmation = false); - - /// - /// Frees cached data and disposes the instance - /// - /// - void DiscardData(); - - /// - /// Sets the with appropriate Canvas data - /// - /// - Task SetDataToDataPackage(DataPackage data); - - /// - /// Copies the Canvas data to clipboard - /// - /// - Task CopyData(); - - /// - /// Overrides the reference if possible - /// - /// - Task> PasteOverrideReference(); - } -} diff --git a/ClipboardCanvas/Models/ISearchControlModel.cs b/ClipboardCanvas/Models/ISearchControlModel.cs deleted file mode 100644 index c1c8a12b..00000000 --- a/ClipboardCanvas/Models/ISearchControlModel.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using ClipboardCanvas.Contexts; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Interfaces.Search; - -namespace ClipboardCanvas.Models -{ - public interface ISearchControlModel - { - event EventHandler OnSearchCloseRequestedEvent; - - ISearchItems SearchItems { get; set; } - - bool IsKeyboardAcceleratorEnabled { get; set; } - - void FindNext(); - - void FindPrevious(); - - void OnSearchShown(); - - void OnSearchHidden(); - - void ResetIndex(); - - void RestoreSearchContext(SearchContext searchContext); - - SearchContext ConstructSearchContext(); - } -} diff --git a/ClipboardCanvas/Models/ISuggestedActionsControlModel.cs b/ClipboardCanvas/Models/ISuggestedActionsControlModel.cs deleted file mode 100644 index 1ff0868a..00000000 --- a/ClipboardCanvas/Models/ISuggestedActionsControlModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ClipboardCanvas.ViewModels.UserControls; -using System.Collections.Generic; - -namespace ClipboardCanvas.Models -{ - public interface ISuggestedActionsControlModel - { - bool ShowNoActionsLabelSuppressed { get; set; } - - void SetActions(IEnumerable actions); - - void AddAction(SuggestedActionsControlItemViewModel action); - - void RemoveAction(SuggestedActionsControlItemViewModel action); - - void RemoveActionAt(int index); - - void RemoveAllActions(); - } -} diff --git a/ClipboardCanvas/Models/IWindowTitleBarControlModel.cs b/ClipboardCanvas/Models/IWindowTitleBarControlModel.cs deleted file mode 100644 index 19bcb646..00000000 --- a/ClipboardCanvas/Models/IWindowTitleBarControlModel.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace ClipboardCanvas.Models -{ - public interface IWindowTitleBarControlModel - { - event EventHandler OnSwitchApplicationViewRequestedEvent; - - bool IsInRestrictedAccess { get; set; } - - bool ShowTitleUnderline { get; set; } - - void SetTitleBarForDefaultView(); - - void SetTitleBarForCollectionsView(); - - void SetTitleBarForCanvasView(string collectionName); - - void SetTitleBarForCollectionPreview(string collectionName); - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/BaseJsonSettingsModel.cs b/ClipboardCanvas/Models/JsonSettings/BaseJsonSettingsModel.cs deleted file mode 100644 index 50c60fb3..00000000 --- a/ClipboardCanvas/Models/JsonSettings/BaseJsonSettingsModel.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.IO; -using System.Runtime.CompilerServices; -using System.Collections.Generic; - -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Models.JsonSettings.Implementation; -using ClipboardCanvas.UnsafeNative; -using ClipboardCanvas.Extensions; - -namespace ClipboardCanvas.Models.JsonSettings -{ - /// - /// Clipboard Canvas - /// A base class to easily manage all application's settings. - /// - public abstract class BaseJsonSettingsModel : ISettingsSharingContext - { - #region Protected Members - - protected int registeredMembers = 0; - - protected ISettingsSharingContext settingsSharingContext; - - public IJsonSettingsSerializer JsonSettingsSerializer { get; set; } - - public ISettingsSerializer SettingsSerializer { get; set; } - - #endregion Protected Members - - #region Properties - - private string _FilePath; - public string FilePath - { - get => settingsSharingContext?.FilePath ?? _FilePath; - protected set => _FilePath = value; - } - - private IJsonSettingsDatabase _JsonSettingsDatabase; - public IJsonSettingsDatabase JsonSettingsDatabase - { - get => settingsSharingContext?.JsonSettingsDatabase ?? _JsonSettingsDatabase; - protected set => _JsonSettingsDatabase = value; - } - - #endregion Properties - - #region Events - - public event EventHandler OnSettingChangedEvent; - - #endregion Events - - #region Constructor - - public BaseJsonSettingsModel() - { - } - - public BaseJsonSettingsModel(string filePath) - : this(filePath, null, null, null) - { - } - - public BaseJsonSettingsModel(ISettingsSharingContext settingsSharingContext) - { - RegisterSettingsContext(settingsSharingContext); - Initialize(); - } - - public BaseJsonSettingsModel(string filePath, bool isCachingEnabled, - IJsonSettingsSerializer jsonSettingsSerializer = null, - ISettingsSerializer settingsSerializer = null) - { - this.FilePath = filePath; - Initialize(); - - this.JsonSettingsSerializer = jsonSettingsSerializer; - this.SettingsSerializer = settingsSerializer; - - // Fallback - this.JsonSettingsSerializer ??= new DefaultJsonSettingsSerializer(); - this.SettingsSerializer ??= new DefaultSettingsSerializer(this.FilePath); - - if (isCachingEnabled) - { - this.JsonSettingsDatabase = new CachingJsonSettingsDatabase(this.JsonSettingsSerializer, this.SettingsSerializer); - } - else - { - this.JsonSettingsDatabase = new DefaultJsonSettingsDatabase(this.JsonSettingsSerializer, this.SettingsSerializer); - } - } - - public BaseJsonSettingsModel(string filePath, - IJsonSettingsSerializer jsonSettingsSerializer, - ISettingsSerializer settingsSerializer, - IJsonSettingsDatabase jsonSettingsDatabase) - { - this.FilePath = filePath; - Initialize(); - - this.JsonSettingsSerializer = jsonSettingsSerializer; - this.SettingsSerializer = settingsSerializer; - this.JsonSettingsDatabase = jsonSettingsDatabase; - - // Fallback - this.JsonSettingsSerializer ??= new DefaultJsonSettingsSerializer(); - this.SettingsSerializer ??= new DefaultSettingsSerializer(this.FilePath); - this.JsonSettingsDatabase ??= new DefaultJsonSettingsDatabase(this.JsonSettingsSerializer, this.SettingsSerializer); - } - - #endregion Constructor - - #region Helpers - - protected virtual void Initialize() - { - // Create the file - UnsafeNativeApis.CreateDirectoryFromApp(Path.GetDirectoryName(FilePath), IntPtr.Zero); - UnsafeNativeHelpers.CreateFileForWrite(FilePath, false).CloseFileHandle(); - } - - public virtual bool FlushSettings() - { - return JsonSettingsDatabase.FlushSettings(); - } - - public virtual object ExportSettings() - { - return JsonSettingsDatabase.ExportSettings(); - } - - public virtual bool ImportSettings(object import) - { - return JsonSettingsDatabase.ImportSettings(import); - } - - public bool RegisterSettingsContext(ISettingsSharingContext settingsSharingContext) - { - if (this.settingsSharingContext == null) - { - // Can set only once - this.settingsSharingContext = settingsSharingContext; - return true; - } - - return false; - } - - public ISettingsSharingContext GetSharingContext() - { - registeredMembers++; - return settingsSharingContext ?? this; - } - - public bool GuaranteeAddToList(IList list, T item, string listSettingName) - { - list?.Add(item); - - bool result = Set(list, listSettingName); - return FlushSettings() && result; - } - - public bool GuaranteeAddRangeToList(List list, IEnumerable items, string listSettingName) - { - list?.AddRange(items); - - bool result = Set(list, listSettingName); - return FlushSettings() && result; - } - - public bool GuaranteeRemoveFromList(IList list, T item, string listSettingName) - { - if (!list?.Remove(item) ?? true) - { - return false; - } - - bool result = Set(list, listSettingName); - return FlushSettings() && result; - } - - public virtual void RaiseOnSettingChangedEvent(object sender, SettingChangedEventArgs e) - { - if (settingsSharingContext != null) - { - settingsSharingContext.RaiseOnSettingChangedEvent(sender, e); - } - else - { - OnSettingChangedEvent?.Invoke(sender, e); - } - } - - #endregion Helpers - - #region Get, Set - - protected virtual TValue Get(TValue defaultValue, [CallerMemberName] string propertyName = "") - { - if (string.IsNullOrEmpty(propertyName)) - { - return defaultValue; - } - - return JsonSettingsDatabase.GetValue(propertyName, defaultValue); - } - - protected virtual bool Set(TValue value, [CallerMemberName] string propertyName = "") - { - if (string.IsNullOrEmpty(propertyName)) - { - return false; - } - - if (JsonSettingsDatabase.UpdateKey(propertyName, value)) - { - RaiseOnSettingChangedEvent(this, new SettingChangedEventArgs(propertyName, value)); - return true; - } - - return false; - } - - #endregion Get, Set - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/IJsonSettingsDatabase.cs b/ClipboardCanvas/Models/JsonSettings/IJsonSettingsDatabase.cs deleted file mode 100644 index e0324b7b..00000000 --- a/ClipboardCanvas/Models/JsonSettings/IJsonSettingsDatabase.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace ClipboardCanvas.Models.JsonSettings -{ - public interface IJsonSettingsDatabase - { - Type DataBaseObjectType { get; } - - TValue GetValue(string key, TValue defaultValue = default); - - bool AddKey(string key, object value); - - bool RemoveKey(string key); - - bool UpdateKey(string key, object newValue); - - bool FlushSettings(); - - bool ImportSettings(object import); - - object ExportSettings(); - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/IJsonSettingsSerializer.cs b/ClipboardCanvas/Models/JsonSettings/IJsonSettingsSerializer.cs deleted file mode 100644 index 5ce93048..00000000 --- a/ClipboardCanvas/Models/JsonSettings/IJsonSettingsSerializer.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Models.JsonSettings -{ - public interface IJsonSettingsSerializer - { - string SerializeToJson(object obj); - - T DeserializeFromJson(string json); - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/ISettingsSerializer.cs b/ClipboardCanvas/Models/JsonSettings/ISettingsSerializer.cs deleted file mode 100644 index f418219f..00000000 --- a/ClipboardCanvas/Models/JsonSettings/ISettingsSerializer.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Models.JsonSettings -{ - public interface ISettingsSerializer - { - bool WriteToFile(string json); - - string ReadFromFile(); - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/ISettingsSharingContext.cs b/ClipboardCanvas/Models/JsonSettings/ISettingsSharingContext.cs deleted file mode 100644 index 10ff0f92..00000000 --- a/ClipboardCanvas/Models/JsonSettings/ISettingsSharingContext.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ClipboardCanvas.EventArguments; - -namespace ClipboardCanvas.Models.JsonSettings -{ - public interface ISettingsSharingContext - { - string FilePath { get; } - - IJsonSettingsDatabase JsonSettingsDatabase { get; } - - ISettingsSharingContext GetSharingContext(); - - void RaiseOnSettingChangedEvent(object sender, SettingChangedEventArgs e); - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/Implementation/CachingJsonSettingsDatabase.cs b/ClipboardCanvas/Models/JsonSettings/Implementation/CachingJsonSettingsDatabase.cs deleted file mode 100644 index 75663c7d..00000000 --- a/ClipboardCanvas/Models/JsonSettings/Implementation/CachingJsonSettingsDatabase.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Collections; -using System.Linq; - -namespace ClipboardCanvas.Models.JsonSettings.Implementation -{ - public sealed class CachingJsonSettingsDatabase : DefaultJsonSettingsDatabase, IJsonSettingsDatabase - { - private int _cacheMisses = 0; - - public CachingJsonSettingsDatabase(IJsonSettingsSerializer jsonSettingsSerializer, ISettingsSerializer settingsSerializer) - : base(jsonSettingsSerializer, settingsSerializer) - { - } - - public override TValue GetValue(string key, TValue defaultValue = default) - { - try - { - if (settingsCache.ContainsKey(key)) - { - var value = settingsCache[key]; - if (value is Newtonsoft.Json.Linq.JToken jTokenValue) - { - var objValue = jTokenValue.ToObject(); - settingsCache[key] = objValue; - return objValue; - } - return (TValue)value; - } - else - { - _cacheMisses++; - return base.GetValue(key, defaultValue); - } - } - catch - { - return defaultValue; - } - } - - public override bool AddKey(string key, object value) - { - if (settingsCache.ContainsKey(key)) - { - return false; - } - - _cacheMisses++; - return base.AddKey(key, value); - } - - public override bool RemoveKey(string key) - { - if (!settingsCache.ContainsKey(key)) - { - return false; - } - - _cacheMisses++; - return base.RemoveKey(key); - } - - public override bool UpdateKey(string key, object newValue) - { - if (!settingsCache.ContainsKey(key)) - { - // Doesn't contain setting, add it - return this.AddKey(key, newValue); - } - else - { - object value = settingsCache[key]; - - bool isDifferent; - if (newValue is IEnumerable enumerableNewValue && value is IEnumerable enumerableValue) - { - isDifferent = !enumerableValue.Cast().SequenceEqual(enumerableNewValue.Cast()); - } - else - { - isDifferent = value != newValue; - } - - if (isDifferent) - { - // Values are different, update value and reload the cache - _cacheMisses++; - return base.UpdateKey(key, newValue); - } - else - { - // The cache does not need to be updated, continue - return false; - } - } - } - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultJsonSettingsDatabase.cs b/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultJsonSettingsDatabase.cs deleted file mode 100644 index 50bdd63e..00000000 --- a/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultJsonSettingsDatabase.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; - -namespace ClipboardCanvas.Models.JsonSettings.Implementation -{ - public class DefaultJsonSettingsDatabase : IJsonSettingsDatabase - { - protected Dictionary settingsCache; - - protected readonly IJsonSettingsSerializer jsonSettingsSerializer; - - protected readonly ISettingsSerializer settingsSerializer; - - public Type DataBaseObjectType { get; } - - public DefaultJsonSettingsDatabase(IJsonSettingsSerializer jsonSettingsSerializer, ISettingsSerializer settingsSerializer) - { - this.jsonSettingsSerializer = jsonSettingsSerializer; - this.settingsSerializer = settingsSerializer; - - this.settingsCache = new Dictionary(); - this.DataBaseObjectType = this.settingsCache.GetType(); - } - - protected virtual Dictionary GetNewSettingsCache() - { - string settingsData = settingsSerializer.ReadFromFile(); - - if (string.IsNullOrEmpty(settingsData)) - { - return new Dictionary(); - } - - return jsonSettingsSerializer.DeserializeFromJson>(settingsData) ?? new Dictionary(); - } - - protected virtual bool SaveSettingsCache() - { - string settingsData = jsonSettingsSerializer.SerializeToJson(this.settingsCache); - - return settingsSerializer.WriteToFile(settingsData); - } - - public virtual TValue GetValue(string key, TValue defaultValue = default) - { - try - { - var value = GetObjectValue(key, defaultValue); - if (value is Newtonsoft.Json.Linq.JToken jTokenValue) - { - return jTokenValue.ToObject(); - } - return (TValue)value; - } - catch - { - return defaultValue; - } - } - - private object GetObjectValue(string key, object defaultValue = null) - { - this.settingsCache = GetNewSettingsCache(); - - if (settingsCache.ContainsKey(key)) - { - return settingsCache[key]; - } - else - { - AddKey(key, defaultValue); - return defaultValue; - } - } - - public virtual bool AddKey(string key, object value) - { - this.settingsCache = GetNewSettingsCache(); - - if (!this.settingsCache.ContainsKey(key)) - { - this.settingsCache.Add(key, value); - - return SaveSettingsCache(); - } - - return false; - } - - public virtual bool RemoveKey(string key) - { - this.settingsCache = GetNewSettingsCache(); - - if (this.settingsCache.ContainsKey(key)) - { - this.settingsCache.Remove(key); - - return SaveSettingsCache(); - } - - return false; - } - - public virtual bool UpdateKey(string key, object newValue) - { - this.settingsCache = GetNewSettingsCache(); - - if (!this.settingsCache.ContainsKey(key)) - { - return AddKey(key, newValue); - } - else - { - this.settingsCache[key] = newValue; - - return SaveSettingsCache(); - } - } - - public virtual bool ImportSettings(object import) - { - try - { - // Try convert - settingsCache = (Dictionary)import; - - // Serialize - string serialized = jsonSettingsSerializer.SerializeToJson(this.settingsCache); - - // Write to file - settingsSerializer.WriteToFile(serialized); - - return true; - } - catch (Exception ex) - { - Debug.WriteLine(ex); - Debugger.Break(); - - return false; - } - } - - public virtual bool FlushSettings() - { - try - { - // Serialize - string serialized = jsonSettingsSerializer.SerializeToJson(this.settingsCache); - - // Write to file - settingsSerializer.WriteToFile(serialized); - - return true; - } - catch (Exception ex) - { - Debug.WriteLine(ex); - Debugger.Break(); - - return false; - } - } - - public virtual object ExportSettings() - { - settingsCache = GetNewSettingsCache(); - - return settingsCache; - } - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultJsonSettingsSerializer.cs b/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultJsonSettingsSerializer.cs deleted file mode 100644 index 928b37f2..00000000 --- a/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultJsonSettingsSerializer.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Newtonsoft.Json; - -namespace ClipboardCanvas.Models.JsonSettings.Implementation -{ - public sealed class DefaultJsonSettingsSerializer : IJsonSettingsSerializer - { - public T DeserializeFromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json); - } - catch - { - return default; - } - } - - public string SerializeToJson(object obj) - { - return JsonConvert.SerializeObject(obj, Formatting.Indented); - } - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultSettingsSerializer.cs b/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultSettingsSerializer.cs deleted file mode 100644 index d3706489..00000000 --- a/ClipboardCanvas/Models/JsonSettings/Implementation/DefaultSettingsSerializer.cs +++ /dev/null @@ -1,24 +0,0 @@ -using ClipboardCanvas.UnsafeNative; - -namespace ClipboardCanvas.Models.JsonSettings.Implementation -{ - public class DefaultSettingsSerializer : ISettingsSerializer - { - private readonly string _filePath; - - public DefaultSettingsSerializer(string filePath) - { - this._filePath = filePath; - } - - public string ReadFromFile() - { - return UnsafeNativeHelpers.ReadStringFromFile(_filePath); - } - - public bool WriteToFile(string json) - { - return UnsafeNativeHelpers.WriteStringToFile(_filePath, json); - } - } -} diff --git a/ClipboardCanvas/Models/JsonSettings/Implementation/DerivedTypesJsonSettingsSerializer.cs b/ClipboardCanvas/Models/JsonSettings/Implementation/DerivedTypesJsonSettingsSerializer.cs deleted file mode 100644 index b9c7f8f2..00000000 --- a/ClipboardCanvas/Models/JsonSettings/Implementation/DerivedTypesJsonSettingsSerializer.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace ClipboardCanvas.Models.JsonSettings.Implementation -{ - public sealed class DerivedTypesJsonSettingsSerializer : IJsonSettingsSerializer - { - private readonly JsonSerializerSettings _settings; - - public DerivedTypesJsonSettingsSerializer(ISerializationBinder serializationBinder) - { - _settings = new JsonSerializerSettings() - { - TypeNameHandling = TypeNameHandling.All, - SerializationBinder = serializationBinder, - Formatting = Formatting.Indented - }; - } - - public T DeserializeFromJson(string json) - { - try - { - return JsonConvert.DeserializeObject(json, _settings); - } - catch - { - return default; - } - } - - public string SerializeToJson(object obj) - { - return JsonConvert.SerializeObject(obj, _settings); - } - } -} diff --git a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.de-DE.xlf b/ClipboardCanvas/MultilingualResources/ClipboardCanvas.de-DE.xlf deleted file mode 100644 index 7aec9ed8..00000000 --- a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.de-DE.xlf +++ /dev/null @@ -1,710 +0,0 @@ - - - -
- -
- - - - Add a collection - Eine Sammlung hinzufügen - - - The app will need to be restarted in order to apply the changes. - Das Programm muss neu gestartet werden, um die Änderungen anzuwenden. - - - Autopaste - Autoeinfügen - - - Add rule - Regel hinzufügen - - - Content is being pasted - Inhalt wird eingefügt - - - The content has been pasted - Der Inhalt wurde eingefügt - - - Autopaste was unable to paste content. Error: {0} - Autoeinfügen konnte den Inhalt nicht einfügen. Fehler: {0} - - - Exclude type - Typ auschließen - - - Autopaste pasted successfully - Autoeinfügen erfolgreich - - - Autopaste is disabled - Autoeinfügen ist deaktiviert - - - Larger than - Größer als - - - No target - Kein Ziel - - - Paste to: - Einfügen in: - - - Autopaste failed - Autoeinfügen fehlgeschlagen - - - File size... - Dateigröße... - - - Rule set - Regelsatz - - - Type filter... - Filter eingeben... - - - Smaller than - Kleiner als - - - File - Datei - - - Folder - Ordner - - - Image - Bild - - - Text - Text - When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed. - - - Url - Url - When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed. - - - Autopaste is working - Autoeinfügen arbeitet - - - Cancel - Abbrechen - - - You're in Infinite Canvas mode - Du bist im 'Unbegrenzte Leinwand'-Modus - - - You're in One Canvas mode - Du bist im 'Eine Leinwand'-Modus - - - Change - Ändern - - - Change icon - Icon ändern - - - Fetching data from GitHub - Ruft Daten aus GitHub ab - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - Beim Versuch des Abrufes der Versionshinweise aus GitHub ist ein Fehler aufgetreten - - - Clipboard Canvas has been updated! - Clipboard Canvas wurde aktualisiert! - - - View on GitHub - In GitHub ansehen - - - Report this issue - Dieses Problem melden - - - We've encountered an issue that we couldn't recover from. - Wir sind auf ein Problem gestoßen von dem wir uns nicht erholen konnten. - - - Clipboard Canvas crashed spectacularly! - Clipboard Canvas ist spektakulär abgestürzt! - - - Close Search - Suche schließen - - - {0} Error: {1} - {0} Fehler: {1} - - - The folder associated with this collection was not found. - Der mit dieser Sammlung assoziierte Ordner konnte nicht gefunden werden. - - - The Collection is being initialized - Die Sammlung wird initialisiert - - - We've noticed some items went missing. We're reloading the Collection for you. - Wir haben festgestellt, dass einige Gegenstände fehlen. Wir laden die Sammlung für dich neu. - - - Collection Preview: - Sammlungsvorschau: - - - Collections - Sammlungen - - - Double click to open this Collection. -Right click for more options. - Doppelklick zum Öffnen dieser Sammlung. -Rechtsklick für mehr Optionen. - - - Collection unavailable - Sammlung unverfügbar - - - Continue in Restricted Access - Im beschränkten Zugang fortfahren - - - Copy file - Datei kopieren - - - Copy selected text - Ausgewählten Text kopieren - - - Current icon could not be deleted. - Aktuelles Icon konnte nicht gelöscht werden. - - - Couldn't remove icon. - Icon konnte nicht entfernt werden - - - Couldn't rename Collection - Sammlung konnte nicht umbenannt werden - - - Couldn't set custom Collection icon. - Eigenes Sammlungsicon konnte nicht gesetzt werden - - - Current Collection: - Aktuelle Sammlung - - - Default Collection - Standardsammlung - - - Delete - Löschen - - - Delete file - Datei löschen - - - Delete Infinite Canvas - Unbegrenzte Leinwand löschen - - - Delete item - Gegenstand löschen - - - Are you sure you want to delete this item? - Bist du sicher, dass du diesen Gegenstand löschen möchtest? - - - Permanently delete - Dauerhaft löschen - - - Delete Reference - Referenz löschen - - - Drag and drop or paste to add content - Ziehen und loslassen zum Einfügen von Inhalten - - - Recently pasted items will show up on your Timeline here - Kürzlich eingefügte Gegenstände tauchen hier auf deiner Zeitleiste auf. - - - Enable Autopaste - Autoeinfügen aktivieren - - - Error - Fehler - - - Error whilst overriding reference. Error: {0} - Fehler beim Überschreiben der Referenz. Fehler: {0} - - - File size rule does not apply to folders. - Dateigrößenregel wird nicht auf Ordner angewandt. - - - Find next - Nächste finden - - - Find previous - Vorherige finden - - - Right click desired collection and set it as an autopaste target. - Rechtsklicke gewünschte Sammlung und setze sie als ein Autoeinfügen-Ziel - - - Select autopaste target - Autoeinfügen-Ziel auswählen - - - Infinite Canvas is empty - Unbegrenzte Leinwand ist leer - - - Invalid file. - Ungültige Datei. - - - There are no items to preview. - Es gibt keine Gegenstände zur Vorschau. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - Wechsle in die Vogelperspektive deiner Dateien. Lokalisiere schnell was du brauchst, dank der Suchfunktion in der Sammlungsvorschau. - - - Preview your Collections - Vorschau deiner Sammlung - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - Nutze Sammlungen, um dich rasch in deinen Arbeitsbereichen umherzubewegen. Passe Sie entsprechend deinen Wünschen an. Gruppiere deine Arbeit in getrennten Ordnern. - - - Manage your workspace using Collections - Verwalte deinen Arbeitsbereich mithilfe von Sammlungen - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - Du bist nun bereit, Clipboard Canvas zu nutzen! Du kannst deine App-Erfahrung in den Einstellungen anpassen. - - - You're good to go! - Du bist startklar! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - Betrachte deine Dateien auf der grenzenlosen Leinwand. Die Unbegrenze Leinwand ist deine Desktop-Pinnwand, die dir erlaubt, deine Arbeit in flexibler Manier zu verwalten. Ziehe deine eingefügten Dateien umher und übernimm die volle Kontrolle über sie. - - - Infinite Canvas - Unbegrenzte Leinwand - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - Füge schnell Inhalt in deine 'Eine Leinwand' ein und interagiere mit ihm. 'Eine Leinwand' gibt dir eine vollformatige, interaktive Vorschau verschiedenster Dateien: - -- Bildvorschau -- Medienvorschau -- Textvorschau -- Markdown-Format-Vorschau -- Ordner- und Datei-Vorschau - - - One Canvas - 'Eine Leinwand' - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - Mit Referenz-Dateien brauchst du dich nicht um eine volle Festplatte zu sorgen. Referenzierte Dateien sparen Platz, indem sie eine auf die Originaldatei verweisende Referenz speichern. Dank Clipboard Canvas' nahtloser Integration funktionieren referenzierte Dateien sowohl in der 'Einen Leinwand' sowie der 'Unbegrenzten Leinwand' einwandfrei. - - - Save storage space with Reference Files - Spare Speicherplatz mit Referenz-Dateien - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - Verpasse keine(n) Datei oder Ordner mit der Zeitleiste auf deiner Startseite. Die Zeitleiste verfolgt kürzlich eingefügte Gegenstände, damit du dir keine Sorgen vor irgendetwas Unbemerktem machen musst. - - - See a run-down of recent activity on your Timeline - Erhalte eine Analyse der kürzlichen Aktivitäten auf deiner Zeitleiste - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - Danke, dass du Clipboard Canvas ausprobierst! Um dir den Start zu erleichtern, wird dich diese Präsentation durch die wichtigsten Funktionen dieses Programms führen. - - - Welcome to Clipboard Canvas! - Welcome to Clipboard Canvas! - When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed. - - - Open canvas - Leinwand öffnen - - - Open Collection location - Sammlungsort öffnen - - - Open containing folder - Enthaltenden Ordner öffnen - - - Open file - Datei öffnen - - - Open Infinite Canvas folder - 'Unbegrenzte Leinwand'-Ordner öffnen - - - Open new Canvas - Neue Leinwand öffnen - - - Open new Infinite Canvas - Neue 'Unbegrenzte Leinwand' öffnen - - - Open reference containing folder - Referenz-enthaltenden Ordner öffnen - - - Open Settings - Einstellungen öffnen - - - The operation was canceled. - Der Vorgang wurde abgebrochen. - - - Paste reference - Referenz einfügen - - - File pasted as reference - Datei als Referenz eingefügt - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - Diese Datei wurde als Referenz auf die Originaldatei eingefügt. Clipboard Canvas lädt die referenzierte Originialdatei. - -Du kannst die Referenz überschreiben und den Gegenstand direkt in diese Sammlung kopieren, indem du den unteren Knopf drückst. - - - Paste from Clipboard - Aus der Zwischenablage einfügen - - - Reference Files - Referenz-Dateien - - - Reload Collection - Sammlung neu laden - - - Remove Collection - Sammlung entfernen - - - Remove from this section - Aus dieser Sammlung entfernen - - - Remove icon - Icon entfernen - - - Rename - Umbenennen - - - Reset item positions - Gegenstandspositionen zurücksetzen - - - Restart Application - Programm neustarten - - - Restricted Access - Beschränkter Zugang - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - Clipboard Canvas benötigt die Berechtigung, auf das Dateisystem zuzugreifen, um richtig zu funktionieren. Ohne die Berechtigung werden einige Funktionen gesperrt oder limitiert. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - Du kannst die Berechtigung in den Einstellungen erteilen, woraufhin das Programm geschlossen wird. - - - You can also continue in Restricted Access mode with limited features. - Du kannst auch im 'Beschränkter Zugang'-Modus fortfahren. Klicke für mehr Informationen. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - Clipboard Canvas ist zurzeit im 'Beschränkter Zugang'-Modus. Klicke für mehr Informationen. - - - Retry - Erneut versuchen - - - Search - Suche - - - Select all - Alles auswählen - - - Set as Autopaste target - Als Autoeinfügen-Ziel setzen - - - Settings - Einstellungen - - - About - Über - - - Version {0} - Version {0} - When the XLIFF file support was added via MAT, existing resources were found and auto-imported. This source and target string contained the same value so the resource was marked as 'Needs review' to ensure the translation could be easily reviewed. - - - Open log file location - Protokolldateien-Speicherort öffnen - - - Privacy Policy - Datenschutzerklärung - - - An error occurred while trying to load privacy policy - Beim Laden der Datenschutzerklärung ist ein Fehler aufgetreten - - - Pulling Clipboard Canvas' privacy policy from GitHub - Lädt Clipboard Canvas' Datenschutzerklärung aus GitHub - - - Release notes - Versionshinweise - - - Star Clipboard Canvas on GitHub - Clipboard Canvas in GitHub einen Stern geben - - - Submit feedback - Rückmeldung abgeben - - - View introduction page - Einführungsansicht anzeigen - - - General - Allgemein - - - Windows default - Windows' Standard - - - Use Infinite Canvas as default - 'Unbegrenzte Leinwand' als Standard nutzen - - - Language - Sprache - - - Permanently delete items as default - Dateien standardmäßig dauerhaft löschen - - - Show confirmation dialog when deleting items - Bestätigungsdialog beim Löschen von Gegenständen anzeigen - - - Show Timeline widget on the Homepage - Zeitleistenwidget auf der Startseite anzeigen - - - Notifications - Benachrichtigungen - - - Show a notification when autopaste fails - Eine Benachrichtigung bei fehlerhaftem Autoeinfügen anzeigen - - - Show a notification when autopaste starts pasting - Eine Benachrichtigung bei beginnendem Autoeinfügen anzeigen - - - Show error notification if app crashes - Bei Programmabstürzen Fehlermeldung anzeigen - - - Pasting - Einfügen - - - Open new canvas on paste - Beim Einfügen eine neue Leinwand öffnen - - - Paste files as reference - Dateien als Referenz einfügen - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - Referenz-Dateien erlauben dir das Einfügen von Dateien ohne Kopien dieser zu erstellen. Wird diese Einstellung aktiviert, wird jede Datei als Referenz eingefügt. - -Eine auf die Originaldatei verweisende Referenz-Datei wird erstellt, welche nahtlos durch Clipboard Canvas dargestellt wird. - - - Cannot enable this setting while in Restricted Access mode. - Diese Einstellung kann im 'Beschränkter Zugang'-Modus nicht aktiviert werden. - - - Use markdown format instead of text files - Markdown-Format statt Textdatei verwenden - - - Show in Collection - In Sammlung anzeigen - - - Status Center - Status-Center - - - Completed 0.00% - 0.00% abgeschlossen - - - The operation was canceled - Der Vorgang wurde abgebrochen - - - Operation canceled - Vorgang abgebrochen - - - The operation is complete - Der Vorgang ist abgeschlossen - - - Operation complete - Vorgang abgeschlossen - - - Overwriting Reference was canceled - Überschreiben der Referenz abgebrochen - - - Overwriting Reference complete - Überschreiben der Referenz erfolgreich - - - Pasting was canceled - Einfügen wurde abgebrochen - - - Pasting complete - Einfügen erfolgreich - - - Completed {0}% - {0}% abgeschlossen - - - Processing... - Arbeitet... - - - Starting... - Startet... - - - Switch to Infinite Canvas - Zur 'Unbegrenzten Leinwand' wechseln - - - Switch to One Canvas - Zur Einen Leinwand' wechseln - - - Timeline - Zeitleiste - - - An unknown error occurred. - Ein unbekannter Fehler ist aufgetreten. - - - View on GitHub - In GitHub ansehen - - - -
-
\ No newline at end of file diff --git a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.de.xlf b/ClipboardCanvas/MultilingualResources/ClipboardCanvas.de.xlf deleted file mode 100644 index bd002606..00000000 --- a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.de.xlf +++ /dev/null @@ -1,706 +0,0 @@ - - - -
- -
- - - - Add a collection - Add a collection - - - The app will need to be restarted in order to apply the changes. - The app will need to be restarted in order to apply the changes. - - - Autopaste - Autopaste - - - Add rule - Add rule - - - Content is being pasted - Content is being pasted - - - The content has been pasted - The content has been pasted - - - Autopaste was unable to paste content. Error: {0} - Autopaste was unable to paste content. Error: {0} - - - Exclude type - Exclude type - - - Autopaste pasted successfully - Autopaste pasted successfully - - - Autopaste is disabled - Autopaste is disabled - - - Larger than - Larger than - - - No target - No target - - - Paste to: - Paste to: - - - Autopaste failed - Autopaste failed - - - File size... - File size... - - - Rule set - Rule set - - - Type filter... - Type filter... - - - Smaller than - Smaller than - - - File - File - - - Folder - Folder - - - Image - Image - - - Text - Text - - - Url - Url - - - Autopaste is working - Autopaste is working - - - Cancel - Cancel - - - You're in Infinite Canvas mode - You're in Infinite Canvas mode - - - You're in One Canvas mode - You're in One Canvas mode - - - Change - Change - - - Change icon - Change icon - - - Fetching data from GitHub - Fetching data from GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - - - Clipboard Canvas has been updated! - Clipboard Canvas has been updated! - - - View on GitHub - View on GitHub - - - Report this issue - Report this issue - - - We've encountered an issue that we couldn't recover from. - We've encountered an issue that we couldn't recover from. - - - Clipboard Canvas crashed spectacularly! - Clipboard Canvas crashed spectacularly! - - - Close Search - Close Search - - - {0} Error: {1} - {0} Error: {1} - - - The folder associated with this collection was not found. - The folder associated with this collection was not found. - - - The Collection is being initialized - The Collection is being initialized - - - We've noticed some items went missing. We're reloading the Collection for you. - We've noticed some items went missing. We're reloading the Collection for you. - - - Collection Preview: - Collection Preview: - - - Collections - Collections - - - Double click to open this Collection. -Right click for more options. - Double click to open this Collection. -Right click for more options. - - - Collection unavailable - Collection unavailable - - - Continue in Restricted Access - Continue in Restricted Access - - - Copy file - Copy file - - - Copy selected text - Copy selected text - - - Current icon could not be deleted. - Current icon could not be deleted. - - - Couldn't remove icon. - Couldn't remove icon. - - - Couldn't rename Collection - Couldn't rename Collection - - - Couldn't set custom Collection icon. - Couldn't set custom Collection icon. - - - Current Collection: - Current Collection: - - - Default Collection - Default Collection - - - Delete - Delete - - - Delete file - Delete file - - - Delete Infinite Canvas - Delete Infinite Canvas - - - Delete item - Delete item - - - Are you sure you want to delete this item? - Are you sure you want to delete this item? - - - Permanently delete - Permanently delete - - - Delete Reference - Delete Reference - - - Drag and drop or paste to add content - Drag and drop or paste to add content - - - Recently pasted items will show up on your Timeline here - Recently pasted items will show up on your Timeline here - - - Enable Autopaste - Enable Autopaste - - - Error - Error - - - Error whilst overriding reference. Error: {0} - Error whilst overriding reference. Error: {0} - - - File size rule does not apply to folders. - File size rule does not apply to folders. - - - Find next - Find next - - - Find previous - Find previous - - - Right click desired collection and set it as an autopaste target. - Right click desired collection and set it as an autopaste target. - - - Select autopaste target - Select autopaste target - - - Infinite Canvas is empty - Infinite Canvas is empty - - - Invalid file. - Invalid file. - - - There are no items to preview. - There are no items to preview. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - - - Preview your Collections - Preview your Collections - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - - - Manage your workspace using Collections - Manage your workspace using Collections - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - - - You're good to go! - You're good to go! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - - - Infinite Canvas - Infinite Canvas - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - - - One Canvas - One Canvas - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - - - Save storage space with Reference Files - Save storage space with Reference Files - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - - - See a run-down of recent activity on your Timeline - See a run-down of recent activity on your Timeline - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - - - Welcome to Clipboard Canvas! - Welcome to Clipboard Canvas! - - - Open canvas - Open canvas - - - Open Collection location - Open Collection location - - - Open containing folder - Open containing folder - - - Open file - Open file - - - Open Infinite Canvas folder - Open Infinite Canvas folder - - - Open new Canvas - Open new Canvas - - - Open new Infinite Canvas - Open new Infinite Canvas - - - Open reference containing folder - Open reference containing folder - - - Open Settings - Open Settings - - - The operation was canceled. - The operation was canceled. - - - Paste reference - Paste reference - - - File pasted as reference - File pasted as reference - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - - - Paste from Clipboard - Paste from Clipboard - - - Reference Files - Reference Files - - - Reload Collection - Reload Collection - - - Remove Collection - Remove Collection - - - Remove from this section - Remove from this section - - - Remove icon - Remove icon - - - Rename - Rename - - - Reset item positions - Reset item positions - - - Restart Application - Restart Application - - - Restricted Access - Restricted Access - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - You can grant this permission by heading to settings, whereupon the app will be closed. - - - You can also continue in Restricted Access mode with limited features. - You can also continue in Restricted Access mode with limited features. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - - - Retry - Retry - - - Search - Search - - - Select all - Select all - - - Set as Autopaste target - Set as Autopaste target - - - Settings - Settings - - - About - About - - - Version {0} - Version {0} - - - Open log file location - Open log file location - - - Privacy Policy - Privacy Policy - - - An error occurred while trying to load privacy policy - An error occurred while trying to load privacy policy - - - Pulling Clipboard Canvas' privacy policy from GitHub - Pulling Clipboard Canvas' privacy policy from GitHub - - - Release notes - Release notes - - - Star Clipboard Canvas on GitHub - Star Clipboard Canvas on GitHub - - - Submit feedback - Submit feedback - - - View introduction page - View introduction page - - - General - General - - - Windows default - Windows default - - - Use Infinite Canvas as default - Use Infinite Canvas as default - - - Language - Language - - - Permanently delete items as default - Permanently delete items as default - - - Show confirmation dialog when deleting items - Show confirmation dialog when deleting items - - - Show Timeline widget on the Homepage - Show Timeline widget on the Homepage - - - Notifications - Notifications - - - Show a notification when autopaste fails - Show a notification when autopaste fails - - - Show a notification when autopaste starts pasting - Show a notification when autopaste starts pasting - - - Show error notification if app crashes - Show error notification if app crashes - - - Pasting - Pasting - - - Open new canvas on paste - Open new canvas on paste - - - Paste files as reference - Paste files as reference - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - - - Cannot enable this setting while in Restricted Access mode. - Cannot enable this setting while in Restricted Access mode. - - - Use markdown format instead of text files - Use markdown format instead of text files - - - Show in Collection - Show in Collection - - - Status Center - Status Center - - - Completed 0.00% - Completed 0.00% - - - The operation was canceled - The operation was canceled - - - Operation canceled - Operation canceled - - - The operation is complete - The operation is complete - - - Operation complete - Operation complete - - - Overwriting Reference was canceled - Overwriting Reference was canceled - - - Overwriting Reference complete - Overwriting Reference complete - - - Pasting was canceled - Pasting was canceled - - - Pasting complete - Pasting complete - - - Completed {0}% - Completed {0}% - - - Processing... - Processing... - - - Starting... - Starting... - - - Switch to Infinite Canvas - Switch to Infinite Canvas - - - Switch to One Canvas - Switch to One Canvas - - - Timeline - Timeline - - - An unknown error occurred. - An unknown error occurred. - - - View on GitHub - View on GitHub - - - -
-
\ No newline at end of file diff --git a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.pt-PT.xlf b/ClipboardCanvas/MultilingualResources/ClipboardCanvas.pt-PT.xlf deleted file mode 100644 index 2f36d991..00000000 --- a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.pt-PT.xlf +++ /dev/null @@ -1,706 +0,0 @@ - - - -
- -
- - - - Add a collection - Adicionar uma coleção - - - The app will need to be restarted in order to apply the changes. - A aplicação terá de ser reiniciada a fim de aplicar as alterações. - - - Autopaste - Colagem automática - - - Add rule - Adicionar regra - - - Content is being pasted - O conteúdo está a ser colado - - - The content has been pasted - O conteúdo foi colado - - - Autopaste was unable to paste content. Error: {0} - A colagem automática não conseguiu colar o conteúdo. Erro: {0} - - - Exclude type - Excluir tipo - - - Autopaste pasted successfully - Colagem automática colada com sucesso - - - Autopaste is disabled - Colagem automática está desativado - - - Larger than - Maior do que - - - No target - Sem alvo - - - Paste to: - Colar para: - - - Autopaste failed - Colagem automática falhou - - - File size... - Tamanho do ficheiro... - - - Rule set - Conjunto de regras - - - Type filter... - Tipo de filtro... - - - Smaller than - Menor do que - - - File - Ficheiro - - - Folder - Pasta - - - Image - Imagem - - - Text - Texto - - - Url - Url - - - Autopaste is working - Colagem automática está a trabalhar - - - Cancel - Cancelar - - - You're in Infinite Canvas mode - Está no modo Tela Infinita - - - You're in One Canvas mode - Está no modo de Tela Única - - - Change - Mudar - - - Change icon - Mudar ícone - - - Fetching data from GitHub - Obtendo dados de GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - Ocorreu um erro ao tentar obter as notas de lançamento da Clipboard Canvas do GitHub - - - Clipboard Canvas has been updated! - Clipboard Canvas foi atualizado! - - - View on GitHub - Ver no GitHub - - - Report this issue - Reportar este problema - - - We've encountered an issue that we couldn't recover from. - Encontrámos um problema do qual não pudemos recuperar. - - - Clipboard Canvas crashed spectacularly! - Clipboard Canvas caiu de forma espetacular! - - - Close Search - Fechar Pesquisa - - - {0} Error: {1} - {0} Erro: {1} - - - The folder associated with this collection was not found. - A pasta associada a esta coleção não foi encontrada. - - - The Collection is being initialized - A Coleção está a ser inicializada - - - We've noticed some items went missing. We're reloading the Collection for you. - Notamos que alguns artigos desapareceram. Estamos a recarregar a coleção para si. - - - Collection Preview: - Pré-visualização da coleção: - - - Collections - Coleções - - - Double click to open this Collection. -Right click for more options. - Duplo clique para abrir esta coleção. -Clique com o botão direito do rato para mais opções. - - - Collection unavailable - Coleção indisponível - - - Continue in Restricted Access - Continuar em Acesso Restrito - - - Copy file - Copiar ficheiro - - - Copy selected text - Copiar texto selecionado - - - Current icon could not be deleted. - O ícone atual não pode ser eliminado. - - - Couldn't remove icon. - Não foi possível remover o ícone. - - - Couldn't rename Collection - Não foi possível mudar o nome da Coleção - - - Couldn't set custom Collection icon. - Não foi possível definir o ícone personalizado da Coleção. - - - Current Collection: - Coleção atual: - - - Default Collection - Coleção predefinida - - - Delete - Eliminar - - - Delete file - Eliminar ficheiro - - - Delete Infinite Canvas - Eliminar Tela Infinita - - - Delete item - Eliminar item - - - Are you sure you want to delete this item? - Tem a certeza de que quer eliminar este item? - - - Permanently delete - Eliminar permanentemente - - - Delete Reference - Eliminar Referência - - - Drag and drop or paste to add content - Arrastar e largar ou colar para adicionar conteúdo - - - Recently pasted items will show up on your Timeline here - Itens colados recentemente aparecerão na sua Linha do Tempo aqui - - - Enable Autopaste - Ativar Colagem automática - - - Error - Erro - - - Error whilst overriding reference. Error: {0} - Erro ao anular a referência. Erro: {0} - - - File size rule does not apply to folders. - A regra do tamanho do ficheiro não se aplica a pastas. - - - Find next - Localizar seguinte - - - Find previous - Localizar anterior - - - Right click desired collection and set it as an autopaste target. - Clique com o botão direito do rato na coleção desejada e defina-a como um alvo de colagem automática. - - - Select autopaste target - Selecione um alvo para a colagem automática - - - Infinite Canvas is empty - A Tela Infinita está vazia - - - Invalid file. - Ficheiro inválido. - - - There are no items to preview. - Não há itens para pré-visualizar. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - Obtenha uma vista aérea dos seus ficheiros. Localize rapidamente o que precisa graças à função de pesquisa na Pré-visualização da coleção. - - - Preview your Collections - Pré-visualize as suas Coleções - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - Utilize as Coleções para se deslocar rapidamente nos seus espaços de trabalho. Personalize as coleções de acordo com as suas necessidades. Agrupe o seu trabalho em pastas separadas. - - - Manage your workspace using Collections - Gere o seu espaço de trabalho utilizando Coleções - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - Está agora pronto para começar a usar Clipboard Canvas! Pode personalizar a sua experiência na aplicação, dirigindo-se às Definições. - - - You're good to go! - Está pronto para ir! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - Veja os seus ficheiros numa tela sem limites. Tela Infinita é o seu quadro de adesivos no computador que lhe permite gerir o seu trabalho de uma forma flexível. Arraste os seus ficheiros colados e assuma um controlo total dos mesmos. - - - Infinite Canvas - Tela Infinita - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - Cole e interaja rapidamente com o seu conteúdo na Tela Única. Tela Única dá-lhe uma pré-visualização interativa de vários ficheiros em tamanho real: - - - Pré-visualização de imagem - - Pré-visualização dos meios de comunicação - - Pré-visualização do texto - - Pré-visualização do formato Markdown - - Pré-visualização de pastas e ficheiros - - - One Canvas - Tela Única - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - Com Ficheiros de Referência não tem de se preocupar em encher o seu disco rígido. Os Ficheiros de Referência poupam espaço ao manter uma referência que aponta para o ficheiro original. Graças à integração perfeita do Clipboard Canvas, os Ficheiros de Referência funcionam bem tanto na Tela Única como na Tela Infinita. - - - Save storage space with Reference Files - Guardar espaço de armazenamento com Ficheiros de Referência - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - Nunca perca um ficheiro ou pasta com a Linha do Tempo na sua página inicial. A Linha do Tempo mantém um registo dos itens recentemente colados para que não tenha de se preocupar com nada que passe despercebido! - - - See a run-down of recent activity on your Timeline - Veja um resumo da atividade recente na sua Linha do Tempo - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - Obrigado por experimentar Clipboard Canvas! Para começar, esta apresentação irá guiá-lo através das características mais notáveis da aplicação. - - - Welcome to Clipboard Canvas! - Bem-vindo ao Clipboard Canvas! - - - Open canvas - Abrir tela - - - Open Collection location - Abrir localização da Coleção - - - Open containing folder - Abrir pasta contentora - - - Open file - Abrir ficheiro - - - Open Infinite Canvas folder - Abrir pasta Tela Infinita - - - Open new Canvas - Abrir nova Tela - - - Open new Infinite Canvas - Abrir nova Tela Infinita - - - Open reference containing folder - Abrir pasta de referência contentora - - - Open Settings - Abrir Definições - - - The operation was canceled. - A operação foi cancelada. - - - Paste reference - Colar referência - - - File pasted as reference - Ficheiro colado como referência - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - Este ficheiro foi colado como uma referência ao ficheiro original. Clipboard Canvas carrega o ficheiro original para o qual a referência está a apontar. - -Pode anular a referência e copiar o item diretamente para esta coleção, premindo o botão abaixo. - - - Paste from Clipboard - Colar a partir da Área de transferência - - - Reference Files - Ficheiros de Referência - - - Reload Collection - Recarregar Coleção - - - Remove Collection - Remover Coleção - - - Remove from this section - Remover desta secção - - - Remove icon - Remover ícone - - - Rename - Mudar o nome - - - Reset item positions - Repor as posições do item - - - Restart Application - Reiniciar Aplicação - - - Restricted Access - Acesso Restrito - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - Clipboard Canvas requer permissão para aceder ao sistema de ficheiros para que este funcione corretamente. Sem a permissão, algumas características serão desativadas e/ou limitadas. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - Pode conceder esta permissão dirigindo-se às definições, após o que a aplicação será encerrada. - - - You can also continue in Restricted Access mode with limited features. - Também pode continuar no modo de Acesso Restrito com características limitadas. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - Clipboard Canvas está atualmente em modo de Acesso Restrito. Clique para mais detalhes. - - - Retry - Tentar novamente - - - Search - Pesquisar - - - Select all - Selecionar tudo - - - Set as Autopaste target - Definir como alvo da Colagem automática - - - Settings - Definições - - - About - Acerca de - - - Version {0} - Versão {0} - - - Open log file location - Abrir localização do ficheiro de registo - - - Privacy Policy - Política de Privacidade - - - An error occurred while trying to load privacy policy - Ocorreu um erro ao tentar carregar a política de privacidade - - - Pulling Clipboard Canvas' privacy policy from GitHub - Puxando a política de privacidade do Clipboard Canvas do GitHub - - - Release notes - Notas de lançamento - - - Star Clipboard Canvas on GitHub - Estrelar Clipboard Canvas no Github - - - Submit feedback - Submeter feedback - - - View introduction page - Ver página de introdução - - - General - Geral - - - Windows default - Predefinição do Windows - - - Use Infinite Canvas as default - Utilizar Tela Infinita como predefinição - - - Language - Idioma - - - Permanently delete items as default - Eliminar permanentemente os itens como predefinição - - - Show confirmation dialog when deleting items - Mostrar diálogo de confirmação ao eliminar ficheiros - - - Show Timeline widget on the Homepage - Mostrar o widget Linha do Tempo na Página inicial - - - Notifications - Notificações - - - Show a notification when autopaste fails - Mostrar uma notificação quando a colagem automática falha - - - Show a notification when autopaste starts pasting - Mostrar uma notificação quando a colagem automática inicia a colagem - - - Show error notification if app crashes - Mostrar notificação de erro se a aplicação falhar - - - Pasting - Colagem - - - Open new canvas on paste - Abrir nova tela ao colar - - - Paste files as reference - Colar ficheiros como referência - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - Os Ficheiros de Referência permitem-lhe colar ficheiros sem criar cópias dos mesmos. Com esta definição ativada, cada ficheiro é colado como uma referência. - -É criado um ficheiro de referência apontando para o ficheiro original, que é exibido sem problemas pelo Clipboard Canvas. - - - Cannot enable this setting while in Restricted Access mode. - Não é possível ativar esta definição enquanto estiver no modo de Acesso Restrito. - - - Use markdown format instead of text files - Utilizar o formato Markdown em vez de ficheiros de texto - - - Show in Collection - Mostrar na Coleção - - - Status Center - Centro de Estado - - - Completed 0.00% - Completado 0.00% - - - The operation was canceled - A operação foi cancelada - - - Operation canceled - Operação cancelada - - - The operation is complete - A operação foi completada - - - Operation complete - Operação completa - - - Overwriting Reference was canceled - Sobrescrita de Referência foi cancelado - - - Overwriting Reference complete - Sobrescrita de Referência completa - - - Pasting was canceled - Colagem foi cancelado - - - Pasting complete - Colagem completa - - - Completed {0}% - Completado {0}% - - - Processing... - Processando... - - - Starting... - A Iniciar... - - - Switch to Infinite Canvas - Trocar para Tela Infinita - - - Switch to One Canvas - Trocar para Tela Única - - - Timeline - Linha do tempo - - - An unknown error occurred. - Ocorreu um erro desconhecido. - - - View on GitHub - Ver no GitHub - - - -
-
\ No newline at end of file diff --git a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.ro-RO.xlf b/ClipboardCanvas/MultilingualResources/ClipboardCanvas.ro-RO.xlf deleted file mode 100644 index a96e4cdf..00000000 --- a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.ro-RO.xlf +++ /dev/null @@ -1,706 +0,0 @@ - - - -
- -
- - - - Add a collection - Adaugă o colecție - - - The app will need to be restarted in order to apply the changes. - Pentru a aplica schimbările va fi nevoie de o repornire a aplicației. - - - Autopaste - Autolipire - - - Add rule - Adaugă o regulă - - - Content is being pasted - Conținutul este în curs de lipire - - - The content has been pasted - Conținutul a fost lipit - - - Autopaste was unable to paste content. Error: {0} - Autolipirea nu a putut lipi conținutul. Eroare: {0} - - - Exclude type - Excludere tip - - - Autopaste pasted successfully - Autolipirea a lipit cu succes - - - Autopaste is disabled - Autolipirea este dezactivată - - - Larger than - Mai mare decât - - - No target - Fără țintă - - - Paste to: - Lipire în: - - - Autopaste failed - Autolipirea a eșuat - - - File size... - Mărime fișier... - - - Rule set - Set de reguli - - - Type filter... - Filtru tip... - - - Smaller than - Mai mic decât - - - File - Fișier - - - Folder - Folder - - - Image - Imagine - - - Text - Text - - - Url - URL - - - Autopaste is working - Autolipirea funcționează - - - Cancel - Anulare - - - You're in Infinite Canvas mode - Ești în modul Canvas Infinit - - - You're in One Canvas mode - Ești în modul un Canvas - - - Change - Modificare - - - Change icon - Modificare pictogramă - - - Fetching data from GitHub - Preluare date de la GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - Am întâmpinat o eroare încercând să preluăm notele de lansare Clipboard Canvas de pe GitHub - - - Clipboard Canvas has been updated! - Clipboard Canvas a fost actualizat! - - - View on GitHub - Vezi pe GitHub - - - Report this issue - Raportează această problemă - - - We've encountered an issue that we couldn't recover from. - Am întâmpinat o problemă din care n-am putut să ne revenim. - - - Clipboard Canvas crashed spectacularly! - Clipboard Canvas a avut un accident spectaculos! - - - Close Search - Închidere Căutare - - - {0} Error: {1} - {0} Eroare: {1} - - - The folder associated with this collection was not found. - Folderul asociat cu această colecție nu a fost găsit. - - - The Collection is being initialized - Colecția este în curs de inițializare - - - We've noticed some items went missing. We're reloading the Collection for you. - Am văzut că unele elemente au fost date dispărute. Reîncărcăm Colecția pentru tine. - - - Collection Preview: - Previzualizare Colecție: - - - Collections - Colecții - - - Double click to open this Collection. -Right click for more options. - Dublu-clic pentru a deschide această Colecție. -Clic-dreapta pentru mai multe opțiuni. - - - Collection unavailable - Colecție indisponibilă - - - Continue in Restricted Access - Continuă în Acces restricționat - - - Copy file - Copiere fișier - - - Copy selected text - Copiere text selectat - - - Current icon could not be deleted. - Pictograma curentă nu a putut fi ștearsă. - - - Couldn't remove icon. - Nu s-a putut șterge pictograma. - - - Couldn't rename Collection - Nu s-a putut redenumi Colecția - - - Couldn't set custom Collection icon. - Nu s-a putut seta o pictogramă personalizată pentru Colecție. - - - Current Collection: - Colecția curentă: - - - Default Collection - Colecția implicită - - - Delete - Ștergere - - - Delete file - Ștergere fișier - - - Delete Infinite Canvas - Ștergere Canvas Infinit - - - Delete item - Ștergere element - - - Are you sure you want to delete this item? - Sigur vrei să ștergi acest element? - - - Permanently delete - Ștergere definitivă - - - Delete Reference - Ștergere Referință - - - Drag and drop or paste to add content - Drag și drop sau lipește pentru a adăuga conținut - - - Recently pasted items will show up on your Timeline here - Elemente lipite recent vor apărea în Cronologie, chiar aici - - - Enable Autopaste - Activare autolipire - - - Error - Eroare - - - Error whilst overriding reference. Error: {0} - Eroare în timpul suprascrierii referinței. Eroare: {0} - - - File size rule does not apply to folders. - Regula mărimii fișierelor nu se aplică la foldere. - - - Find next - Găsire următor - - - Find previous - Găsire precedent - - - Right click desired collection and set it as an autopaste target. - Clic-dreapta pe colecția dorită și seteaz-o ca o țintă pentru autolipire. - - - Select autopaste target - Selectare țintă autolipire - - - Infinite Canvas is empty - Canvasul Infinit este gol - - - Invalid file. - Fișier invalid. - - - There are no items to preview. - Nu există elemente de previzualizat. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - Ia o privire scurtă la fișierele tale. Lochează rapid toate fișierele de care ai nevoie mulțumită funcției de căutare în Previzualizare Colecție. - - - Preview your Collections - Previzualizează-ți Colecțiile - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - Utilizează Colecții pentru a te muta cu elan printre spații de lucru. Personalizează colecțiile nevoilor tale. Grupează-ți munca în foldere separate. - - - Manage your workspace using Collections - Ești gata să folosești Clipboard Canvas! Îți poți personaliza experiența în Setări. - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - Ești gata să folosești Clipboard Canvas! Îți poți personaliza experiența în aplicație în Setări. - - - You're good to go! - Ești gata de plecare! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - Vezi fișierele tale pe un canvas fără limite. Pe bune. Canvasul Infinit este stickyboard-ul ecranului tău care te lasă să-ți gestionezi munca într-o manieră flexibilă. - - - Infinite Canvas - Canvas Infinit - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - Lipește și interacționează rapid cu conținutul tău pe un Canvas. Un Canvas îți dă o previzualizare interactivă în mărime-completă a diverse fișiere: - - - Previzualizare imagini - - Previzualizare media - - Previzualizare text - - Previzualizare format markdown - - Previzualizare folder și fișiere - - - One Canvas - Un Canvas - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - Cu Fișiere de Referință, nu te îngrijora despre spațiu de stocare. Ele salvează spațiu ținând o referință care punctează la fișierul original. Mulțumită integrării fără-efort Clipboard Canvas, Fișierele de Referință merg bine și pe un Canvas, dar și pe Canvasul Infinit. - - - Save storage space with Reference Files - Salvează spațiu de stocare cu Fișiere de Referință - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - Nu rata un fișier sau folder mulțumită Cronologiei de pe pagina de pornire. Cronologia are grijă de elemente lipite recent ca tu să n-ai grijă despre fișiere ratate! - - - See a run-down of recent activity on your Timeline - Vezi o analiză a activității recente în Cronologia ta - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - Îți mulțumim pentru că încerci Clipboard Canvas! Ca să știi tot-tot, această prezentare te va ghida printre cele mai notabile funcționalități ale aplicației. - - - Welcome to Clipboard Canvas! - Bun venit la Clipboard Canvas! - - - Open canvas - Deschidere canvas - - - Open Collection location - Deschidere locație Colecție - - - Open containing folder - Deschidere folder conținut - - - Open file - Deschidere fișier - - - Open Infinite Canvas folder - Deschidere folder Canvas Infinit - - - Open new Canvas - Deschidere Canvas nou - - - Open new Infinite Canvas - Deschidere Canvas Infinit nou - - - Open reference containing folder - Deschidere folder care conține referința - - - Open Settings - Deschidere Setări - - - The operation was canceled. - Operația a fost anulată. - - - Paste reference - Lipire referință - - - File pasted as reference - Fișier lipit ca referință - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - Acest fișier a fost lipit ca o referință a fișierului original. Clipboard Canvas încarcă fișierul original spre care punctează referința. - -Poți suprascrie referința și copia elementul direct în această colecție apăsând butonul de mai jos. - - - Paste from Clipboard - Lipire din Clipboard - - - Reference Files - Fișiere de Referință - - - Reload Collection - Reîncărcare Colecție - - - Remove Collection - Ștergere Colecție - - - Remove from this section - Ștergere din această secțiune - - - Remove icon - Ștergere pictogramă - - - Rename - Redenumire - - - Reset item positions - Resetare poziții pictograme - - - Restart Application - Repornire aplicație - - - Restricted Access - Acces restricționat - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - Clipboard Canvas are nevoie de acces la sistemul de fișiere pentru a funcționa normal. Fără permisiune, unele funcționalități vor fi dezactivate și/sau limitate. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - Poți permite asta în Setări, unde aplicația va fi închisă. - - - You can also continue in Restricted Access mode with limited features. - Poți continua în Acces restricționat cu funcționalitate limitată. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - Clipboard Canvas este în Acces restricționat. Clic pentru mai multe detalii. - - - Retry - Încearcă din nou - - - Search - Căutare - - - Select all - Selectare totală - - - Set as Autopaste target - Setare ca țintă autolipire - - - Settings - Setări - - - About - Despre - - - Version {0} - Versiunea {0} - - - Open log file location - Deschidere locație fișier log - - - Privacy Policy - Politică de confidențialitate - - - An error occurred while trying to load privacy policy - Am întâmpinat o eroare încercând să încărcăm politica de confidențialitate - - - Pulling Clipboard Canvas' privacy policy from GitHub - Se preia politica de confidențialitate Clipboard Canvas din GitHub - - - Release notes - Note de lansare - - - Star Clipboard Canvas on GitHub - Star Clipboard Canvas pe GitHub - - - Submit feedback - Trimite feedback - - - View introduction page - Vezi pagina introductivă - - - General - General - - - Windows default - Implicit Windows - - - Use Infinite Canvas as default - Utilizează Canvasul Infinit ca setare implicită - - - Language - Limbă - - - Permanently delete items as default - Șterge elemente definitiv în mod implicit - - - Show confirmation dialog when deleting items - Afișează un dialog de confirmare la ștergerea elementelor - - - Show Timeline widget on the Homepage - Afișează widget Cronologie pe pagina de pornire - - - Notifications - Notificări - - - Show a notification when autopaste fails - Afișează o notificare când autolipirea eșuează - - - Show a notification when autopaste starts pasting - Afișează o notificare când autolipirea începe a lipi - - - Show error notification if app crashes - Afișează o notificare de eroare dacă aplicația are un accident - - - Pasting - Lipire - - - Open new canvas on paste - Deschide un canvas nou la lipire - - - Paste files as reference - Lipește fișierele ca referințe - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - Fișierele de Referință îți permit să lipești fișiere fără să creezi copii ale acestora. Cu această setare activată, fiecare fișier este lipit ca o referință. - -Un fișier de referință este creat punctând la locația fișierului original care este afișat fără efort de către aplicație. - - - Cannot enable this setting while in Restricted Access mode. - Nu se poate activa această setare în modul Acces restricționat. - - - Use markdown format instead of text files - Utilizează formatul markdown în favoarea fișierelor text - - - Show in Collection - Afișează în Colecție - - - Status Center - Centru de stare - - - Completed 0.00% - 0.00% complet - - - The operation was canceled - Operația a fost anulată - - - Operation canceled - Operație anulată - - - The operation is complete - Operația a fost completată - - - Operation complete - Operație completă - - - Overwriting Reference was canceled - Suprascrierea Referinței a fost anulată - - - Overwriting Reference complete - Referința a fost suprascrisă cu succes - - - Pasting was canceled - Lipirea a fost anulată - - - Pasting complete - Lipire completă - - - Completed {0}% - {0}% complet - - - Processing... - Se procesează... - - - Starting... - Se inițializează... - - - Switch to Infinite Canvas - Comută la Canvas Infinit - - - Switch to One Canvas - Comută la un Canvas - - - Timeline - Cronologie - - - An unknown error occurred. - O eroare necunoscută a fost întâmpinată. - - - View on GitHub - Vezi pe GitHub - - - -
-
\ No newline at end of file diff --git a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.ru.xlf b/ClipboardCanvas/MultilingualResources/ClipboardCanvas.ru.xlf deleted file mode 100644 index 69697bff..00000000 --- a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.ru.xlf +++ /dev/null @@ -1,706 +0,0 @@ - - - -
- -
- - - - Add a collection - Добавить коллекцию - - - The app will need to be restarted in order to apply the changes. - Чтобы применить изменения, приложение необходимо перезапустить. - - - Autopaste - Автовставка - - - Add rule - Добавить правило - - - Content is being pasted - Содержимое вставляется - - - The content has been pasted - Содержимое вставлено - - - Autopaste was unable to paste content. Error: {0} - Автовставка не смогла обработать содержимое. Ошибка: {0} - - - Exclude type - Исключить тип - - - Autopaste pasted successfully - Автовставка осуществлена - - - Autopaste is disabled - Автовставка отключена - - - Larger than - Больше, чем - - - No target - Нет цели - - - Paste to: - Вставить в: - - - Autopaste failed - Автовставка не удалась - - - File size... - Размер файла... - - - Rule set - Набор правил - - - Type filter... - Фильтр типа... - - - Smaller than - Меньше, чем - - - File - Файл - - - Folder - Папка - - - Image - Изображение - - - Text - Текст - - - Url - Ссылка - - - Autopaste is working - Автовставка осуществляется - - - Cancel - Отмена - - - You're in Infinite Canvas mode - Вы находитесь в режиме бесконечного полотна - - - You're in One Canvas mode - Вы находитесь в режиме одного полотна - - - Change - Изменить - - - Change icon - Изменить иконку - - - Fetching data from GitHub - Получение данных из GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - Произошла ошибка при попытке получить заметки о выпуске Clipboard Canvas' из GitHub - - - Clipboard Canvas has been updated! - Clipboard Canvas был обновлен! - - - View on GitHub - Просмотреть на GitHub - - - Report this issue - Сообщить о проблеме - - - We've encountered an issue that we couldn't recover from. - Мы столкнулись с проблемой, от которой не смогли оправиться. - - - Clipboard Canvas crashed spectacularly! - Clipboard Canvas драматично упал! - - - Close Search - Закрыть поиск - - - {0} Error: {1} - {0} Ошибка: {1} - - - The folder associated with this collection was not found. - Папка, связанная с этой коллекцией, не найдена. - - - The Collection is being initialized - Коллекция инициализируется - - - We've noticed some items went missing. We're reloading the Collection for you. - Мы заметили, что некоторые объекты пропали. Мы перезагружаем коллекцию для вас. - - - Collection Preview: - Предпросмотр коллекции: - - - Collections - Коллекции - - - Double click to open this Collection. -Right click for more options. - Щелкните дважды, чтобы открыть эту коллекцию. -Щелкните правой кнопкой мыши для получения дополнительных параметров. - - - Collection unavailable - Коллекция недоступна - - - Continue in Restricted Access - Продолжить в ограниченном режиме - - - Copy file - Копировать файл - - - Copy selected text - Копировать выбранный текст - - - Current icon could not be deleted. - Текущая иконка не может быть удалена. - - - Couldn't remove icon. - Не удалось удалить иконку. - - - Couldn't rename Collection - Не удалось переименовать коллекцию - - - Couldn't set custom Collection icon. - Не удалось установить иконку коллекции. - - - Current Collection: - Текущая коллекция: - - - Default Collection - Коллекция по умолчанию - - - Delete - Удалить - - - Delete file - Удалить файл - - - Delete Infinite Canvas - Удалить бесконечное полотно - - - Delete item - Удалить объект - - - Are you sure you want to delete this item? - Вы уверены, что хотите удалить этот объект? - - - Permanently delete - Удалить навсегда - - - Delete Reference - Удалить упоминание - - - Drag and drop or paste to add content - Перетащите или вставьте для добавления содержимого - - - Recently pasted items will show up on your Timeline here - Недавно вставленные объекты будут отображаться на временной шкале здесь - - - Enable Autopaste - Включить автовставку - - - Error - Ошибка - - - Error whilst overriding reference. Error: {0} - Ошибка при переопределении упоминания. Ошибка: {0} - - - File size rule does not apply to folders. - Правило размера файла не применяется к папкам. - - - Find next - Найти следующее - - - Find previous - Найти предыдущее - - - Right click desired collection and set it as an autopaste target. - Щелкните правой кнопкой мыши по коллекции и установите ее в качестве цели автовставки. - - - Select autopaste target - Выберите цель автовставки - - - Infinite Canvas is empty - Бесконечное полотно пусто - - - Invalid file. - Недопустимый файл. - - - There are no items to preview. - Нет объектов для предпросмотра. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - Получите представление о ваших файлах с высоты птичьего полета. Быстро находите то, что вам нужно, благодаря функции поиска в разделе предпросмотра коллекции. - - - Preview your Collections - Предпросмотр ваших коллекций - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - Используйте коллекции для быстрого перемещения по рабочему пространству. Настраивайте коллекции в соответствии со своими потребностями. Группируйте работу в отдельные папки. - - - Manage your workspace using Collections - Управление рабочим пространством с помощью коллекций - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - Теперь вы готовы начать использовать Clipboard Canvas! Вы можете настроить работу с приложением в соответствующем разделе. - - - You're good to go! - Вы готовы к работе! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - Просматривайте свои файлы на бесконечном полотне. Бесконечное полотно представляет собой настольную доску, позволяющую гибко управлять работой. Перетаскивайте вставленные файлы и получайте полный контроль над ними. - - - Infinite Canvas - Бесконечное полотно - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - Быстрая вставка и взаимодействие с содержимым на одном полотне. Одно полотно дает возможность интерактивного предварительного просмотра различных файлов в натуральную величину: - - - Предпросмотр изображений - - Предпросмотр мультимедиа - - Предпросмотр текста - - Предпросмотр формата Markdown - - Предпросмотр папок и файлов - - - One Canvas - Одно полотно - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - С файлами упоминания вам не придется беспокоиться о заполнении жесткого диска. Файлы упоминания экономят место, поскольку содержат ссылку, указывающую на исходный файл. Благодаря бесшовной интеграции с Clipboard Canvas файлы упоминания отлично работают на любом полотне. - - - Save storage space with Reference Files - Экономьте место с файлами упоминания - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - Никогда не пропускайте объекты с временной шкалой на вашей домашней странице. Временная шкала отслеживает недавно вставленные объекты, поэтому вам не придется беспокоиться о том, что файл или папка ускользнет от вашего взора! - - - See a run-down of recent activity on your Timeline - Просмотр последних действий на временной шкале - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - Спасибо, что попробовали Clipboard Canvas! Чтобы вы могли начать работу, в этой презентации мы расскажем о самых важных функциях приложения. - - - Welcome to Clipboard Canvas! - Добро пожаловать в Clipboard Canvas! - - - Open canvas - Открыть полотно - - - Open Collection location - Открыть расположение коллекции - - - Open containing folder - Открыть содержащую папку - - - Open file - Открыть файл - - - Open Infinite Canvas folder - Открыть папку бесконечного полотна - - - Open new Canvas - Открыть новое полотно - - - Open new Infinite Canvas - Открыть новое бесконечное полотно - - - Open reference containing folder - Открыть папку, содержащую упоминания - - - Open Settings - Открыть параметры - - - The operation was canceled. - Операция была отменена. - - - Paste reference - Вставить упоминание - - - File pasted as reference - Файл вставлен как упоминание - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - Этот файл был вставлен как упоминание исходного файла. Clipboard Canvas загружает исходный файл, на который указывает ссылка. - -Вы можете отменить упоминание и скопировать объект непосредственно в эту коллекцию, нажав кнопку ниже. - - - Paste from Clipboard - Вставить из буфера обмена - - - Reference Files - Файлы упоминания - - - Reload Collection - Перезагрузить коллекцию - - - Remove Collection - Удалить коллекцию - - - Remove from this section - Удалить из этого раздела - - - Remove icon - Удалить иконку - - - Rename - Переименовать - - - Reset item positions - Сбросить позицию объектов - - - Restart Application - Перезапустить приложение - - - Restricted Access - Ограниченный доступ - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - Для корректной работы Clipboard Canvas требуется разрешение на доступ к файловой системе. Без этого разрешения некоторые функции будут отключены и/или ограничены. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - Вы можете предоставить это разрешение, перейдя в параметры, после чего приложение будет закрыто. - - - You can also continue in Restricted Access mode with limited features. - Вы также можете продолжить работу в режиме ограниченного доступа с заблокированными функциями. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - В настоящее время Clipboard Canvas находится в режиме ограниченного доступа. Нажмите для получения более подробной информации. - - - Retry - Повторить - - - Search - Поиск - - - Select all - Выбрать все - - - Set as Autopaste target - Установить в качестве цели автовставки - - - Settings - Параметры - - - About - О приложении - - - Version {0} - Версия {0} - - - Open log file location - Открыть логи - - - Privacy Policy - Политика конфиденциальности - - - An error occurred while trying to load privacy policy - В ходе загрузки политики конфиденциальности произошла ошибка - - - Pulling Clipboard Canvas' privacy policy from GitHub - Получение политики конфиденциальности Clipboard Canvas' из GitHub - - - Release notes - Примечания к выпуску - - - Star Clipboard Canvas on GitHub - Отметить Clipboard Canvas на GitHub - - - Submit feedback - Отправить отзыв - - - View introduction page - Просмотреть вводную страницу - - - General - Общие - - - Windows default - Как в системе - - - Use Infinite Canvas as default - Использовать бесконечное полотно по умолчанию - - - Language - Язык - - - Permanently delete items as default - Удаление навсегда по умолчанию - - - Show confirmation dialog when deleting items - Показывать диалог подтверждения при удалении - - - Show Timeline widget on the Homepage - Показывать временную шкалу на домашней странице - - - Notifications - Уведомления - - - Show a notification when autopaste fails - Показывать уведомление при неудачной автовставке - - - Show a notification when autopaste starts pasting - Показывать уведомление, когда начинается автовставка - - - Show error notification if app crashes - Показывать уведомление при сбое приложения - - - Pasting - Вставка - - - Open new canvas on paste - Открывать новое полотно при вставке - - - Paste files as reference - Вставлять объекты как файлы упоминания - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - Файлы упоминания позволяют вставлять объекты без создания их копий. При включении этого параметра каждый объект вставляется как упоминание. - -Файл упоминания, указывающий на исходный объект, создается и беспрепятственно отображается в Clipboard Canvas. - - - Cannot enable this setting while in Restricted Access mode. - Невозможно включить этот параметр в режиме ограниченного доступа. - - - Use markdown format instead of text files - Использовать формат Markdown вместо текстовых файлов - - - Show in Collection - Показывать в коллекции - - - Status Center - Центр состояния - - - Completed 0.00% - Завершено 0.00% - - - The operation was canceled - Операция была отменена - - - Operation canceled - Операция отменена - - - The operation is complete - Операция успешно выполнена - - - Operation complete - Операция выполнена - - - Overwriting Reference was canceled - Переопределение упоминания отменено - - - Overwriting Reference complete - Переопределение упоминания выполнено - - - Pasting was canceled - Вставка была отменена - - - Pasting complete - Вставка успешно выполнена - - - Completed {0}% - Завершено {0}% - - - Processing... - Обработка... - - - Starting... - Начало... - - - Switch to Infinite Canvas - Переключиться на бесконечное полотно - - - Switch to One Canvas - Переключиться на одно полотно - - - Timeline - Временная шкала - - - An unknown error occurred. - Произошла неизвестная ошибка. - - - View on GitHub - Просмотреть на GitHub - - - -
-
\ No newline at end of file diff --git a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.zh-CN.xlf b/ClipboardCanvas/MultilingualResources/ClipboardCanvas.zh-CN.xlf deleted file mode 100644 index 7a553db5..00000000 --- a/ClipboardCanvas/MultilingualResources/ClipboardCanvas.zh-CN.xlf +++ /dev/null @@ -1,705 +0,0 @@ - - - -
- -
- - - - Add a collection - 添加合集 - - - The app will need to be restarted in order to apply the changes. - 需要重新启动应用程序才能应用更改。 - - - Autopaste - 自动粘贴 - - - Add rule - 添加规则 - - - Content is being pasted - 正在粘贴内容 - - - The content has been pasted - 内容已粘贴 - - - Autopaste was unable to paste content. Error: {0} - 自动粘贴无法粘贴该内容。 错误:{0} - - - Exclude type - 排除类型 - - - Autopaste pasted successfully - 自动粘贴成功 - - - Autopaste is disabled - 自动粘贴已关闭 - - - Larger than - 大于 - - - No target - - - - Paste to: - 粘贴到: - - - Autopaste failed - 自动粘贴失败 - - - File size... - 文件大小... - - - Rule set - 规则列表 - - - Type filter... - 类型筛选... - - - Smaller than - 小于 - - - File - 文件 - - - Folder - 文件夹 - - - Image - 图片 - - - Text - 文本 - - - Url - 链接 - - - Autopaste is working - 自动粘贴正在工作 - - - Cancel - 取消 - - - You're in Infinite Canvas mode - 正在使用无限画布模式 - - - You're in One Canvas mode - 正在使用单画布模式 - - - Change - 修改 - - - Change icon - 修改图标 - - - Fetching data from GitHub - 正在从 GitHub 获取数据 - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - 尝试从 GitHub 获取 Clipboard Canvas 的发行说明时出错 - - - Clipboard Canvas has been updated! - Clipboard Canvas 已更新! - - - View on GitHub - 在 GitHub 上查看 - - - Report this issue - 报告此问题 - - - We've encountered an issue that we couldn't recover from. - 出现了无法恢复的问题。 - - - Clipboard Canvas crashed spectacularly! - Clipboard Canvas 出现严重崩溃! - - - Close Search - 关闭搜索 - - - {0} Error: {1} - {0} 错误: {1} - - - The folder associated with this collection was not found. - 找不到与此合集关联的文件夹。 - - - The Collection is being initialized - 正在初始化合集 - - - We've noticed some items went missing. We're reloading the Collection for you. - 检测到部分文件丢失,正在为您重新加载合集。 - - - - Collection Preview: - 预览合集: - - - Collections - 合集 - - - Double click to open this Collection. -Right click for more options. - 双击打开此合集。 -右键单击可查看更多选项。 - - - Collection unavailable - 合集不可用 - - - Continue in Restricted Access - 继续受限访问 - - - Copy file - 复制文件 - - - Copy selected text - 复制所选文本 - - - Current icon could not be deleted. - 无法删除当前图标。 - - - Couldn't remove icon. - 无法删除图标。 - - - Couldn't rename Collection - 无法重命名合集 - - - Couldn't set custom Collection icon. - 无法设置自定义合集图标。 - - - Current Collection: - 当前合集: - - - Default Collection - 默认合集 - - - Delete - 删除 - - - Delete file - 删除文件 - - - Delete Infinite Canvas - 删除无限画布 - - - Delete item - 删除项目 - - - Are you sure you want to delete this item? - 确定删除此项目? - - - Permanently delete - 永久删除 - - - Delete Reference - 删除引用 - - - Drag and drop or paste to add content - 通过拖放或粘贴添加内容 - - - Recently pasted items will show up on your Timeline here - 在时间轴上显示最近粘贴的项目 - - - Enable Autopaste - 开启自动粘贴 - - - Error - 错误 - - - Error whilst overriding reference. Error: {0} - 重写引用时错误. Error: {0} - - - File size rule does not apply to folders. - 文件大小规则不适用于文件夹。 - - - Find next - 查找下一个 - - - Find previous - 查找上一个 - - - Right click desired collection and set it as an autopaste target. - 右键单击所需合集并将其设置为自动粘贴目标。 - - - Select autopaste target - 选择自动粘贴目标 - - - Infinite Canvas is empty - 无限画布为空 - - - Invalid file. - 文件无效。 - - - There are no items to preview. - 没有可预览的项目。 - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - 查找的文件。通过预览合集中的搜索功能,可以快速找到您所需要的内容。 - - - Preview your Collections - 预览你的合集 - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - 使用合集在您的工作区中快速移动。 自定义合集可以满足您的需求。 将工作分组到不同的文件夹中。 - - - Manage your workspace using Collections - 使用合集管理你的工作区 - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - 您现在可以开始使用Clipboard Canvas!了! 您可以通过前往“设置”来自定义您的应用体验。 - - - You're good to go! - 现在开始吧! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - 在无限画布上查看文件。无限画布是您的桌面粘性板,允许您以灵活的方式管理您的工作。拖动粘贴的文件并完全控制它们。 - - - Infinite Canvas - 无限画布 - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - 快速粘贴并与单画布上的内容交互。单画布为您提供各种文件的全尺寸交互式预览: - --图像预览 --媒体预览 --文本预览 --标记格式预览 --文件夹和文件预览 - - - One Canvas - 单画布 - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - 使用“引用文件”,您不必担心硬盘驱动器会被填满。引用文件通过保持指向原始文件的引用来节省空间。得益于Clipboard Canvas的无缝集成,“引用文件”在“单画布”和“无限画布”中都能更好的工作。 - - - Save storage space with Reference Files - 使用引用文件节省存储空间 - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - 千万不要错过主页上带有时间轴的文件或文件夹。时间轴会跟踪最近粘贴的项目,因此您不必担心没有注意而被忽视! - - - See a run-down of recent activity on your Timeline - 在时间轴上查看最近活动的摘要 - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - 感谢您使用剪贴板画布!为了帮助您快速开始,本演示将引导您了解应用程序的最显著的功能。 - - - Welcome to Clipboard Canvas! - 欢迎使用Clipboard Canvas! - - - Open canvas - 打开画布 - - - Open Collection location - 打开合集位置 - - - Open containing folder - 打开包含文件夹 - - - Open file - 打开文件 - - - Open Infinite Canvas folder - 打开无限画布文件夹 - - - Open new Canvas - 打开新画布 - - - Open new Infinite Canvas - 打开新的无限画布 - - - Open reference containing folder - 打开包含文件夹的引用 - - - Open Settings - 打开设置 - - - The operation was canceled. - 操作已取消。 - - - Paste reference - 粘贴引用 - - - File pasted as reference - 作为引用粘贴文件 - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - 此文件已粘贴为对原始文件的引用。Clipboard Canvas加载引用所指向的原始文件。 -通过按下下面的按钮,可以覆盖引用并将项目直接复制到此集合。 - - - Paste from Clipboard - 从剪贴板粘贴 - - - Reference Files - 引用文件 - - - Reload Collection - 重新加载合集 - - - Remove Collection - 删除合集 - - - Remove from this section - 从分区中删除 - - - Remove icon - 删除图标 - - - Rename - 重命名 - - - Reset item positions - 重置项目位置 - - - Restart Application - 重启应用程序 - - - Restricted Access - 受限访问 - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - Clipboard Canvas需要访问文件系统的权限才能正常工作。未经许可,某些功能将被禁用或限制。 - - - You can grant this permission by heading to settings, whereupon the app will be closed. - 您可以通过指向设置授予此权限,然后应用程序将关闭。 - - - You can also continue in Restricted Access mode with limited features. - 您也可以在受限访问模式下继续使用受限功能。 - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - Clipboard Canvas 当前处于受限访问模式。单击了解更多详细信息。 - - - Retry - 重试 - - - Search - 搜索 - - - Select all - 全选 - - - Set as Autopaste target - 设置为自动粘贴目标 - - - Settings - 设置 - - - About - 关于 - - - Version {0} - 版本 {0} - - - Open log file location - 打开日志文件位置 - - - Privacy Policy - 隐私政策 - - - An error occurred while trying to load privacy policy - 尝试加载隐私策略时出错 - - - Pulling Clipboard Canvas' privacy policy from GitHub - 从GitHub中提取剪贴板画布的隐私策略 - - - Release notes - 发行说明 - - - Star Clipboard Canvas on GitHub - Clipboard Canvas在GitHub上的星标数量 - - - Submit feedback - 提交反馈 - - - View introduction page - 查看介绍页 - - - General - 常规 - - - Windows default - Windows默认值 - - - Use Infinite Canvas as default - 使用无限画布作为默认值 - - - Language - 语言 - - - Permanently delete items as default - 永久删除默认项目 - - - Show confirmation dialog when deleting items - 删除项目时显示确认对话框 - - - Show Timeline widget on the Homepage - 在主页上显示时间轴小部件 - - - Notifications - 通知 - - - Show a notification when autopaste fails - 自动粘贴失败时显示通知 - - - Show a notification when autopaste starts pasting - 自动粘贴开始粘贴时显示通知 - - - Show error notification if app crashes - 当应用程序崩溃时显示错误通知 - - - Pasting - 粘贴 - - - Open new canvas on paste - 粘贴时打开新画布 - - - Paste files as reference - 将文件作为引用粘贴 - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - “引用文件”允许您粘贴文件,而无需创建它们的副本。启用此设置后,每个文件都将作为引用粘贴。 -将创建一个引用文件,指向剪贴板画布无缝显示的原始文件。 - - - Cannot enable this setting while in Restricted Access mode. - 在受限访问模式下无法启用此设置。 - - - Use markdown format instead of text files - 使用markdown格式替代文本文件 - - - Show in Collection - 在合集中显示 - - - Status Center - 状态中心 - - - Completed 0.00% - 完成 0.00% - - - The operation was canceled - 操作已取消 - - - Operation canceled - 操作已取消 - - - The operation is complete - 操作已完成 - - - Operation complete - 操作完成 - - - Overwriting Reference was canceled - 覆盖引用已取消 - - - Overwriting Reference complete - 覆盖引用完成 - - - Pasting was canceled - 粘贴已取消 - - - Pasting complete - 粘贴完成 - - - Completed {0}% - 完成 {0}% - - - Processing... - 处理... - - - Starting... - 启动... - - - Switch to Infinite Canvas - 切换到无限画布 - - - Switch to One Canvas - 切换到单画布 - - - Timeline - 时间轴 - - - An unknown error occurred. - 发生未知错误。 - - - View on GitHub - 去GitHub查看 - - - -
-
\ No newline at end of file diff --git a/ClipboardCanvas/Pages/CanvasPage.xaml b/ClipboardCanvas/Pages/CanvasPage.xaml deleted file mode 100644 index 7360530b..00000000 --- a/ClipboardCanvas/Pages/CanvasPage.xaml +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/CanvasPage.xaml.cs b/ClipboardCanvas/Pages/CanvasPage.xaml.cs deleted file mode 100644 index f6988384..00000000 --- a/ClipboardCanvas/Pages/CanvasPage.xaml.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; -using Microsoft.UI.Xaml.Media.Animation; -using Microsoft.UI.Xaml.Input; - -using ClipboardCanvas.ViewModels.Pages; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Models; -using ClipboardCanvas.DataModels.Navigation; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class CanvasPage : Page, ICanvasPageView - { - private IDisposable _collectionPreviewIDisposable; - - private ConnectedAnimation _connectedAnimation; - - public CanvasPageViewModel ViewModel - { - get => (CanvasPageViewModel)DataContext; - set => DataContext = value; - } - - public ICanvasPreviewModel CanvasPreviewModel => CanvasPreviewControl?.ViewModel; - - public ICollectionModel AssociatedCollectionModel { get; private set; } - - public CanvasPage() - { - this.InitializeComponent(); - - this.ViewModel = new CanvasPageViewModel(this); - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - - CanvasPageNavigationParameterModel navigationParameter = e.Parameter as CanvasPageNavigationParameterModel; - AssociatedCollectionModel = navigationParameter.collectionModel; - this.ViewModel.RequestedCanvasType = navigationParameter.canvasType; - - if (navigationParameter.CollectionPreviewIDisposable != null) - { - this._collectionPreviewIDisposable = navigationParameter.CollectionPreviewIDisposable; - } - - // Set connected animation - _connectedAnimation = ConnectedAnimationService.GetForCurrentView().GetAnimation( - Constants.UI.Animations.CONNECTED_ANIMATION_COLLECTION_PREVIEW_ITEM_OPEN_REQUESTED_TOKEN); - } - - protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) - { - if (_collectionPreviewIDisposable != null) - { - // In-case the user closed the page before connected animation finished, we need to Dispose - _collectionPreviewIDisposable.Dispose(); - _collectionPreviewIDisposable = null; - } - - base.OnNavigatingFrom(e); - } - - private void PastedAsReference_Click(object sender, RoutedEventArgs e) - { - Flyout.ShowAttachedFlyout(PastedAsReference); - } - - private void CanvasContextMenu_Opening(object sender, object e) - { - ViewModel.CanvasContextMenuOpeningCommand.Execute(null); - } - - public void FinishConnectedAnimation() - { - // Animate connected animation if available - if (_connectedAnimation != null) - { - _connectedAnimation.TryStart(CanvasPreviewControl); - } - - if (_collectionPreviewIDisposable != null) - { - _collectionPreviewIDisposable.Dispose(); - _collectionPreviewIDisposable = null; - } - } - - private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) - { - this.ViewModel?.DefaultKeyboardAcceleratorInvokedCommand?.Execute(args); - } - - private void Grid_DragEnter(object sender, DragEventArgs e) - { - this.ViewModel?.DragEnterCommand?.Execute(e); - } - - private void Grid_Drop(object sender, DragEventArgs e) - { - this.ViewModel?.DropCommand?.Execute(e); - } - - private void Grid_DragLeave(object sender, DragEventArgs e) - { - this.ViewModel?.DragLeaveCommand?.Execute(e); - } - } -} diff --git a/ClipboardCanvas/Pages/CollectionPreviewPage.xaml b/ClipboardCanvas/Pages/CollectionPreviewPage.xaml deleted file mode 100644 index e15fa3ef..00000000 --- a/ClipboardCanvas/Pages/CollectionPreviewPage.xaml +++ /dev/null @@ -1,284 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/CollectionPreviewPage.xaml.cs b/ClipboardCanvas/Pages/CollectionPreviewPage.xaml.cs deleted file mode 100644 index f09482eb..00000000 --- a/ClipboardCanvas/Pages/CollectionPreviewPage.xaml.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System.Linq; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; -using Microsoft.UI.Xaml.Media.Animation; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Input; - -using ClipboardCanvas.ViewModels.Pages; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.ViewModels; -using ClipboardCanvas.DataModels; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class CollectionPreviewPage : Page, ICollectionPreviewPageView - { - private CanvasItem _canvasItemToScrollTo; - - private bool _suppressDispose; - - public CollectionPreviewPageViewModel ViewModel - { - get => (CollectionPreviewPageViewModel)DataContext; - set => DataContext = value; - } - - public ICollectionModel AssociatedCollectionModel { get; private set; } - - public ISearchControlModel SearchControlModel => CanvasPreviewSearchControl.ViewModel; - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - - CollectionPreviewPageNavigationParameterModel navigationParameter = e.Parameter as CollectionPreviewPageNavigationParameterModel; - AssociatedCollectionModel = navigationParameter.collectionModel; - _canvasItemToScrollTo = navigationParameter.itemToSelect; - } - - public CollectionPreviewPage() - { - this.InitializeComponent(); - - this.ViewModel = new CollectionPreviewPageViewModel(this); - } - - protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) - { - if (!_suppressDispose) - { - this.ViewModel.Dispose(); - } - else - { - this._suppressDispose = false; - } - - base.OnNavigatingFrom(e); - } - - private async void Page_Loaded(object sender, RoutedEventArgs e) - { - await this.ViewModel.Initialize(); - this.ViewModel.CheckSearchContext(); - } - - public void PrepareConnectedAnimation(int itemIndex) - { - // Prevent crash when canvas preview is null - if (ViewModel.Items[itemIndex].ReadOnlyCanvasPreviewModel is IReadOnlyCanvasPreviewModel canvasPreviewModel - && canvasPreviewModel.IsContentLoaded) - { - UIElement sourceAnimationControl = ((ItemsGrid.ContainerFromIndex(itemIndex) as ContentControl).ContentTemplateRoot as FrameworkElement).FindName("SimpleCanvasPreviewControl") as UIElement; - - ConnectedAnimation connectedAnimation = ConnectedAnimationService.GetForCurrentView().PrepareToAnimate( - Constants.UI.Animations.CONNECTED_ANIMATION_COLLECTION_PREVIEW_ITEM_OPEN_REQUESTED_TOKEN, - sourceAnimationControl); - - connectedAnimation.Configuration = new DirectConnectedAnimationConfiguration(); - _suppressDispose = true; - } - } - - public void ScrollItemToView(CollectionPreviewItemViewModel itemToScrollTo) - { - ItemsGrid.ScrollIntoView(itemToScrollTo); - } - - public void ScrollToItemOnInitialization(CollectionPreviewItemViewModel itemToScrollTo) - { - if (itemToScrollTo != null && _canvasItemToScrollTo == null) - { - ScrollItemToView(itemToScrollTo); - } - else if (_canvasItemToScrollTo != null) - { - itemToScrollTo = this.ViewModel.Items.FirstOrDefault((item) => item.CollectionItemViewModel.AssociatedItem.Path == _canvasItemToScrollTo.AssociatedItem.Path); - - if (itemToScrollTo != null) - { - this.ViewModel.SelectedItem = itemToScrollTo; - ScrollItemToView(itemToScrollTo); - } - } - } - - private void RootPanel_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e) - { - if ((sender as FrameworkElement)?.DataContext is CollectionPreviewItemViewModel itemViewModel) - { - this.ViewModel.OpenItem(itemViewModel); - } - } - - private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) - { - this.ViewModel?.DefaultKeyboardAcceleratorInvokedCommand?.Execute(args); - } - - private void ItemsGrid_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) - { - this.ViewModel?.ContainerChangingCommand?.Execute(args); - } - } -} diff --git a/ClipboardCanvas/Pages/HomePage.xaml b/ClipboardCanvas/Pages/HomePage.xaml deleted file mode 100644 index 3c9282f1..00000000 --- a/ClipboardCanvas/Pages/HomePage.xaml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/HomePage.xaml.cs b/ClipboardCanvas/Pages/HomePage.xaml.cs deleted file mode 100644 index 8b5a73be..00000000 --- a/ClipboardCanvas/Pages/HomePage.xaml.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Threading; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -using ClipboardCanvas.ViewModels.Pages; -using ClipboardCanvas.ViewModels.Widgets.Timeline; -using ClipboardCanvas.DataModels.Navigation; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class HomePage : Page - { - public HomePageViewModel ViewModel - { - get => (HomePageViewModel)DataContext; - set => DataContext = value; - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - if (e.Parameter is FromAutopasteHomepageNavigationParameterModel fromAutopasteParameter) - { - this.ViewModel.OpenTeachingTip(); - } - - base.OnNavigatedTo(e); - } - - protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) - { - TimelineWidgetViewModel.LoadCancellationToken.Cancel(); - TimelineWidgetViewModel.LoadCancellationToken.Dispose(); - TimelineWidgetViewModel.LoadCancellationToken = new CancellationTokenSource(); - - CollectionsWidget.ViewModel.Dispose(); - this.ViewModel.Dispose(); - - base.OnNavigatingFrom(e); - } - - public HomePage() - { - this.InitializeComponent(); - - this.ViewModel = new HomePageViewModel(); - } - - private async void TimelineWidget_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - await this.ViewModel.LoadWidgets(); - } - } -} diff --git a/ClipboardCanvas/Pages/MainWindowContentPage.xaml b/ClipboardCanvas/Pages/MainWindowContentPage.xaml deleted file mode 100644 index 003f33d2..00000000 --- a/ClipboardCanvas/Pages/MainWindowContentPage.xaml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/MainWindowContentPage.xaml.cs b/ClipboardCanvas/Pages/MainWindowContentPage.xaml.cs deleted file mode 100644 index 141452bd..00000000 --- a/ClipboardCanvas/Pages/MainWindowContentPage.xaml.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using System.ComponentModel; -using System.Runtime.CompilerServices; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace ClipboardCanvas.Pages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class MainWindowContentPage : Page, INotifyPropertyChanged - { - private bool _IntroductionPanelLoad; - public bool IntroductionPanelLoad - { - get => _IntroductionPanelLoad; - set - { - if (_IntroductionPanelLoad != value) - { - _IntroductionPanelLoad = value; - OnPropertyChanged(); - } - } - } - - public MainWindowContentPage() - { - this.InitializeComponent(); - } - - - public event PropertyChangedEventHandler PropertyChanged; - private void OnPropertyChanged([CallerMemberName] string caller = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller)); - } - } -} diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsAboutPage.xaml b/ClipboardCanvas/Pages/SettingsPages/SettingsAboutPage.xaml deleted file mode 100644 index ffdfe45e..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsAboutPage.xaml +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsAboutPage.xaml.cs b/ClipboardCanvas/Pages/SettingsPages/SettingsAboutPage.xaml.cs deleted file mode 100644 index 54373924..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsAboutPage.xaml.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.Pages.SettingsPages; -using ClipboardCanvas.ModelViews; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages.SettingsPages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class SettingsAboutPage : Page, ISettingsAboutPageView - { - public SettingsAboutPageViewModel ViewModel - { - get => (SettingsAboutPageViewModel)DataContext; - set => DataContext = value; - } - - public SettingsAboutPage() - { - this.InitializeComponent(); - - this.ViewModel = new SettingsAboutPageViewModel(this); - } - - public bool IntroductionPanelLoad - { - get => MainWindow.Instance.MainWindowContentPage.IntroductionPanelLoad; - set => MainWindow.Instance.MainWindowContentPage.IntroductionPanelLoad = value; - } - } -} diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsGeneralPage.xaml b/ClipboardCanvas/Pages/SettingsPages/SettingsGeneralPage.xaml deleted file mode 100644 index ab07e983..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsGeneralPage.xaml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsGeneralPage.xaml.cs b/ClipboardCanvas/Pages/SettingsPages/SettingsGeneralPage.xaml.cs deleted file mode 100644 index d6e55b94..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsGeneralPage.xaml.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.Pages.SettingsPages; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages.SettingsPages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class SettingsGeneralPage : Page - { - public SettingsGeneralPageViewModel ViewModel - { - get => (SettingsGeneralPageViewModel)DataContext; - set => DataContext = value; - } - - public SettingsGeneralPage() - { - this.InitializeComponent(); - - this.ViewModel = new SettingsGeneralPageViewModel(); - } - } -} diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsNotificationsPage.xaml b/ClipboardCanvas/Pages/SettingsPages/SettingsNotificationsPage.xaml deleted file mode 100644 index 1267bc53..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsNotificationsPage.xaml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsNotificationsPage.xaml.cs b/ClipboardCanvas/Pages/SettingsPages/SettingsNotificationsPage.xaml.cs deleted file mode 100644 index 3fd91f22..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsNotificationsPage.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.Pages.SettingsPages; - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages.SettingsPages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class SettingsNotificationsPage : Page - { - public SettingsNotificationsPageViewModel ViewModel - { - get => (SettingsNotificationsPageViewModel)DataContext; - set => DataContext = value; - } - - public SettingsNotificationsPage() - { - this.InitializeComponent(); - - this.ViewModel = new SettingsNotificationsPageViewModel(); - } - } -} diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsPastingPage.xaml b/ClipboardCanvas/Pages/SettingsPages/SettingsPastingPage.xaml deleted file mode 100644 index 4f598355..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsPastingPage.xaml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/Pages/SettingsPages/SettingsPastingPage.xaml.cs b/ClipboardCanvas/Pages/SettingsPages/SettingsPastingPage.xaml.cs deleted file mode 100644 index b3c1fa9e..00000000 --- a/ClipboardCanvas/Pages/SettingsPages/SettingsPastingPage.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.Pages.SettingsPages; - - -// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 - -namespace ClipboardCanvas.Pages.SettingsPages -{ - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class SettingsPastingPage : Page - { - public SettingsPastingPageViewModel ViewModel - { - get => (SettingsPastingPageViewModel)DataContext; - set => DataContext = value; - } - - public SettingsPastingPage() - { - this.InitializeComponent(); - - this.ViewModel = new SettingsPastingPageViewModel(); - } - } -} diff --git a/ClipboardCanvas/Properties/AssemblyInfo.cs b/ClipboardCanvas/Properties/AssemblyInfo.cs deleted file mode 100644 index ca9a3567..00000000 --- a/ClipboardCanvas/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ClipboardCanvas")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ClipboardCanvas")] -[assembly: AssemblyCopyright("Copyright © 2021")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: ComVisible(false)] \ No newline at end of file diff --git a/ClipboardCanvas/Properties/Default.rd.xml b/ClipboardCanvas/Properties/Default.rd.xml deleted file mode 100644 index c537b89e..00000000 --- a/ClipboardCanvas/Properties/Default.rd.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - diff --git a/ClipboardCanvas/ReferenceItems/ReferenceFile.cs b/ClipboardCanvas/ReferenceItems/ReferenceFile.cs deleted file mode 100644 index eb1db1d8..00000000 --- a/ClipboardCanvas/ReferenceItems/ReferenceFile.cs +++ /dev/null @@ -1,255 +0,0 @@ -using System; -using Newtonsoft.Json; -using System.IO; -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Exceptions; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.UnsafeNative; -using Vanara.PInvoke; -using System.Runtime.InteropServices; -using System.Text; - -namespace ClipboardCanvas.ReferenceItems -{ - /// - /// A file containing data and reference to an actual file - /// - public sealed class ReferenceFile - { - private readonly StorageFile _innerReferenceFile; - - private ReferenceFileData _referenceFileData; - - public SafeWrapperResult LastError { get; private set; } = SafeWrapperResult.SUCCESS; - - public IStorageItem ReferencedItem { get; private set; } - - private ReferenceFile(StorageFile innerFile, IStorageItem referencedItem) - { - this._innerReferenceFile = innerFile; - this.ReferencedItem = referencedItem; - } - - /// - /// Updates the underlying file and fileData - /// - /// - /// - private async Task UpdateReference(string newPath, bool regenerateReferenceItem) - { - if (!StorageHelpers.Existsh(newPath)) - { - return new SafeWrapperResult(OperationErrorCode.NotFound, new FileNotFoundException(), "File does not exist."); - } - - long fileId = GetFileId(newPath); - bool isRepairable = fileId != -1; - - _referenceFileData = new ReferenceFileData(newPath, fileId, isRepairable); - string serialized = JsonConvert.SerializeObject(_referenceFileData, Formatting.Indented); - - SafeWrapperResult writeFileTextResult = await FilesystemOperations.WriteFileText(_innerReferenceFile, serialized); - if (!writeFileTextResult) - { - return writeFileTextResult; - } - - if (regenerateReferenceItem) - { - SafeWrapper referencedItem = await StorageHelpers.ToStorageItemWithError(newPath); - this.ReferencedItem = referencedItem.Result; - - return referencedItem; - } - - return SafeWrapperResult.SUCCESS; - } - - public static async Task CreateReferenceFileFromFile(StorageFile emptyReferenceFile, IStorageItem referencedItem) - { - if (!FileHelpers.IsPathEqualExtension(emptyReferenceFile.Path, Constants.FileSystem.REFERENCE_FILE_EXTENSION)) - { - return new ReferenceFile(emptyReferenceFile, null) - { - LastError = new SafeWrapperResult(OperationErrorCode.InvalidArgument, new ArgumentException(), "Empty file uses invalid Reference File extension.") - }; - } - - ReferenceFile referenceFile = new ReferenceFile(emptyReferenceFile, referencedItem); - - SafeWrapperResult result = await referenceFile.UpdateReference(referencedItem.Path, false); - referenceFile.LastError = result; - - return referenceFile; - } - - private static async Task> ReadData(StorageFile referenceFile) - { - SafeWrapper data = await FilesystemOperations.ReadFileText(referenceFile); - if (!data) - { - return (null, data.Details); - } - - ReferenceFileData referenceFileData = JsonConvert.DeserializeObject(data); - return (referenceFileData, SafeWrapperResult.SUCCESS); - } - - public static async Task GetReferenceFile(StorageFile file) - { - // The file is not a Reference File - if (!IsReferenceFile(file)) - { - return null; - } - - // The referenceFile does not exist - if (!StorageHelpers.Existsh(file.Path)) - { - return new ReferenceFile(file, null) - { - LastError = new SafeWrapperResult(OperationErrorCode.NotFound, new FileNotFoundException(), "Couldn't resolve item associated with path.") - }; - } - - SafeWrapper referenceFileData = await ReadData(file); - - ReferenceFile referenceFile = await GetFile(file, referenceFileData); - if (referenceFile.LastError) - { - if (!referenceFileData.Result.isRepairable) // Bad FileId but the path is correct - { - // Repair the FileId - await referenceFile.UpdateReference(referenceFileData.Result.path, false); - } - } - else - { - if (referenceFile.LastError == OperationErrorCode.InvalidArgument || referenceFile.LastError == OperationErrorCode.NotFound || referenceFile.LastError == OperationErrorCode.UnknownFailed) - { - if (referenceFileData.Result?.isRepairable ?? false) - { - // Repair it - SafeWrapper result = RepairReferenceFile(referenceFile, referenceFileData); - referenceFile.LastError = result; - if (result) - { - await referenceFile.UpdateReference(result.Result.path, false); - return await GetFile(file, result); - } - } - } - } - - return referenceFile; - } - - private static async Task GetFile(StorageFile referenceFile, SafeWrapper referenceFileData) - { - if (!referenceFileData) - { - return new ReferenceFile(referenceFile, null) - { - LastError = referenceFileData - }; - } - else if (string.IsNullOrEmpty(referenceFileData?.Result?.path)) - { - return new ReferenceFile(referenceFile, null) - { - LastError = new SafeWrapperResult(OperationErrorCode.InvalidArgument, new NullReferenceException(), "Reference File path is null.") - }; - } - - SafeWrapper file = await StorageHelpers.ToStorageItemWithError(referenceFileData.Result.path); - - if (!file) - { - if (file == OperationErrorCode.NotFound) - { - // If NotFound, use custom exception for LoadCanvasFromCollection() - return new ReferenceFile(referenceFile, null) - { - LastError = new SafeWrapperResult(OperationErrorCode.NotFound, new ReferencedFileNotFoundException(), "The item referenced could not be found.") - }; - } - else - { - return new ReferenceFile(referenceFile, null) - { - LastError = file - }; - } - } - - return new ReferenceFile(referenceFile, file.Result) - { - _referenceFileData = referenceFileData.Result - }; - } - - private static SafeWrapper RepairReferenceFile(ReferenceFile referenceFile, ReferenceFileData referenceFileData) - { - if (referenceFileData.fileId == -1) - { - return (null, referenceFile.LastError); - } - - // Get path from FileId... - SafeWrapperResult result = new SafeWrapperResult(OperationErrorCode.NotFound, "The reference file could not be repaired."); - - string volumeRoot = Path.GetPathRoot(referenceFileData.path); - using var volumeHandle = Kernel32.CreateFile(volumeRoot, Kernel32.FileAccess.GENERIC_READ, FileShare.Read, null, FileMode.Open, FileFlagsAndAttributes.FILE_FLAG_BACKUP_SEMANTICS); - if (volumeHandle.IsInvalid) - { - return (null, result); - } - - var fileId = new Kernel32.FILE_ID_DESCRIPTOR() { Type = 0, Id = new Kernel32.FILE_ID_DESCRIPTOR.DUMMYUNIONNAME() { FileId = referenceFileData.fileId } }; - fileId.dwSize = (uint)Marshal.SizeOf(fileId); - - using var hFile = Kernel32.OpenFileById(volumeHandle, fileId, Kernel32.FileAccess.GENERIC_READ, FileShare.Read, null, FileFlagsAndAttributes.FILE_FLAG_BACKUP_SEMANTICS); - if (hFile.IsInvalid) - { - return (null, result); - } - - var stringBuilder = new StringBuilder(4096); - uint res = Kernel32.GetFinalPathNameByHandle(hFile, stringBuilder, 4095, 0); - if (res != 0) - { - return new SafeWrapper(new ReferenceFileData(Path.GetFullPath(stringBuilder.ToString().Replace(@"\\?\", "", StringComparison.Ordinal)), referenceFileData.fileId, true), OperationErrorCode.Success); - } - else - { - return (null, result); - } - } - - private static long GetFileId(string path) - { - using var hFile = Kernel32.CreateFile(path, Kernel32.FileAccess.GENERIC_READ, FileShare.ReadWrite, null, FileMode.Open, FileFlagsAndAttributes.FILE_FLAG_BACKUP_SEMANTICS); - if (hFile.IsInvalid) - { - return -1L; - } - - SafeWrapper result = SafeWrapperRoutines.SafeWrap(() => - { - var fileId = Kernel32.GetFileInformationByHandleEx(hFile, Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileIdInfo); - return BitConverter.ToInt64(fileId.FileId.Identifier, 0); - }); - - return result ? result : -1L; - } - - public static bool IsReferenceFile(StorageFile file) - { - return FileHelpers.IsPathEqualExtension(file?.Path, Constants.FileSystem.REFERENCE_FILE_EXTENSION); - } - } -} diff --git a/ClipboardCanvas/ReferenceItems/ReferenceFileData.cs b/ClipboardCanvas/ReferenceItems/ReferenceFileData.cs deleted file mode 100644 index e30c05e0..00000000 --- a/ClipboardCanvas/ReferenceItems/ReferenceFileData.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace ClipboardCanvas.ReferenceItems -{ - [Serializable] - public sealed class ReferenceFileData - { - public readonly string path; - - public readonly long fileId; - - public readonly bool isRepairable; - - public ReferenceFileData(string path, long fileId, bool isRepairable) - { - this.path = path; - this.fileId = fileId; - this.isRepairable = isRepairable; - } - } -} diff --git a/ClipboardCanvas/ResourceDictionaries/CanvasDictionary.xaml b/ClipboardCanvas/ResourceDictionaries/CanvasDictionary.xaml deleted file mode 100644 index d52ae457..00000000 --- a/ClipboardCanvas/ResourceDictionaries/CanvasDictionary.xaml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/ResourceDictionaries/CanvasDictionary.xaml.cs b/ClipboardCanvas/ResourceDictionaries/CanvasDictionary.xaml.cs deleted file mode 100644 index 58266ecd..00000000 --- a/ClipboardCanvas/ResourceDictionaries/CanvasDictionary.xaml.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.UI.Xaml; - -namespace ClipboardCanvas.ResourceDictionaries -{ - public partial class CanvasDictionary : ResourceDictionary - { - public CanvasDictionary() - { - InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/ResourceDictionaries/ColorsDictionary.xaml b/ClipboardCanvas/ResourceDictionaries/ColorsDictionary.xaml deleted file mode 100644 index 73cba436..00000000 --- a/ClipboardCanvas/ResourceDictionaries/ColorsDictionary.xaml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - #702E2E2E - #E0E0E0 - #FBFBFB - #00FFFFFF - #E8AF20 - #FFFFFF - #FFc7c7c7 - #F3F3F3 - #FBFBFB - #E5E5E5 - #20FFFFFF - #20FFFFFF - #AAFFFFFF - #F3F3F3 - #90F3F3F3 - #F3F3F3 - - - #EE000000 - #2E2E2E - #171717 - #00000000 - #FFFF20 - #000000 - #6FFFFFFF - #201F1E - #2D2C2B - #302F2E - #0FFFFFFF - #0FFFFFFF - #DF000000 - #202020 - #AA202020 - #EE202020 - - - - - diff --git a/ClipboardCanvas/ResourceDictionaries/ToggleSwitches.xaml b/ClipboardCanvas/ResourceDictionaries/ToggleSwitches.xaml deleted file mode 100644 index 04ed623e..00000000 --- a/ClipboardCanvas/ResourceDictionaries/ToggleSwitches.xaml +++ /dev/null @@ -1,590 +0,0 @@ - - - - diff --git a/ClipboardCanvas/Resources/MiddleClickScrolling-CursorType.res b/ClipboardCanvas/Resources/MiddleClickScrolling-CursorType.res deleted file mode 100644 index b4859a50..00000000 Binary files a/ClipboardCanvas/Resources/MiddleClickScrolling-CursorType.res and /dev/null differ diff --git a/ClipboardCanvas/Services/IApplicationService.cs b/ClipboardCanvas/Services/IApplicationService.cs deleted file mode 100644 index 7c146b22..00000000 --- a/ClipboardCanvas/Services/IApplicationService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.UI.Xaml; - -using ClipboardCanvas.DataModels; - -namespace ClipboardCanvas.Services -{ - public interface IApplicationService - { - bool IsWindowActivated { get; } - - string AppVersion { get; } - - bool IsInRestrictedAccessMode { get; set; } - - List AppLanguages { get; } - - AppLanguageModel AppLanguage { get; set; } - - AppLanguageModel CurrentAppLanguage { get; } - - IntPtr GetHwnd(Window wnd); - } -} diff --git a/ClipboardCanvas/Services/IApplicationSettingsService.cs b/ClipboardCanvas/Services/IApplicationSettingsService.cs deleted file mode 100644 index 91f5fcf6..00000000 --- a/ClipboardCanvas/Services/IApplicationSettingsService.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Services -{ - public interface IApplicationSettingsService - { - string LastVersionNumber { get; set; } - - bool IsUserIntroduced { get; set; } - } -} diff --git a/ClipboardCanvas/Services/IAutopasteService.cs b/ClipboardCanvas/Services/IAutopasteService.cs deleted file mode 100644 index 199d0dce..00000000 --- a/ClipboardCanvas/Services/IAutopasteService.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ClipboardCanvas.Models.Autopaste; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Services -{ - public interface IAutopasteService - { - void UpdateAutopasteTarget(IAutopasteTarget autopasteTarget); - - bool IsAutopasteTarget(IAutopasteTarget autopasteTarget); - - Task InitializeAutopaste(); - } -} diff --git a/ClipboardCanvas/Services/IAutopasteSettingsService.cs b/ClipboardCanvas/Services/IAutopasteSettingsService.cs deleted file mode 100644 index 9c2fd8a0..00000000 --- a/ClipboardCanvas/Services/IAutopasteSettingsService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; - -using ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules; - -namespace ClipboardCanvas.Services -{ - public interface IAutopasteSettingsService - { - bool GuaranteeAddToList(IList list, T item, string listSettingName); - - bool GuaranteeRemoveFromList(IList list, T item, string listSettingName); - - bool FlushSettings(); - - string AutopastePath { get; set; } - - List SavedRules { get; set; } - - bool FileSizeRuleDoesNotApplyToFoldersWarningDismissed { get; set; } - } -} diff --git a/ClipboardCanvas/Services/ICanvasSettingsService.cs b/ClipboardCanvas/Services/ICanvasSettingsService.cs deleted file mode 100644 index e3d7450e..00000000 --- a/ClipboardCanvas/Services/ICanvasSettingsService.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ClipboardCanvas.Services -{ - public interface ICanvasSettingsService - { - bool MediaCanvas_IsLoopingEnabled { get; set; } - - double MediaCanvas_UniversalVolume { get; set; } - } -} diff --git a/ClipboardCanvas/Services/ICollectionsSettingsService.cs b/ClipboardCanvas/Services/ICollectionsSettingsService.cs deleted file mode 100644 index ea6a0a42..00000000 --- a/ClipboardCanvas/Services/ICollectionsSettingsService.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.Services -{ - public interface ICollectionsSettingsService - { - List SavedCollections { get; set; } - - string LastSelectedCollection { get; set; } - } -} diff --git a/ClipboardCanvas/Services/IDialogService.cs b/ClipboardCanvas/Services/IDialogService.cs deleted file mode 100644 index 5ed06b07..00000000 --- a/ClipboardCanvas/Services/IDialogService.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Threading.Tasks; -using Windows.Storage; -using System.Collections.Generic; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; - -namespace ClipboardCanvas.Services -{ - public interface IDialogService - { - void CloseDialog(); - - IDialog GetDialog(TViewModel viewModel); - - Task ShowDialog(TViewModel viewModel); - - IInAppNotification GetNotification(InAppNotificationControlViewModel viewModel = null); - - IInAppNotification ShowNotification(InAppNotificationControlViewModel viewModel = null, int milliseconds = 0); - - // TODO: Add FolderPickerSettings - Task PickSingleFolder(); - - Task PickSingleFile(IEnumerable filter); - } -} diff --git a/ClipboardCanvas/Services/ILogger.cs b/ClipboardCanvas/Services/ILogger.cs deleted file mode 100644 index 1fcf08f5..00000000 --- a/ClipboardCanvas/Services/ILogger.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace ClipboardCanvas.Services -{ - public interface ILogger - { - void LogToFile(string text); - } -} diff --git a/ClipboardCanvas/Services/INavigationService.cs b/ClipboardCanvas/Services/INavigationService.cs deleted file mode 100644 index a4043447..00000000 --- a/ClipboardCanvas/Services/INavigationService.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.DisplayFrameEventArgs; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.Collections; - -namespace ClipboardCanvas.Services -{ - public interface INavigationService - { - DisplayPageType CurrentPage { get; } - - DisplayPageType LastPage { get; } - - event EventHandler OnNavigationStartedEvent; - - event EventHandler OnNavigationFinishedEvent; - - bool OpenNewCanvas(ICollectionModel collection, NavigationTransitionType transitionType = NavigationTransitionType.DrillInTransition, CanvasType? canvasType = null); - - bool OpenCanvasPage(ICollectionModel collection, CollectionItemViewModel collectionItem = null, CanvasPageNavigationParameterModel navigationParameter = null, NavigationTransitionType transitionType = NavigationTransitionType.DrillInTransition, CanvasType? canvasType = null); - - bool OpenHomepage(HomepageNavigationParameterModel navigationParameter = null, NavigationTransitionType transitionType = NavigationTransitionType.DrillInTransition); - - bool OpenCollectionPreviewPage(ICollectionModel collection, CollectionPreviewPageNavigationParameterModel navigationParameter = null, NavigationTransitionType transitionType = NavigationTransitionType.EntranceTransition, CanvasType? canvasType = null); - } -} diff --git a/ClipboardCanvas/Services/INotificationService.cs b/ClipboardCanvas/Services/INotificationService.cs deleted file mode 100644 index 53f2dc73..00000000 --- a/ClipboardCanvas/Services/INotificationService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Threading; - -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.Services -{ - public interface INotificationService - { - CancellationToken PushAutopastePasteStartedNotification(); - - void PushAutopastePasteFinishedNotification(); - - void PushAutopastePasteFailedNotification(SafeWrapperResult result); - } -} diff --git a/ClipboardCanvas/Services/IStatusCenterService.cs b/ClipboardCanvas/Services/IStatusCenterService.cs deleted file mode 100644 index 9277cdb5..00000000 --- a/ClipboardCanvas/Services/IStatusCenterService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Threading; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ViewModels.UserControls.StatusCenter; - -namespace ClipboardCanvas.Services -{ - public interface IStatusCenterService - { - StatusCenterItemViewModel AppendInstantOperationBanner(string operationName, StatusCenterOperationType operationType, CancellationTokenSource cancellationTokenSource); - - StatusCenterItemViewModel AppendOperationBanner(string operationName, StatusCenterOperationType operationType, CancellationTokenSource cancellationTokenSource, TimeSpan appendDelay); - - StatusCenterItemViewModel AppendInfoBanner(string infoTitle, string infoDescription, SafeWrapperResult result); - - void RemoveBanner(StatusCenterItemViewModel banner); - - void ShowStatusCenter(); - - void HideStatusCenter(); - } -} diff --git a/ClipboardCanvas/Services/ITimelineService.cs b/ClipboardCanvas/Services/ITimelineService.cs deleted file mode 100644 index 8895420b..00000000 --- a/ClipboardCanvas/Services/ITimelineService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Threading.Tasks; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.Models.Configuration; -using ClipboardCanvas.ViewModels.Widgets.Timeline; - -namespace ClipboardCanvas.Services -{ - public interface ITimelineService - { - Task> AddItemForSection(TimelineSectionViewModel timelineSection, ICollectionModel collectionModel, CanvasItem canvasItem); - - bool RemoveItemFromSection(TimelineSectionViewModel timelineSection, TimelineSectionItemViewModel timelineSectionItem); - - Task GetOrCreateTodaySection(); - - Task LoadSectionAsync(TimelineSectionViewModel timelineSection); - - Task LoadAllSectionsAsync(); - - void UnloadSection(TimelineSectionViewModel timelineSection); - - void UnloadAllSections(); - - TimelineSectionItemViewModel FindTimelineSectionItem(TimelineSectionViewModel timelineSection, CanvasItem canvasItem); - - (TimelineSectionViewModel section, TimelineSectionItemViewModel sectionItem) FindTimelineSectionItem(CanvasItem canvasItem); - - TimelineConfigurationModel ConstructConfigurationModel(); - } -} diff --git a/ClipboardCanvas/Services/ITimelineSettingsService.cs b/ClipboardCanvas/Services/ITimelineSettingsService.cs deleted file mode 100644 index 52708997..00000000 --- a/ClipboardCanvas/Services/ITimelineSettingsService.cs +++ /dev/null @@ -1,9 +0,0 @@ -using ClipboardCanvas.Models.Configuration; - -namespace ClipboardCanvas.Services -{ - public interface ITimelineSettingsService - { - TimelineConfigurationModel UserTimeline { get; set; } - } -} diff --git a/ClipboardCanvas/Services/IUserSettingsService.cs b/ClipboardCanvas/Services/IUserSettingsService.cs deleted file mode 100644 index 2da55547..00000000 --- a/ClipboardCanvas/Services/IUserSettingsService.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; - -using ClipboardCanvas.EventArguments; - -namespace ClipboardCanvas.Services -{ - public interface IUserSettingsService - { - event EventHandler OnSettingChangedEvent; - - /// - /// Determines whether to push a notification when app crashes - /// - bool PushErrorNotification { get; set; } - - /// - /// Determines whether to show Timeline widget on homepage - /// - bool ShowTimelineOnHomepage { get; set; } - - /// - /// Determines whether to enable permanent deletion option as default - /// - bool DeletePermanentlyAsDefault { get; set; } - - /// - /// Determines whether to open new canvas on paste - /// - bool OpenNewCanvasOnPaste { get; set; } - - /// - /// Determines whether items are copied as reference or directly to collection - ///

- /// If is true, then item on paste will be copied as reference to original item location. - ///
- /// Otherwise, items are copied directly to collection. - ///
- bool AlwaysPasteFilesAsReference { get; set; } // TODO: Add a setting so user can also select which items to paste as reference - - /// - /// Determines whether to favor markdown or .txt files when pasting items - /// - bool PrioritizeMarkdownOverText { get; set; } - - /// - /// Determines whether to show delete confirmation dialog when deleting canvases - /// - bool ShowDeleteConfirmationDialog { get; set; } - - /// - /// Determines whether to use Infinite Canvas as default when opening new Canvas - /// - bool UseInfiniteCanvasAsDefault { get; set; } - - /// - /// Determines whether to show a notification when Autopaste is run or finished - /// - bool PushAutopasteNotification { get; set; } - - /// - /// Determines whether to show a notification when Autopaste failed - /// - bool PushAutopasteFailedNotification { get; set; } - - /// - /// Determines whether to use Autopaste - /// - bool IsAutopasteEnabled { get; set; } - } -} diff --git a/ClipboardCanvas/Services/Implementation/ApplicationService.cs b/ClipboardCanvas/Services/Implementation/ApplicationService.cs deleted file mode 100644 index 58506a74..00000000 --- a/ClipboardCanvas/Services/Implementation/ApplicationService.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Windows.ApplicationModel; -using Windows.Globalization; -using Microsoft.UI.Xaml; -using Microsoft.UI.Windowing; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.Services.Implementation -{ - public class ApplicationService : IApplicationService - { - public bool IsWindowActivated { get; private set; } - - public string AppVersion { get; } = $"{Package.Current.Id.Version.Major}.{Package.Current.Id.Version.Minor}.{Package.Current.Id.Version.Build}.{Package.Current.Id.Version.Revision}"; - - public bool IsInRestrictedAccessMode { get; set; } - - public AppLanguageModel AppLanguage - { - get => AppLanguages.FirstOrDefault(item => item.Id == ApplicationLanguages.PrimaryLanguageOverride) ?? AppLanguages.FirstOrDefault(); - set => ApplicationLanguages.PrimaryLanguageOverride = value.Id; - } - - public List AppLanguages { get; } = ApplicationLanguages.ManifestLanguages.Select((item) => new AppLanguageModel(item)).ToList(); - - public AppLanguageModel CurrentAppLanguage { get; } = new AppLanguageModel(ApplicationLanguages.PrimaryLanguageOverride); - - public IntPtr GetHwnd(Window wnd) - { - IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(wnd); - return hwnd; - } - - public ApplicationService() - { - try - { - MainWindow.Instance.Activated -= Current_Activated; - MainWindow.Instance.Activated += Current_Activated; - } - catch (Exception ex) - { - LoggingHelpers.SafeLogExceptionToFile(ex); - } - } - - private void Current_Activated(object sender, WindowActivatedEventArgs e) - { - IsWindowActivated = e.WindowActivationState != WindowActivationState.Deactivated; - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/ApplicationSettingsService.cs b/ClipboardCanvas/Services/Implementation/ApplicationSettingsService.cs deleted file mode 100644 index c3bb2097..00000000 --- a/ClipboardCanvas/Services/Implementation/ApplicationSettingsService.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.IO; -using Windows.Storage; - -using ClipboardCanvas.Models.JsonSettings; - -namespace ClipboardCanvas.Services -{ - public class ApplicationSettingsService : BaseJsonSettingsModel, IApplicationSettingsService - { - #region Constructor - - public ApplicationSettingsService() - : base (Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.LocalSettings.SETTINGS_FOLDERNAME, Constants.LocalSettings.APPLICATION_SETTINGS_FILENAME), - isCachingEnabled: true) - { - } - - #endregion - - #region IApplicationSettings - - public string LastVersionNumber - { - get => Get(null); - set => Set(value); - } - - public bool IsUserIntroduced - { - get => Get(false); - set => Set(value); - } - - #endregion - } -} diff --git a/ClipboardCanvas/Services/Implementation/AutopasteService.cs b/ClipboardCanvas/Services/Implementation/AutopasteService.cs deleted file mode 100644 index 93a579fa..00000000 --- a/ClipboardCanvas/Services/Implementation/AutopasteService.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading.Tasks; - -using ClipboardCanvas.Models.Autopaste; -using ClipboardCanvas.ViewModels.UserControls.Autopaste; - -namespace ClipboardCanvas.Services.Implementation -{ - public class AutopasteService : IAutopasteService - { - public AutopasteControlViewModel AutopasteControlViewModel { get; set; } - - public async Task InitializeAutopaste() - { - if (AutopasteControlViewModel != null) - { - await AutopasteControlViewModel.Initialize(); - } - } - - public bool IsAutopasteTarget(IAutopasteTarget autopasteTarget) - { - return AutopasteControlViewModel.AutopasteTarget == autopasteTarget; - } - - public void UpdateAutopasteTarget(IAutopasteTarget autopasteTarget) - { - AutopasteControlViewModel?.UpdateTarget(autopasteTarget); - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/AutopasteSettingsService.cs b/ClipboardCanvas/Services/Implementation/AutopasteSettingsService.cs deleted file mode 100644 index 6b835175..00000000 --- a/ClipboardCanvas/Services/Implementation/AutopasteSettingsService.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using Windows.Storage; -using Newtonsoft.Json.Serialization; -using System; -using System.Linq; - -using ClipboardCanvas.Models.JsonSettings; -using ClipboardCanvas.Models.JsonSettings.Implementation; -using ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules; - -namespace ClipboardCanvas.Services.Implementation -{ - public sealed class AutopasteSettingsService : BaseJsonSettingsModel, IAutopasteSettingsService - { - public AutopasteSettingsService() - : base (Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.LocalSettings.SETTINGS_FOLDERNAME, Constants.LocalSettings.AUTOPASTE_SETTINGS_FILENAME), - isCachingEnabled: true, - jsonSettingsSerializer: new DerivedTypesJsonSettingsSerializer(new AutopasteSerializationBinder(typeof(Dictionary)))) - { - } - - public string AutopastePath - { - get => Get(null); - set => Set(value); - } - - public List SavedRules - { - get => Get>(null); - set => Set(value); - } - - public bool FileSizeRuleDoesNotApplyToFoldersWarningDismissed - { - get => Get(false); - set => Set(value); - } - } - - public sealed class AutopasteSerializationBinder : ISerializationBinder - { - private readonly List _knownTypes; - - public AutopasteSerializationBinder(Type dataBaseObjectType) - { - _knownTypes = new List() - { - dataBaseObjectType, - typeof(BaseAutopasteRuleViewModel), - typeof(FileSizeRuleViewModel), - typeof(TypeFilterRuleViewModel), - typeof(List) - }; - } - - public Type BindToType(string assemblyName, string typeName) - { - return _knownTypes.SingleOrDefault(t => t.Name == typeName); - } - - public void BindToName(Type serializedType, out string assemblyName, out string typeName) - { - assemblyName = null; - typeName = serializedType.Name; - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/CanvasSettingsService.cs b/ClipboardCanvas/Services/Implementation/CanvasSettingsService.cs deleted file mode 100644 index 26db0fa4..00000000 --- a/ClipboardCanvas/Services/Implementation/CanvasSettingsService.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.IO; -using Windows.Storage; - -using ClipboardCanvas.Models.JsonSettings; - -namespace ClipboardCanvas.Services -{ - public class CanvasSettingsService : BaseJsonSettingsModel, ICanvasSettingsService - { - #region Constructor - - public CanvasSettingsService() - : base (Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.LocalSettings.SETTINGS_FOLDERNAME, Constants.LocalSettings.CANVAS_SETTINGS_FILENAME), - isCachingEnabled: true) - { - } - - #endregion - - #region ICanvasSettings - - public bool MediaCanvas_IsLoopingEnabled - { - get => Get(false); - set => Set(value); - } - - public double MediaCanvas_UniversalVolume - { - get => Get(1.0d); - set => Set(value); - } - - #endregion - } -} diff --git a/ClipboardCanvas/Services/Implementation/CollectionsSettingsService.cs b/ClipboardCanvas/Services/Implementation/CollectionsSettingsService.cs deleted file mode 100644 index 50cff5a7..00000000 --- a/ClipboardCanvas/Services/Implementation/CollectionsSettingsService.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.IO; -using Windows.Storage; -using System.Collections.Generic; - -using ClipboardCanvas.Models.JsonSettings; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.Services -{ - public class CollectionsSettingsService : BaseJsonSettingsModel, ICollectionsSettingsService - { - #region Constructor - - public CollectionsSettingsService() - : base(Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.LocalSettings.SETTINGS_FOLDERNAME, Constants.LocalSettings.COLLECTION_SETTINGS_FILENAME), - isCachingEnabled: true) - { - } - - #endregion - - #region ICollectionLocationsSettings - - public List SavedCollections - { - get => Get>(null); - set => Set>(value); - } - - public string LastSelectedCollection - { - get => Get(Constants.Collections.DEFAULT_COLLECTION_TOKEN); - set => Set(value); - } - - #endregion - } -} diff --git a/ClipboardCanvas/Services/Implementation/DialogService.cs b/ClipboardCanvas/Services/Implementation/DialogService.cs deleted file mode 100644 index 32f37eb7..00000000 --- a/ClipboardCanvas/Services/Implementation/DialogService.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Reflection; -using System.Threading.Tasks; -using Windows.Storage; -using System.Collections.Generic; -using Windows.Storage.Pickers; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Extensions; - -namespace ClipboardCanvas.Services.Implementation -{ - public class DialogService : IDialogService - { - private IInAppNotification _lastInAppNotification; - - private IDialogView _currentDialog; - - #region IDialogService - - public void CloseDialog() - { - _currentDialog?.Hide(); - _currentDialog = null; - } - - public IDialog GetDialog(TViewModel viewModel) - { - IDialog dialog; - - Type dialogType = GetDialogType(viewModel); - - if (dialogType == null) - { - throw new TypeLoadException($"The dialog for {viewModel} couldn't be found."); - } - - dialog = GetDialogFromType>(dialogType, viewModel); - dialog.ViewModel = viewModel; - - if (dialog is IDialogView dialogView) - { - dialogView.XamlRoot = MainWindow.Instance.Content.XamlRoot; - _currentDialog = dialogView; - } - else - { - throw new NotSupportedException($"Dialog doesn't implement {nameof(IDialogView)}."); - } - - return dialog; - } - - public async Task ShowDialog(TViewModel viewModel) - { - IDialog dialog = GetDialog(viewModel); - - return await dialog.ShowAsync(); - } - - public IInAppNotification GetNotification(InAppNotificationControlViewModel viewModel = null) - { - _lastInAppNotification?.Dismiss(); - - IInAppNotification notification = MainWindow.Instance.MainWindowContentPage.MainInAppNotification; - _lastInAppNotification = notification; - - if (viewModel != null) - { - notification.ViewModel?.Dispose(); - notification.ViewModel = viewModel; - } - - return notification; - } - - public IInAppNotification ShowNotification(InAppNotificationControlViewModel viewModel = null, int milliseconds = 0) - { - IInAppNotification notification = GetNotification(viewModel); - - notification.Show(milliseconds); - return notification; - } - - public async Task PickSingleFolder() - { - FolderPicker folderPicker = new FolderPicker(); - folderPicker.FileTypeFilter.Add("*"); - - IntPtr hwnd = Vanara.PInvoke.User32.GetActiveWindow().DangerousGetHandle(); - WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd); - - return await folderPicker.PickSingleFolderAsync(); - } - - public async Task PickSingleFile(IEnumerable filter) - { - FileOpenPicker filePicker = new FileOpenPicker(); - - if (filter.IsEmpty()) - { - filePicker.FileTypeFilter.Add("*"); - } - else - { - foreach (var item in filter) - { - filePicker.FileTypeFilter.Add(item); - } - } - - IntPtr hwnd = Vanara.PInvoke.User32.GetActiveWindow().DangerousGetHandle(); - WinRT.Interop.InitializeWithWindow.Initialize(filePicker, hwnd); - - return await filePicker.PickSingleFileAsync(); - } - - #endregion - - private Type GetDialogType(TViewModel viewModel) - { - Type viewModelType = viewModel.GetType(); - string dialogName = GetDialogName(viewModelType); - - Type dialogType = viewModelType.GetTypeInfo().Assembly.GetType(dialogName); - return dialogType; - } - - private string GetDialogName(Type viewModelType) - { - if (viewModelType.FullName != null) - { - string dialogName = viewModelType.FullName.Replace("ViewModels.", string.Empty); - - if (dialogName.EndsWith("ViewModel", StringComparison.Ordinal)) - { - return dialogName.Substring(0, dialogName.Length - "ViewModel".Length); - } - } - - throw new TypeLoadException($"The {viewModelType} isn't suffixed with \"ViewModel\"."); - } - - private TRequestedDialog GetDialogFromType(Type dialogType, TViewModel viewModel) - { - object dialogInstance = Activator.CreateInstance(dialogType); - - if (dialogInstance is not TRequestedDialog dialog) - { - throw new ArgumentException($"Dialog of type {dialogType} does not implement {nameof(IDialog)}."); - } - - return dialog; - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/ExceptionToFileLogger.cs b/ClipboardCanvas/Services/Implementation/ExceptionToFileLogger.cs deleted file mode 100644 index 4845a99a..00000000 --- a/ClipboardCanvas/Services/Implementation/ExceptionToFileLogger.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Windows.Storage; -using System.Diagnostics; -using System.IO; - -using ClipboardCanvas.UnsafeNative; - -namespace ClipboardCanvas.Services.Implementation -{ - public class ExceptionToFileLogger : ILogger - { - public void LogToFile(string text) - { - try - { - string filePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.FileSystem.EXCEPTIONLOG_FILENAME); - - string existing = UnsafeNativeHelpers.ReadStringFromFile(filePath); - existing += text; - - UnsafeNativeHelpers.WriteStringToFile(filePath, existing); - } - catch (Exception e) - { - Debug.WriteLine(e); - } - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/NavigationService.cs b/ClipboardCanvas/Services/Implementation/NavigationService.cs deleted file mode 100644 index 1bce8a7a..00000000 --- a/ClipboardCanvas/Services/Implementation/NavigationService.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.Pages; -using ClipboardCanvas.DisplayFrameEventArgs; -using ClipboardCanvas.ViewModels.UserControls.Collections; - -#nullable enable - -namespace ClipboardCanvas.Services.Implementation -{ - public class NavigationService : INavigationService - { - public Frame? DisplayFrame { get; internal set; } - - public Func? CheckCollectionAvailabilityBeforePageNavigation { get; internal set; } - - public DisplayPageType CurrentPage { get; private set; } - - public DisplayPageType LastPage { get; private set; } = DisplayPageType.CanvasPage; - - public event EventHandler OnNavigationStartedEvent; - - public event EventHandler OnNavigationFinishedEvent; - - public bool OpenNewCanvas(ICollectionModel collection, NavigationTransitionType transitionType = NavigationTransitionType.DrillInTransition, CanvasType? canvasType = null) - { - if (canvasType == null) - { - canvasType = collection.AssociatedCanvasType; - } - - OnNavigationStartedEvent?.Invoke(this, new NavigationStartedEventArgs(collection, (CanvasType)canvasType, DisplayPageType.CanvasPage)); - - collection.SetIndexOnNewCanvas(); - - BaseDisplayFrameParameterDataModel navigationParameter = new CanvasPageNavigationParameterModel(collection, (CanvasType)canvasType); - LastPage = CurrentPage; - CurrentPage = DisplayPageType.CanvasPage; - DisplayFrame?.Navigate(typeof(CanvasPage), navigationParameter, transitionType.ToNavigationTransition()); - - OnNavigationFinishedEvent?.Invoke(this, new NavigationFinishedEventArgs(true, null, collection, (CanvasType)canvasType, DisplayPageType.CanvasPage)); - - return true; - } - - public bool OpenCanvasPage(ICollectionModel collection, CollectionItemViewModel collectionItem = null, CanvasPageNavigationParameterModel navigationParameter = null, NavigationTransitionType transitionType = NavigationTransitionType.DrillInTransition, CanvasType? canvasType = null) - { - if (canvasType == null) - { - canvasType = collection.AssociatedCanvasType; - } - - if (!CheckCollectionAvailabilityBeforePageNavigation?.Invoke() ?? true) - { - OnNavigationFinishedEvent?.Invoke(this, new NavigationFinishedEventArgs(false, null, collection, (CanvasType)canvasType, DisplayPageType.CanvasPage)); - return false; - } - - OnNavigationStartedEvent?.Invoke(this, new NavigationStartedEventArgs(collection, (CanvasType)canvasType, DisplayPageType.CanvasPage)); - - if (navigationParameter == null) - { - navigationParameter = new CanvasPageNavigationParameterModel(collection, (CanvasType)canvasType); - } - LastPage = CurrentPage; - CurrentPage = DisplayPageType.CanvasPage; - DisplayFrame.Navigate(typeof(CanvasPage), navigationParameter, transitionType.ToNavigationTransition()); - - OnNavigationFinishedEvent?.Invoke(this, new NavigationFinishedEventArgs(true, collectionItem ?? collection.CurrentCollectionItemViewModel, collection, (CanvasType)canvasType, DisplayPageType.CanvasPage)); - - return true; - } - - public bool OpenHomepage(HomepageNavigationParameterModel navigationParameter = null, NavigationTransitionType transitionType = NavigationTransitionType.DrillInTransition) - { - CanvasType canvasType = navigationParameter?.canvasType ?? CanvasHelpers.GetDefaultCanvasType(); - - OnNavigationStartedEvent?.Invoke(this, new NavigationStartedEventArgs(null, canvasType, DisplayPageType.Homepage)); - - if (navigationParameter == null) - { - navigationParameter = new HomepageNavigationParameterModel(canvasType); - } - LastPage = CurrentPage; - CurrentPage = DisplayPageType.Homepage; - DisplayFrame.Navigate(typeof(HomePage), navigationParameter, transitionType.ToNavigationTransition()); - - OnNavigationFinishedEvent?.Invoke(this, new NavigationFinishedEventArgs(true, null, null, canvasType, DisplayPageType.Homepage)); - - return true; - } - - public bool OpenCollectionPreviewPage(ICollectionModel collection, CollectionPreviewPageNavigationParameterModel navigationParameter = null, NavigationTransitionType transitionType = NavigationTransitionType.EntranceTransition, CanvasType? canvasType = null) - { - if (canvasType == null) - { - canvasType = collection.AssociatedCanvasType; - } - - OnNavigationStartedEvent?.Invoke(this, new NavigationStartedEventArgs(collection, (CanvasType)canvasType, DisplayPageType.CollectionPreviewPage)); - - if (!CheckCollectionAvailabilityBeforePageNavigation()) - { - OnNavigationFinishedEvent?.Invoke(this, new NavigationFinishedEventArgs(false, null, collection, (CanvasType)canvasType, DisplayPageType.CollectionPreviewPage)); - return false; - } - - if (navigationParameter == null) - { - navigationParameter = new CollectionPreviewPageNavigationParameterModel(collection, (CanvasType)canvasType); - } - LastPage = CurrentPage; - CurrentPage = DisplayPageType.CollectionPreviewPage; - DisplayFrame.Navigate(typeof(CollectionPreviewPage), navigationParameter, transitionType.ToNavigationTransition()); - - OnNavigationFinishedEvent?.Invoke(this, new NavigationFinishedEventArgs(true, null, collection, (CanvasType)canvasType, DisplayPageType.CollectionPreviewPage)); - - return true; - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/NotificationService.cs b/ClipboardCanvas/Services/Implementation/NotificationService.cs deleted file mode 100644 index 23a8de78..00000000 --- a/ClipboardCanvas/Services/Implementation/NotificationService.cs +++ /dev/null @@ -1,98 +0,0 @@ -using CommunityToolkit.WinUI.Notifications; -using System.Threading; -using Windows.UI.Notifications; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.Services.Implementation -{ - public class NotificationService : INotificationService - { - public CancellationToken PushAutopastePasteStartedNotification() - { - CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - - ToastContent toastContent = new ToastContent() - { - Visual = new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric() - { - Children = - { - new AdaptiveText() - { - Text = "AutopasteWorking".GetLocalized2() - }, - new AdaptiveText() - { - Text = "AutopasteContentBeingPasted".GetLocalized2() - } - } - } - } - }; - - ToastNotification toastNotificationNative = new ToastNotification(toastContent.GetXml()); - ToastNotificationManager.CreateToastNotifier().Show(toastNotificationNative); - - return cancellationTokenSource.Token; - } - - public void PushAutopastePasteFinishedNotification() - { - ToastContent toastContent = new ToastContent() - { - Visual = new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric() - { - Children = - { - new AdaptiveText() - { - Text = "AutopasteFinishedWorking".GetLocalized2() - }, - new AdaptiveText() - { - Text = "AutopasteContentPasted".GetLocalized2() - } - } - } - } - }; - - ToastNotification toastNotificationNative = new ToastNotification(toastContent.GetXml()); - ToastNotificationManager.CreateToastNotifier().Show(toastNotificationNative); - } - - public void PushAutopastePasteFailedNotification(SafeWrapperResult result) - { - ToastContent toastContent = new ToastContent() - { - Visual = new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric() - { - Children = - { - new AdaptiveText() - { - Text = "AutopastePastingFailed".GetLocalized2() - }, - new AdaptiveText() - { - Text = string.Format("AutopasteContentPastingFailed".GetLocalized2(), result?.ErrorCode ?? OperationErrorCode.UnknownFailed) - } - } - } - } - }; - - ToastNotification toastNotificationNative = new ToastNotification(toastContent.GetXml()); - ToastNotificationManager.CreateToastNotifier().Show(toastNotificationNative); - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/StatusCenterService.cs b/ClipboardCanvas/Services/Implementation/StatusCenterService.cs deleted file mode 100644 index 681424ef..00000000 --- a/ClipboardCanvas/Services/Implementation/StatusCenterService.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Threading; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.StatusCenter; - -namespace ClipboardCanvas.Services.Implementation -{ - public class StatusCenterService : IStatusCenterService - { - public StatusCenterViewModel StatusCenterViewModel { get; set; } - - public INavigationToolBarControlModel NavigationToolBarControlModel { get; set; } - - public StatusCenterItemViewModel AppendInstantOperationBanner(string operationName, StatusCenterOperationType operationType, CancellationTokenSource cancellationTokenSource) - { - var banner = StatusCenterItemViewModel.ConstructOperationBanner(operationName, operationType, cancellationTokenSource); - StatusCenterViewModel.AddItem(banner); - - return banner; - } - - public StatusCenterItemViewModel AppendOperationBanner(string operationName, StatusCenterOperationType operationType, CancellationTokenSource cancellationTokenSource, TimeSpan appendDelay) - { - var banner = StatusCenterItemViewModel.ConstructOperationBanner(operationName, operationType, cancellationTokenSource); - StatusCenterViewModel.AddItem(banner, appendDelay); - - return banner; - } - - public StatusCenterItemViewModel AppendInfoBanner(string infoTitle, string infoDescription, SafeWrapperResult result) - { - var banner = StatusCenterItemViewModel.ConstructInfoBanner(infoTitle, infoDescription, result); - StatusCenterViewModel.AddItem(banner); - - return banner; - } - - public void RemoveBanner(StatusCenterItemViewModel banner) - { - StatusCenterViewModel.RemoveItem(banner); - } - - public void ShowStatusCenter() - { - if (NavigationToolBarControlModel != null) - { - NavigationToolBarControlModel.IsStatusCenterButtonVisible = true; - } - } - - public void HideStatusCenter() - { - if (NavigationToolBarControlModel != null) - { - NavigationToolBarControlModel.IsStatusCenterButtonVisible = false; - } - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/TimelineService.cs b/ClipboardCanvas/Services/Implementation/TimelineService.cs deleted file mode 100644 index b6f8ddaf..00000000 --- a/ClipboardCanvas/Services/Implementation/TimelineService.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.Models.Configuration; -using ClipboardCanvas.ViewModels.Widgets.Timeline; - -namespace ClipboardCanvas.Services.Implementation -{ - public class TimelineService : ITimelineService - { - public async Task> AddItemForSection(TimelineSectionViewModel timelineSection, ICollectionModel collectionModel, CanvasItem canvasItem) - { - if (!await TimelineWidgetViewModel.CheckIfTimelineEnabled()) - { - return null; - } - - return await timelineSection.AddItem(collectionModel, canvasItem); - } - - public bool RemoveItemFromSection(TimelineSectionViewModel timelineSection, TimelineSectionItemViewModel timelineSectionItem) - { - return timelineSection?.RemoveItem(timelineSectionItem) ?? false; - } - - public async Task GetOrCreateTodaySection() - { - if (!await TimelineWidgetViewModel.CheckIfTimelineEnabled()) - { - return null; - } - - return TimelineWidgetViewModel.GetOrCreateTodaySection(); - } - - public async Task LoadSectionAsync(TimelineSectionViewModel timelineSection) - { - if (!await TimelineWidgetViewModel.CheckIfTimelineEnabled()) - { - return; - } - - List loadItemTasks = new List(); - foreach (var item in timelineSection.Items) - { - loadItemTasks.Add(item.InitializeSectionItemContent()); - } - - await Task.WhenAll(loadItemTasks); - } - - public async Task LoadAllSectionsAsync() - { - if (!await TimelineWidgetViewModel.CheckIfTimelineEnabled()) - { - return; - } - - List loadItemTasks = new List(); - foreach (var item in TimelineWidgetViewModel.Sections) - { - loadItemTasks.Add(LoadSectionAsync(item)); - } - - await Task.WhenAll(loadItemTasks); - } - - public void UnloadSection(TimelineSectionViewModel timelineSection) - { - timelineSection?.Dispose(); - } - - public void UnloadAllSections() - { - foreach (var item in TimelineWidgetViewModel.Sections) - { - item.Dispose(); - } - } - - public TimelineSectionItemViewModel FindTimelineSectionItem(TimelineSectionViewModel timelineSection, CanvasItem canvasItem) - { - return timelineSection?.FindTimelineSectionItem(canvasItem); - } - - public (TimelineSectionViewModel section, TimelineSectionItemViewModel sectionItem) FindTimelineSectionItem(CanvasItem canvasItem) - { - TimelineSectionViewModel section = null; - TimelineSectionItemViewModel sectionItem = null; - - foreach (var item in TimelineWidgetViewModel.Sections) - { - sectionItem = item.FindTimelineSectionItem(canvasItem); - - if (sectionItem != null) - { - section = item; - break; - } - } - - return (section, sectionItem); - } - - public TimelineConfigurationModel ConstructConfigurationModel() - { - return TimelineWidgetViewModel.ConstructConfigurationModel(); - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/TimelineSettingsService.cs b/ClipboardCanvas/Services/Implementation/TimelineSettingsService.cs deleted file mode 100644 index 64faf823..00000000 --- a/ClipboardCanvas/Services/Implementation/TimelineSettingsService.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.IO; -using Windows.Storage; - -using ClipboardCanvas.Models.Configuration; -using ClipboardCanvas.Models.JsonSettings; - -namespace ClipboardCanvas.Services.Implementation -{ - public class TimelineSettingsService : BaseJsonSettingsModel, ITimelineSettingsService - { - public TimelineSettingsService() - : base(Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.LocalSettings.SETTINGS_FOLDERNAME, Constants.LocalSettings.TIMELINE_SETTINGS_FILENAME), - isCachingEnabled: true) - { - } - - public TimelineConfigurationModel UserTimeline - { - get => Get(null); - set => Set(value); - } - } -} diff --git a/ClipboardCanvas/Services/Implementation/UserSettingsService.cs b/ClipboardCanvas/Services/Implementation/UserSettingsService.cs deleted file mode 100644 index 518e0798..00000000 --- a/ClipboardCanvas/Services/Implementation/UserSettingsService.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.IO; -using Windows.Storage; -using Microsoft.AppCenter.Analytics; - -using ClipboardCanvas.Models.JsonSettings; -using ClipboardCanvas.DataModels; - -namespace ClipboardCanvas.Services -{ - public class UserSettingsService : BaseJsonSettingsModel, IUserSettingsService - { - private IApplicationService _applicationService; - - #region Constructor - - public UserSettingsService(IApplicationService applicationService) - : base(Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.LocalSettings.SETTINGS_FOLDERNAME, Constants.LocalSettings.USER_SETTINGS_FILENAME), - isCachingEnabled: true) - { - this._applicationService = applicationService; - - TrackAppCenterAnalytics(); - } - - #endregion - - #region Private Helpers - - private void TrackAppCenterAnalytics() - { - Analytics.TrackEvent($"{nameof(PushErrorNotification)} {PushErrorNotification}"); - Analytics.TrackEvent($"{nameof(ShowTimelineOnHomepage)} {ShowTimelineOnHomepage}"); - Analytics.TrackEvent($"{nameof(DeletePermanentlyAsDefault)} {DeletePermanentlyAsDefault}"); - Analytics.TrackEvent($"{nameof(OpenNewCanvasOnPaste)} {OpenNewCanvasOnPaste}"); - Analytics.TrackEvent($"{nameof(AlwaysPasteFilesAsReference)} {AlwaysPasteFilesAsReference}"); - Analytics.TrackEvent($"{nameof(PrioritizeMarkdownOverText)} {PrioritizeMarkdownOverText}"); - Analytics.TrackEvent($"{nameof(ShowDeleteConfirmationDialog)} {ShowDeleteConfirmationDialog}"); - Analytics.TrackEvent($"{nameof(UseInfiniteCanvasAsDefault)} {UseInfiniteCanvasAsDefault}"); - Analytics.TrackEvent($"{nameof(IsAutopasteEnabled)} {IsAutopasteEnabled}"); - Analytics.TrackEvent($"{nameof(PushAutopasteNotification)} {PushAutopasteNotification}"); - Analytics.TrackEvent($"{nameof(PushAutopasteFailedNotification)} {PushAutopasteFailedNotification}"); - } - - #endregion - - #region IUserSettings - - public AppLanguageModel AppLanguage - { - get => Get(new AppLanguageModel(null)); - set => Set(value); - } - - - public bool PushErrorNotification - { - get => Get(true); - set => Set(value); - } - - public bool ShowTimelineOnHomepage - { - get => Get(true); - set => Set(value); - } - - public bool DeletePermanentlyAsDefault - { - get => Get(false); - set => Set(value); - } - - public bool OpenNewCanvasOnPaste - { - get => Get(false); - set => Set(value); - } - - public bool AlwaysPasteFilesAsReference - { - get => _applicationService.IsInRestrictedAccessMode ? false : Get(true); - set => Set(value); - } - - public bool PrioritizeMarkdownOverText - { - get => Get(false); - set => Set(value); - } - - public bool ShowDeleteConfirmationDialog - { - get => Get(true); - set => Set(value); - } - - public bool UseInfiniteCanvasAsDefault - { - get => Get(true); - set => Set(value); - } - - public bool IsAutopasteEnabled - { - get => Get(false); - set => Set(value); - } - - public bool PushAutopasteNotification - { - get => Get(true); - set => Set(value); - } - - public bool PushAutopasteFailedNotification - { - get => Get(true); - set => Set(value); - } - - #endregion - } -} diff --git a/ClipboardCanvas/Storage/Base/BaseStorageFile.cs b/ClipboardCanvas/Storage/Base/BaseStorageFile.cs deleted file mode 100644 index db95559f..00000000 --- a/ClipboardCanvas/Storage/Base/BaseStorageFile.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.Storage.Base -{ - public abstract class BaseStorageFile : IBaseStorageItem - { - public virtual string Name { get; } - - public virtual string Path { get; } - - protected BaseStorageFile(string path) - { - this.Path = path; - this.Name = System.IO.Path.GetFileName(path); - } - - public abstract Task DeleteAsync(StorageDeleteOption option, IProgress progress, CancellationToken cancellationToken); - - public abstract Task RenameAsync(string desiredName, NameCollisionOption option = NameCollisionOption.GenerateUniqueName); - } -} diff --git a/ClipboardCanvas/Storage/Base/BaseStorageFolder.cs b/ClipboardCanvas/Storage/Base/BaseStorageFolder.cs deleted file mode 100644 index a2e5ffae..00000000 --- a/ClipboardCanvas/Storage/Base/BaseStorageFolder.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.Storage.Base -{ - public abstract class BaseStorageFolder : IBaseStorageFolder, IBaseStorageItem - { - protected BaseStorageFolder(string path) - { - this.Path = path; - this.Name = System.IO.Path.GetFileName(path); - } - - public virtual string Name { get; } - - public virtual string Path { get; } - - public abstract Task DeleteAsync(StorageDeleteOption option, IProgress progress, CancellationToken cancellationToken); - - public abstract Task DeleteAsync(StorageDeleteOption option, bool recursive, IProgress progress, CancellationToken cancellationToken); - - public abstract Task RenameAsync(string desiredName, NameCollisionOption option = NameCollisionOption.GenerateUniqueName); - } -} diff --git a/ClipboardCanvas/Storage/Base/IBaseStorageFile.cs b/ClipboardCanvas/Storage/Base/IBaseStorageFile.cs deleted file mode 100644 index 553d9288..00000000 --- a/ClipboardCanvas/Storage/Base/IBaseStorageFile.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.IO; -using System.Threading.Tasks; - -namespace ClipboardCanvas.Storage.Base -{ - public interface IBaseStorageFile : IBaseStorageItem - { - Task OpenAsync(FileAccess access); - } -} diff --git a/ClipboardCanvas/Storage/Base/IBaseStorageFolder.cs b/ClipboardCanvas/Storage/Base/IBaseStorageFolder.cs deleted file mode 100644 index a38afd68..00000000 --- a/ClipboardCanvas/Storage/Base/IBaseStorageFolder.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.Storage.Base -{ - public interface IBaseStorageFolder - { - Task DeleteAsync(StorageDeleteOption option, bool recursive, IProgress progress, CancellationToken cancellationToken); - } -} diff --git a/ClipboardCanvas/Storage/Base/IBaseStorageItem.cs b/ClipboardCanvas/Storage/Base/IBaseStorageItem.cs deleted file mode 100644 index 8d9bf0f4..00000000 --- a/ClipboardCanvas/Storage/Base/IBaseStorageItem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.Storage.Base -{ - public interface IBaseStorageItem - { - string Name { get; } - - string Path { get; } - - Task RenameAsync(string desiredName, NameCollisionOption option = NameCollisionOption.GenerateUniqueName); - - Task DeleteAsync(StorageDeleteOption option, IProgress progress, CancellationToken cancellationToken); - } -} diff --git a/ClipboardCanvas/Storage/WindowsStorageFile.cs b/ClipboardCanvas/Storage/WindowsStorageFile.cs deleted file mode 100644 index 2e54ab2e..00000000 --- a/ClipboardCanvas/Storage/WindowsStorageFile.cs +++ /dev/null @@ -1,41 +0,0 @@ -using ClipboardCanvas.Storage.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.Storage -{ - public sealed class WindowsStorageFile : BaseStorageFile - { - private readonly StorageFile _inner; - - public override string Path => _inner?.Path; - - public override string Name => _inner?.Name; - - private WindowsStorageFile(StorageFile inner) - : base(null) - { - this._inner = inner; - } - - public static WindowsStorageFile FromWindowsStorageFile(StorageFile storageFile) - { - return new WindowsStorageFile(storageFile); - } - - public override Task DeleteAsync(StorageDeleteOption option, IProgress progress, CancellationToken cancellationToken) - { - return _inner.DeleteAsync(option).AsTask(); - } - - public override Task RenameAsync(string desiredName, NameCollisionOption option = NameCollisionOption.GenerateUniqueName) - { - return _inner.RenameAsync(desiredName, option).AsTask(); - } - } -} diff --git a/ClipboardCanvas/Storage/WindowsStorageFolder.cs b/ClipboardCanvas/Storage/WindowsStorageFolder.cs deleted file mode 100644 index 7b81dc75..00000000 --- a/ClipboardCanvas/Storage/WindowsStorageFolder.cs +++ /dev/null @@ -1,39 +0,0 @@ -using ClipboardCanvas.Storage.Base; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; -using System; - -namespace ClipboardCanvas.Storage -{ - public sealed class WindowsStorageFolder : BaseStorageFolder - { - private readonly StorageFolder _inner; - - private WindowsStorageFolder(StorageFolder inner) - : base(null) - { - this._inner = inner; - } - - public static WindowsStorageFolder FromWindowsStorageFile(StorageFolder storageFolder) - { - return new WindowsStorageFolder(storageFolder); - } - - public override Task DeleteAsync(StorageDeleteOption option, IProgress progress, CancellationToken cancellationToken) - { - return _inner.DeleteAsync(option).AsTask(); - } - - public override Task DeleteAsync(StorageDeleteOption option, bool recursive, IProgress progress, CancellationToken cancellationToken) - { - return _inner.DeleteAsync(option).AsTask(); - } - - public override Task RenameAsync(string desiredName, NameCollisionOption option = NameCollisionOption.GenerateUniqueName) - { - return _inner.RenameAsync(desiredName, option).AsTask(); - } - } -} diff --git a/ClipboardCanvas/Strings/de-DE/Resources.resw b/ClipboardCanvas/Strings/de-DE/Resources.resw deleted file mode 100644 index 03a5daf7..00000000 --- a/ClipboardCanvas/Strings/de-DE/Resources.resw +++ /dev/null @@ -1,638 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Eine Sammlung hinzufügen - - - Das Programm muss neu gestartet werden, um die Änderungen anzuwenden. - - - Autoeinfügen - - - Regel hinzufügen - - - Inhalt wird eingefügt - - - Der Inhalt wurde eingefügt - - - Autoeinfügen konnte den Inhalt nicht einfügen. Fehler: {0} - - - Typ auschließen - - - Autoeinfügen erfolgreich - - - Autoeinfügen ist deaktiviert - - - Größer als - - - Kein Ziel - - - Einfügen in: - - - Autoeinfügen fehlgeschlagen - - - Dateigröße... - - - Regelsatz - - - Filter eingeben... - - - Kleiner als - - - Datei - - - Ordner - - - Bild - - - Text - - - Url - - - Autoeinfügen arbeitet - - - Abbrechen - - - Du bist im 'Unbegrenzte Leinwand'-Modus - - - Du bist im 'Eine Leinwand'-Modus - - - Ändern - - - Icon ändern - - - Ruft Daten aus GitHub ab - - - Beim Versuch des Abrufes der Versionshinweise aus GitHub ist ein Fehler aufgetreten - - - Clipboard Canvas wurde aktualisiert! - - - In GitHub ansehen - - - Dieses Problem melden - - - Wir sind auf ein Problem gestoßen von dem wir uns nicht erholen konnten. - - - Clipboard Canvas ist spektakulär abgestürzt! - - - Suche schließen - - - {0} Fehler: {1} - - - Der mit dieser Sammlung assoziierte Ordner konnte nicht gefunden werden. - - - Die Sammlung wird initialisiert - - - Wir haben festgestellt, dass einige Gegenstände fehlen. Wir laden die Sammlung für dich neu. - - - Sammlungsvorschau: - - - Sammlungen - - - Doppelklick zum Öffnen dieser Sammlung. -Rechtsklick für mehr Optionen. - - - Sammlung unverfügbar - - - Im beschränkten Zugang fortfahren - - - Datei kopieren - - - Ausgewählten Text kopieren - - - Aktuelles Icon konnte nicht gelöscht werden. - - - Icon konnte nicht entfernt werden - - - Sammlung konnte nicht umbenannt werden - - - Eigenes Sammlungsicon konnte nicht gesetzt werden - - - Aktuelle Sammlung - - - Standardsammlung - - - Löschen - - - Datei löschen - - - Unbegrenzte Leinwand löschen - - - Gegenstand löschen - - - Bist du sicher, dass du diesen Gegenstand löschen möchtest? - - - Dauerhaft löschen - - - Referenz löschen - - - Ziehen und loslassen zum Einfügen von Inhalten - - - Kürzlich eingefügte Gegenstände tauchen hier auf deiner Zeitleiste auf. - - - Autoeinfügen aktivieren - - - Fehler - - - Fehler beim Überschreiben der Referenz. Fehler: {0} - - - Dateigrößenregel wird nicht auf Ordner angewandt. - - - Nächste finden - - - Vorherige finden - - - Rechtsklicke gewünschte Sammlung und setze sie als ein Autoeinfügen-Ziel - - - Autoeinfügen-Ziel auswählen - - - Unbegrenzte Leinwand ist leer - - - Ungültige Datei. - - - Es gibt keine Gegenstände zur Vorschau. - - - Wechsle in die Vogelperspektive deiner Dateien. Lokalisiere schnell was du brauchst, dank der Suchfunktion in der Sammlungsvorschau. - - - Vorschau deiner Sammlung - - - Nutze Sammlungen, um dich rasch in deinen Arbeitsbereichen umherzubewegen. Passe Sie entsprechend deinen Wünschen an. Gruppiere deine Arbeit in getrennten Ordnern. - - - Verwalte deinen Arbeitsbereich mithilfe von Sammlungen - - - Du bist nun bereit, Clipboard Canvas zu nutzen! Du kannst deine App-Erfahrung in den Einstellungen anpassen. - - - Du bist startklar! - - - Betrachte deine Dateien auf der grenzenlosen Leinwand. Die Unbegrenze Leinwand ist deine Desktop-Pinnwand, die dir erlaubt, deine Arbeit in flexibler Manier zu verwalten. Ziehe deine eingefügten Dateien umher und übernimm die volle Kontrolle über sie. - - - Unbegrenzte Leinwand - - - Füge schnell Inhalt in deine 'Eine Leinwand' ein und interagiere mit ihm. 'Eine Leinwand' gibt dir eine vollformatige, interaktive Vorschau verschiedenster Dateien: - -- Bildvorschau -- Medienvorschau -- Textvorschau -- Markdown-Format-Vorschau -- Ordner- und Datei-Vorschau - - - 'Eine Leinwand' - - - Mit Referenz-Dateien brauchst du dich nicht um eine volle Festplatte zu sorgen. Referenzierte Dateien sparen Platz, indem sie eine auf die Originaldatei verweisende Referenz speichern. Dank Clipboard Canvas' nahtloser Integration funktionieren referenzierte Dateien sowohl in der 'Einen Leinwand' sowie der 'Unbegrenzten Leinwand' einwandfrei. - - - Spare Speicherplatz mit Referenz-Dateien - - - Verpasse keine(n) Datei oder Ordner mit der Zeitleiste auf deiner Startseite. Die Zeitleiste verfolgt kürzlich eingefügte Gegenstände, damit du dir keine Sorgen vor irgendetwas Unbemerktem machen musst. - - - Erhalte eine Analyse der kürzlichen Aktivitäten auf deiner Zeitleiste - - - Danke, dass du Clipboard Canvas ausprobierst! Um dir den Start zu erleichtern, wird dich diese Präsentation durch die wichtigsten Funktionen dieses Programms führen. - - - Welcome to Clipboard Canvas! - - - Leinwand öffnen - - - Sammlungsort öffnen - - - Enthaltenden Ordner öffnen - - - Datei öffnen - - - 'Unbegrenzte Leinwand'-Ordner öffnen - - - Neue Leinwand öffnen - - - Neue 'Unbegrenzte Leinwand' öffnen - - - Referenz-enthaltenden Ordner öffnen - - - Einstellungen öffnen - - - Der Vorgang wurde abgebrochen. - - - Referenz einfügen - - - Datei als Referenz eingefügt - - - Diese Datei wurde als Referenz auf die Originaldatei eingefügt. Clipboard Canvas lädt die referenzierte Originialdatei. - -Du kannst die Referenz überschreiben und den Gegenstand direkt in diese Sammlung kopieren, indem du den unteren Knopf drückst. - - - Aus der Zwischenablage einfügen - - - Referenz-Dateien - - - Sammlung neu laden - - - Sammlung entfernen - - - Aus dieser Sammlung entfernen - - - Icon entfernen - - - Umbenennen - - - Gegenstandspositionen zurücksetzen - - - Programm neustarten - - - Beschränkter Zugang - - - Clipboard Canvas benötigt die Berechtigung, auf das Dateisystem zuzugreifen, um richtig zu funktionieren. Ohne die Berechtigung werden einige Funktionen gesperrt oder limitiert. - - - Du kannst die Berechtigung in den Einstellungen erteilen, woraufhin das Programm geschlossen wird. - - - Du kannst auch im 'Beschränkter Zugang'-Modus fortfahren. Klicke für mehr Informationen. - - - Clipboard Canvas ist zurzeit im 'Beschränkter Zugang'-Modus. Klicke für mehr Informationen. - - - Erneut versuchen - - - Suche - - - Alles auswählen - - - Als Autoeinfügen-Ziel setzen - - - Einstellungen - - - Über - - - Version {0} - - - Protokolldateien-Speicherort öffnen - - - Datenschutzerklärung - - - Beim Laden der Datenschutzerklärung ist ein Fehler aufgetreten - - - Lädt Clipboard Canvas' Datenschutzerklärung aus GitHub - - - Versionshinweise - - - Clipboard Canvas in GitHub einen Stern geben - - - Rückmeldung abgeben - - - Einführungsansicht anzeigen - - - Allgemein - - - Windows' Standard - - - 'Unbegrenzte Leinwand' als Standard nutzen - - - Sprache - - - Dateien standardmäßig dauerhaft löschen - - - Bestätigungsdialog beim Löschen von Gegenständen anzeigen - - - Zeitleistenwidget auf der Startseite anzeigen - - - Benachrichtigungen - - - Eine Benachrichtigung bei fehlerhaftem Autoeinfügen anzeigen - - - Eine Benachrichtigung bei beginnendem Autoeinfügen anzeigen - - - Bei Programmabstürzen Fehlermeldung anzeigen - - - Einfügen - - - Beim Einfügen eine neue Leinwand öffnen - - - Dateien als Referenz einfügen - - - Referenz-Dateien erlauben dir das Einfügen von Dateien ohne Kopien dieser zu erstellen. Wird diese Einstellung aktiviert, wird jede Datei als Referenz eingefügt. - -Eine auf die Originaldatei verweisende Referenz-Datei wird erstellt, welche nahtlos durch Clipboard Canvas dargestellt wird. - - - Diese Einstellung kann im 'Beschränkter Zugang'-Modus nicht aktiviert werden. - - - Markdown-Format statt Textdatei verwenden - - - In Sammlung anzeigen - - - Status-Center - - - 0.00% abgeschlossen - - - Der Vorgang wurde abgebrochen - - - Vorgang abgebrochen - - - Der Vorgang ist abgeschlossen - - - Vorgang abgeschlossen - - - Überschreiben der Referenz abgebrochen - - - Überschreiben der Referenz erfolgreich - - - Einfügen wurde abgebrochen - - - Einfügen erfolgreich - - - {0}% abgeschlossen - - - Arbeitet... - - - Startet... - - - Willkommen in Clipboard Canvas! - - - Zur 'Unbegrenzten Leinwand' wechseln - - - Zur Einen Leinwand' wechseln - - - Zeitleiste - - - Ein unbekannter Fehler ist aufgetreten. - - - In GitHub ansehen - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/de/Resources.resw b/ClipboardCanvas/Strings/de/Resources.resw deleted file mode 100644 index 791487e2..00000000 --- a/ClipboardCanvas/Strings/de/Resources.resw +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Add a collection - - - The app will need to be restarted in order to apply the changes. - - - Autopaste - - - Add rule - - - Content is being pasted - - - The content has been pasted - - - Autopaste was unable to paste content. Error: {0} - - - Exclude type - - - Autopaste pasted successfully - - - Autopaste is disabled - - - Larger than - - - No target - - - Paste to: - - - Autopaste failed - - - File size... - - - Rule set - - - Type filter... - - - Smaller than - - - File - - - Folder - - - Image - - - Text - - - Url - - - Autopaste is working - - - Cancel - - - You're in Infinite Canvas mode - - - You're in One Canvas mode - - - Change - - - Change icon - - - Fetching data from GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - - - Clipboard Canvas has been updated! - - - View on GitHub - - - Report this issue - - - We've encountered an issue that we couldn't recover from. - - - Clipboard Canvas crashed spectacularly! - - - Close Search - - - {0} Error: {1} - - - The folder associated with this collection was not found. - - - The Collection is being initialized - - - We've noticed some items went missing. We're reloading the Collection for you. - - - Collection Preview: - - - Collections - - - Double click to open this Collection. -Right click for more options. - - - Collection unavailable - - - Continue in Restricted Access - - - Copy file - - - Copy selected text - - - Current icon could not be deleted. - - - Couldn't remove icon. - - - Couldn't rename Collection - - - Couldn't set custom Collection icon. - - - Current Collection: - - - Default Collection - - - Delete - - - Delete file - - - Delete Infinite Canvas - - - Delete item - - - Are you sure you want to delete this item? - - - Permanently delete - - - Delete Reference - - - Drag and drop or paste to add content - - - Recently pasted items will show up on your Timeline here - - - Enable Autopaste - - - Error - - - Error whilst overriding reference. Error: {0} - - - File size rule does not apply to folders. - - - Find next - - - Find previous - - - Right click desired collection and set it as an autopaste target. - - - Select autopaste target - - - Infinite Canvas is empty - - - Invalid file. - - - There are no items to preview. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - - - Preview your Collections - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - - - Manage your workspace using Collections - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - - - You're good to go! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - - - Infinite Canvas - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - - - One Canvas - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - - - Save storage space with Reference Files - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - - - See a run-down of recent activity on your Timeline - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - - - Welcome to Clipboard Canvas! - - - Open canvas - - - Open Collection location - - - Open containing folder - - - Open file - - - Open Infinite Canvas folder - - - Open new Canvas - - - Open new Infinite Canvas - - - Open reference containing folder - - - Open Settings - - - The operation was canceled. - - - Paste reference - - - File pasted as reference - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - - - Paste from Clipboard - - - Reference Files - - - Reload Collection - - - Remove Collection - - - Remove from this section - - - Remove icon - - - Rename - - - Reset item positions - - - Restart Application - - - Restricted Access - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - - - You can also continue in Restricted Access mode with limited features. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - - - Retry - - - Search - - - Select all - - - Set as Autopaste target - - - Settings - - - About - - - Version {0} - - - Open log file location - - - Privacy Policy - - - An error occurred while trying to load privacy policy - - - Pulling Clipboard Canvas' privacy policy from GitHub - - - Release notes - - - Star Clipboard Canvas on GitHub - - - Submit feedback - - - View introduction page - - - General - - - Windows default - - - Use Infinite Canvas as default - - - Language - - - Permanently delete items as default - - - Show confirmation dialog when deleting items - - - Show Timeline widget on the Homepage - - - Notifications - - - Show a notification when autopaste fails - - - Show a notification when autopaste starts pasting - - - Show error notification if app crashes - - - Pasting - - - Open new canvas on paste - - - Paste files as reference - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - - - Cannot enable this setting while in Restricted Access mode. - - - Use markdown format instead of text files - - - Show in Collection - - - Status Center - - - Completed 0.00% - - - The operation was canceled - - - Operation canceled - - - The operation is complete - - - Operation complete - - - Overwriting Reference was canceled - - - Overwriting Reference complete - - - Pasting was canceled - - - Pasting complete - - - Completed {0}% - - - Processing... - - - Starting... - - - Switch to Infinite Canvas - - - Switch to One Canvas - - - Timeline - - - An unknown error occurred. - - - View on GitHub - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/en-US/Resources.resw b/ClipboardCanvas/Strings/en-US/Resources.resw deleted file mode 100644 index 791487e2..00000000 --- a/ClipboardCanvas/Strings/en-US/Resources.resw +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Add a collection - - - The app will need to be restarted in order to apply the changes. - - - Autopaste - - - Add rule - - - Content is being pasted - - - The content has been pasted - - - Autopaste was unable to paste content. Error: {0} - - - Exclude type - - - Autopaste pasted successfully - - - Autopaste is disabled - - - Larger than - - - No target - - - Paste to: - - - Autopaste failed - - - File size... - - - Rule set - - - Type filter... - - - Smaller than - - - File - - - Folder - - - Image - - - Text - - - Url - - - Autopaste is working - - - Cancel - - - You're in Infinite Canvas mode - - - You're in One Canvas mode - - - Change - - - Change icon - - - Fetching data from GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - - - Clipboard Canvas has been updated! - - - View on GitHub - - - Report this issue - - - We've encountered an issue that we couldn't recover from. - - - Clipboard Canvas crashed spectacularly! - - - Close Search - - - {0} Error: {1} - - - The folder associated with this collection was not found. - - - The Collection is being initialized - - - We've noticed some items went missing. We're reloading the Collection for you. - - - Collection Preview: - - - Collections - - - Double click to open this Collection. -Right click for more options. - - - Collection unavailable - - - Continue in Restricted Access - - - Copy file - - - Copy selected text - - - Current icon could not be deleted. - - - Couldn't remove icon. - - - Couldn't rename Collection - - - Couldn't set custom Collection icon. - - - Current Collection: - - - Default Collection - - - Delete - - - Delete file - - - Delete Infinite Canvas - - - Delete item - - - Are you sure you want to delete this item? - - - Permanently delete - - - Delete Reference - - - Drag and drop or paste to add content - - - Recently pasted items will show up on your Timeline here - - - Enable Autopaste - - - Error - - - Error whilst overriding reference. Error: {0} - - - File size rule does not apply to folders. - - - Find next - - - Find previous - - - Right click desired collection and set it as an autopaste target. - - - Select autopaste target - - - Infinite Canvas is empty - - - Invalid file. - - - There are no items to preview. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - - - Preview your Collections - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - - - Manage your workspace using Collections - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - - - You're good to go! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - - - Infinite Canvas - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - - - One Canvas - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - - - Save storage space with Reference Files - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - - - See a run-down of recent activity on your Timeline - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - - - Welcome to Clipboard Canvas! - - - Open canvas - - - Open Collection location - - - Open containing folder - - - Open file - - - Open Infinite Canvas folder - - - Open new Canvas - - - Open new Infinite Canvas - - - Open reference containing folder - - - Open Settings - - - The operation was canceled. - - - Paste reference - - - File pasted as reference - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - - - Paste from Clipboard - - - Reference Files - - - Reload Collection - - - Remove Collection - - - Remove from this section - - - Remove icon - - - Rename - - - Reset item positions - - - Restart Application - - - Restricted Access - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - - - You can also continue in Restricted Access mode with limited features. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - - - Retry - - - Search - - - Select all - - - Set as Autopaste target - - - Settings - - - About - - - Version {0} - - - Open log file location - - - Privacy Policy - - - An error occurred while trying to load privacy policy - - - Pulling Clipboard Canvas' privacy policy from GitHub - - - Release notes - - - Star Clipboard Canvas on GitHub - - - Submit feedback - - - View introduction page - - - General - - - Windows default - - - Use Infinite Canvas as default - - - Language - - - Permanently delete items as default - - - Show confirmation dialog when deleting items - - - Show Timeline widget on the Homepage - - - Notifications - - - Show a notification when autopaste fails - - - Show a notification when autopaste starts pasting - - - Show error notification if app crashes - - - Pasting - - - Open new canvas on paste - - - Paste files as reference - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - - - Cannot enable this setting while in Restricted Access mode. - - - Use markdown format instead of text files - - - Show in Collection - - - Status Center - - - Completed 0.00% - - - The operation was canceled - - - Operation canceled - - - The operation is complete - - - Operation complete - - - Overwriting Reference was canceled - - - Overwriting Reference complete - - - Pasting was canceled - - - Pasting complete - - - Completed {0}% - - - Processing... - - - Starting... - - - Switch to Infinite Canvas - - - Switch to One Canvas - - - Timeline - - - An unknown error occurred. - - - View on GitHub - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/pt-PT/Resources.resw b/ClipboardCanvas/Strings/pt-PT/Resources.resw deleted file mode 100644 index 4a12eaf1..00000000 --- a/ClipboardCanvas/Strings/pt-PT/Resources.resw +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Adicionar uma coleção - - - A aplicação terá de ser reiniciada a fim de aplicar as alterações. - - - Colagem automática - - - Adicionar regra - - - O conteúdo está a ser colado - - - O conteúdo foi colado - - - A colagem automática não conseguiu colar o conteúdo. Erro: {0} - - - Excluir tipo - - - Colagem automática colada com sucesso - - - Colagem automática está desativado - - - Maior do que - - - Sem alvo - - - Colar para: - - - Colagem automática falhou - - - Tamanho do ficheiro... - - - Conjunto de regras - - - Tipo de filtro... - - - Menor do que - - - Ficheiro - - - Pasta - - - Imagem - - - Texto - - - Url - - - Colagem automática está a trabalhar - - - Cancelar - - - Está no modo Tela Infinita - - - Está no modo de Tela Única - - - Mudar - - - Mudar ícone - - - Obtendo dados de GitHub - - - Ocorreu um erro ao tentar obter as notas de lançamento da Clipboard Canvas do GitHub - - - Clipboard Canvas foi atualizado! - - - Ver no GitHub - - - Reportar este problema - - - Encontrámos um problema do qual não pudemos recuperar. - - - Clipboard Canvas caiu de forma espetacular! - - - Fechar Pesquisa - - - {0} Erro: {1} - - - A pasta associada a esta coleção não foi encontrada. - - - A Coleção está a ser inicializada - - - Notamos que alguns artigos desapareceram. Estamos a recarregar a coleção para si. - - - Pré-visualização da coleção: - - - Coleções - - - Duplo clique para abrir esta coleção. -Clique com o botão direito do rato para mais opções. - - - Coleção indisponível - - - Continuar em Acesso Restrito - - - Copiar ficheiro - - - Copiar texto selecionado - - - O ícone atual não pode ser eliminado. - - - Não foi possível remover o ícone. - - - Não foi possível mudar o nome da Coleção - - - Não foi possível definir o ícone personalizado da Coleção. - - - Coleção atual: - - - Coleção predefinida - - - Eliminar - - - Eliminar ficheiro - - - Eliminar Tela Infinita - - - Eliminar item - - - Tem a certeza de que quer eliminar este item? - - - Eliminar permanentemente - - - Eliminar Referência - - - Arrastar e largar ou colar para adicionar conteúdo - - - Itens colados recentemente aparecerão na sua Linha do Tempo aqui - - - Ativar Colagem automática - - - Erro - - - Erro ao anular a referência. Erro: {0} - - - A regra do tamanho do ficheiro não se aplica a pastas. - - - Localizar seguinte - - - Localizar anterior - - - Clique com o botão direito do rato na coleção desejada e defina-a como um alvo de colagem automática. - - - Selecione um alvo para a colagem automática - - - A Tela Infinita está vazia - - - Ficheiro inválido. - - - Não há itens para pré-visualizar. - - - Obtenha uma vista aérea dos seus ficheiros. Localize rapidamente o que precisa graças à função de pesquisa na Pré-visualização da coleção. - - - Pré-visualize as suas Coleções - - - Utilize as Coleções para se deslocar rapidamente nos seus espaços de trabalho. Personalize as coleções de acordo com as suas necessidades. Agrupe o seu trabalho em pastas separadas. - - - Gere o seu espaço de trabalho utilizando Coleções - - - Está agora pronto para começar a usar Clipboard Canvas! Pode personalizar a sua experiência na aplicação, dirigindo-se às Definições. - - - Está pronto para ir! - - - Veja os seus ficheiros numa tela sem limites. Tela Infinita é o seu quadro de adesivos no computador que lhe permite gerir o seu trabalho de uma forma flexível. Arraste os seus ficheiros colados e assuma um controlo total dos mesmos. - - - Tela Infinita - - - Cole e interaja rapidamente com o seu conteúdo na Tela Única. Tela Única dá-lhe uma pré-visualização interativa de vários ficheiros em tamanho real: - - - Pré-visualização de imagem - - Pré-visualização dos meios de comunicação - - Pré-visualização do texto - - Pré-visualização do formato Markdown - - Pré-visualização de pastas e ficheiros - - - Tela Única - - - Com Ficheiros de Referência não tem de se preocupar em encher o seu disco rígido. Os Ficheiros de Referência poupam espaço ao manter uma referência que aponta para o ficheiro original. Graças à integração perfeita do Clipboard Canvas, os Ficheiros de Referência funcionam bem tanto na Tela Única como na Tela Infinita. - - - Guardar espaço de armazenamento com Ficheiros de Referência - - - Nunca perca um ficheiro ou pasta com a Linha do Tempo na sua página inicial. A Linha do Tempo mantém um registo dos itens recentemente colados para que não tenha de se preocupar com nada que passe despercebido! - - - Veja um resumo da atividade recente na sua Linha do Tempo - - - Obrigado por experimentar Clipboard Canvas! Para começar, esta apresentação irá guiá-lo através das características mais notáveis da aplicação. - - - Bem-vindo ao Clipboard Canvas! - - - Abrir tela - - - Abrir localização da Coleção - - - Abrir pasta contentora - - - Abrir ficheiro - - - Abrir pasta Tela Infinita - - - Abrir nova Tela - - - Abrir nova Tela Infinita - - - Abrir pasta de referência contentora - - - Abrir Definições - - - A operação foi cancelada. - - - Colar referência - - - Ficheiro colado como referência - - - Este ficheiro foi colado como uma referência ao ficheiro original. Clipboard Canvas carrega o ficheiro original para o qual a referência está a apontar. - -Pode anular a referência e copiar o item diretamente para esta coleção, premindo o botão abaixo. - - - Colar a partir da Área de transferência - - - Ficheiros de Referência - - - Recarregar Coleção - - - Remover Coleção - - - Remover desta secção - - - Remover ícone - - - Mudar o nome - - - Repor as posições do item - - - Reiniciar Aplicação - - - Acesso Restrito - - - Clipboard Canvas requer permissão para aceder ao sistema de ficheiros para que este funcione corretamente. Sem a permissão, algumas características serão desativadas e/ou limitadas. - - - Pode conceder esta permissão dirigindo-se às definições, após o que a aplicação será encerrada. - - - Também pode continuar no modo de Acesso Restrito com características limitadas. - - - Clipboard Canvas está atualmente em modo de Acesso Restrito. Clique para mais detalhes. - - - Tentar novamente - - - Pesquisar - - - Selecionar tudo - - - Definir como alvo da Colagem automática - - - Definições - - - Acerca de - - - Versão {0} - - - Abrir localização do ficheiro de registo - - - Política de Privacidade - - - Ocorreu um erro ao tentar carregar a política de privacidade - - - Puxando a política de privacidade do Clipboard Canvas do GitHub - - - Notas de lançamento - - - Estrelar Clipboard Canvas no Github - - - Submeter feedback - - - Ver página de introdução - - - Geral - - - Predefinição do Windows - - - Utilizar Tela Infinita como predefinição - - - Idioma - - - Eliminar permanentemente os itens como predefinição - - - Mostrar diálogo de confirmação ao eliminar ficheiros - - - Mostrar o widget Linha do Tempo na Página inicial - - - Notificações - - - Mostrar uma notificação quando a colagem automática falha - - - Mostrar uma notificação quando a colagem automática inicia a colagem - - - Mostrar notificação de erro se a aplicação falhar - - - Colagem - - - Abrir nova tela ao colar - - - Colar ficheiros como referência - - - Os Ficheiros de Referência permitem-lhe colar ficheiros sem criar cópias dos mesmos. Com esta definição ativada, cada ficheiro é colado como uma referência. - -É criado um ficheiro de referência apontando para o ficheiro original, que é exibido sem problemas pelo Clipboard Canvas. - - - Não é possível ativar esta definição enquanto estiver no modo de Acesso Restrito. - - - Utilizar o formato Markdown em vez de ficheiros de texto - - - Mostrar na Coleção - - - Centro de Estado - - - Completado 0.00% - - - A operação foi cancelada - - - Operação cancelada - - - A operação foi completada - - - Operação completa - - - Sobrescrita de Referência foi cancelado - - - Sobrescrita de Referência completa - - - Colagem foi cancelado - - - Colagem completa - - - Completado {0}% - - - Processando... - - - A Iniciar... - - - Trocar para Tela Infinita - - - Trocar para Tela Única - - - Linha do tempo - - - Ocorreu um erro desconhecido. - - - Ver no GitHub - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/ro-RO/Resources.resw b/ClipboardCanvas/Strings/ro-RO/Resources.resw deleted file mode 100644 index 44ae1310..00000000 --- a/ClipboardCanvas/Strings/ro-RO/Resources.resw +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Adaugă o colecție - - - Pentru a aplica schimbările va fi nevoie de o repornire a aplicației. - - - Autolipire - - - Adaugă o regulă - - - Conținutul este în curs de lipire - - - Conținutul a fost lipit - - - Autolipirea nu a putut lipi conținutul. Eroare: {0} - - - Excludere tip - - - Autolipirea a lipit cu succes - - - Autolipirea este dezactivată - - - Mai mare decât - - - Fără țintă - - - Lipire în: - - - Autolipirea a eșuat - - - Mărime fișier... - - - Set de reguli - - - Filtru tip... - - - Mai mic decât - - - Fișier - - - Folder - - - Imagine - - - Text - - - URL - - - Autolipirea funcționează - - - Anulare - - - Ești în modul Canvas Infinit - - - Ești în modul un Canvas - - - Modificare - - - Modificare pictogramă - - - Preluare date de la GitHub - - - Am întâmpinat o eroare încercând sa preluam notele de lansare Clipboard Canvas de pe GitHub - - - Clipboard Canvas a fost actualizat! - - - Vezi pe GitHub - - - Raportează această problemă - - - Am întâmpinat o problema din care n-am putut sa ne revenim. - - - Clipboard Canvas a avut un accident spectaculos! - - - Închidere Căutare - - - {0} Eroare: {1} - - - Folderul asociat cu această colecție nu a fost găsit. - - - Colecția este în curs de inițializare - - - Am văzut că unele elemente au fost date dispărute. Reîncărcăm Colecția pentru tine. - - - Previzualizare Colecție: - - - Colecții - - - Dublu-clic pentru a deschide această Colecție. -Clic dreapta pentru mai multe opțiuni. - - - Colecție indisponibilă - - - Continuă în Acces restricționat - - - Copiere fișier - - - Copiere text selectat - - - Pictograma curentă nu a putut fi ștearsă. - - - Nu s-a putut șterge pictograma. - - - Nu s-a putut redenumi Colecția. - - - Nu s-a putut seta o pictogramă personalizată pentru Colecție. - - - Colecția curentă: - - - Colecția implicită - - - Ștergere - - - Ștergere fișier - - - Ștergere Canvas Infinit - - - Ștergere element - - - Sigur vrei să ștergi acest element? - - - Ștergere definitivă - - - Ștergere Referință - - - Drag and drop sau lipește pentru a adăuga conținut - - - Elemente lipite recent vor fi apărea în Cronologie, chiar aici - - - Activează autolipirea - - - Eroare - - - Eroare în timpul suprascrierii referinței. Eroare: {0} - - - Regula mărimii fișierelor nu este aplicată la foldere. - - - Găsire următor - - - Găsire precedent - - - Clic-dreapta pe Colecția dorită și seteaz-o ca o țintă pentru autolipire. - - - Selectare țintă autolipire - - - Canvasul Infinit este gol - - - Fișier invalid. - - - Nu există elemente de vizualizat. - - - Ia o privire scurtă la fișierele tale. Lochează rapid toate fișierele de care ai nevoie mulțumită funcției de căutare în Previzualizare Colecție. - - - Previzualizează-ți Colecțiile - - - Utilizează Colecțiile pentru a te muta cu elan printre spații de lucru. Personalizează colecțiile nevoilor tale. Grupează-ți munca în foldere separate. - - - Gestionează-ți spațiul de lucru cu Colecții - - - Ești gata să folosești Clipboard Canvas! Îți poți personaliza experiența în Setări. - - - Ești gata de plecare! - - - Vezi fișierele tale pe un canvas fără limite. Pe bune. Canvasul Infinit este stickyboard-ul ecranului tău care îți permite să îți gestionezi munca într-o manieră flexibilă. - - - Canvas Infinit - - - Lipește și interacționează rapid cu conținutul tău pe un Canvas. Un Canvas dă o previzualizare interactivă în mărime-completă a diverse fișiere: - - - Previzualizare imagine - - Previzualizare media - - Previzualizare text - - Previzualizare format Markdown - - Previzualizare folder și fișier - - - Un Canvas - - - Cu Fișiere de Referință, nu te îngrijora despre spațiu de stocare. Ele salvează spațiu ținând o referință care punctează către fișierul original. Mulțumită integrării fără-efort Clipboard Canvas, Fișierele de Referință merg bine și pe un Canvas, dar și pe Canvasul Infinit. - - - Salvează spațiu de stocare cu Fișierele de Referință - - - Nu rata niciun fișier sau folder mulțumită Cronologiei de pe pagina de pornire. Cronologia are grijă de fișierele lipite recent ca tu să n-ai grijă despre fișiere ratate! - - - Vezi o analiză a activității recente în Cronologia ta - - - Îți mulțumim pentru că încerci Clipboard Canvas! Ca să știi tot-tot, această prezentare te va ghida printre cele mai notabile funcționalități ale aplicației. - - - Bun venit la Clipboard Canvas! - - - Deschidere canvas - - - Deschidere locație Colecție - - - Deschidere folder conținut - - - Deschidere fișier - - - Deschidere folder Canvas Infinit - - - Deschidere Canvas nou - - - Deschidere Canvas Infinit - - - Deschidere folder care conține referința - - - Deschidere Setări - - - Operația a fost anulată. - - - Lipire referință - - - Fișier lipit ca referință - - - Acest fișier a fost lipit ca o referință către fișierul original. Clipboard Canvas încarcă fișierul original spre care referința punctează. - -Poți suprascrie referința și copia elementul direct în această colecție apăsând butonul de mai jos. - - - Lipire din Clipboard - - - Fișiere de Referință - - - Reîncărcare Colecție - - - Ștergere Colecție - - - Ștergere din această secțiune - - - Ștergere pictogramă - - - Redenumire - - - Resetare poziții pictograme - - - Repornire aplicație - - - Acces restricționat - - - Clipboard Canvas are nevoie de acces la sistemul de fișiere pentru a funcționa normal. Fără permisiune, unele funcții vor fi dezactivate și/sau limitate. - - - Poți permite acest lucru în Setări, unde aplicația va fi închisă. - - - Poți continua în Acces restricționat cu funcționalitate redusă. - - - Clipboard Canvas este în Acces restricționat. Clic pentru mai multe detalii. - - - Încearcă din nou - - - Căutare - - - Selectare totală - - - Setare ca țintă autolipire - - - Setări - - - Despre - - - Versiunea {0} - - - Deschidere locație fișier log - - - Politica de confidențialitate - - - Am întâmpinat o eroare încercând să încărcăm politica de confidențialitate - - - Se preia politica de confidențialitate Clipboard Canvas de pe GitHub - - - Note de lansare - - - Star Clipboard Canvas pe GitHub - - - Trimitere feedback - - - Vezi pagina introductivă - - - General - - - Implicit Windows - - - Utilizează Canvasul Infinit ca setare implicită - - - Limbă - - - Șterge elemente definitiv în mod implicit - - - Afișează un dialog de confirmare la ștergerea elementelor - - - Afișează widget Cronologie pe pagina de pornire - - - Notificări - - - Afișează o notificare când autolipirea eșuează - - - Afișează o notificare când autolipirea începe să lipească - - - Afișează notificare eroare când aplicația are un accident - - - Lipire - - - Deschide un canvas nou la lipire - - - Lipește fișierele ca referințe - - - Fișierele de Referință îți permit sa lipești fișiere fără să creezi copii ale acestora. Cu această setare activată, fiecare fișier este lipit ca o referință. - -Un fișier de referință este creat punctând la locația fișierului original care este afișat fără efort de către aplicație. - - - Nu se poate activa această setare în modul Acces restricționat. - - - Utilizează formatul markdown în favoarea fișierelor text - - - Afișare în Colecție - - - Centru de stare - - - 0.00% complet - - - Operația a fost anulată - - - Operație anulată - - - Operația este completă - - - Operație completă - - - Suprascrierea Referință a fost anulată - - - Referința a fost suprascrisă cu succes - - - Lipire anulată - - - Lipire completă - - - {0}% complet - - - Se procesează... - - - Se inițializează... - - - Comută la Canvas Infinit - - - Comută la un Canvas - - - Cronologie - - - O eroare necunoscută a fost întâmpinată. - - - Vezi pe GitHub - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/ru-RU/Resources.resw b/ClipboardCanvas/Strings/ru-RU/Resources.resw deleted file mode 100644 index ad723c94..00000000 --- a/ClipboardCanvas/Strings/ru-RU/Resources.resw +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Добавить коллекцию - - - Чтобы применить изменения, приложение необходимо перезапустить. - - - Автовставка - - - Добавить правило - - - Содержимое вставляется - - - Содержимое вставлено - - - Автовставка не смогла обработать содержимое. Ошибка: {0} - - - Исключить тип - - - Автовставка осуществлена - - - Автовставка отключена - - - Больше, чем - - - Нет цели - - - Вставить в: - - - Автовставка не удалась - - - Размер файла... - - - Набор правил - - - Фильтр типа... - - - Меньше, чем - - - Файл - - - Папка - - - Изображение - - - Текст - - - Ссылка - - - Автовставка осуществляется - - - Отмена - - - Вы находитесь в режиме бесконечного полотна - - - Вы находитесь в режиме одного полотна - - - Изменить - - - Изменить иконку - - - Получение данных из GitHub - - - Произошла ошибка при попытке получить заметки о выпуске Clipboard Canvas' из GitHub - - - Clipboard Canvas был обновлен! - - - Просмотреть на GitHub - - - Сообщить о проблеме - - - Мы столкнулись с проблемой, от которой не смогли оправиться. - - - Clipboard Canvas драматично упал! - - - Закрыть поиск - - - {0} Ошибка: {1} - - - Папка, связанная с этой коллекцией, не найдена. - - - Коллекция инициализируется - - - Мы заметили, что некоторые объекты пропали. Мы перезагружаем коллекцию для вас. - - - Предпросмотр коллекции: - - - Коллекции - - - Щелкните дважды, чтобы открыть эту коллекцию. -Щелкните правой кнопкой мыши для получения дополнительных параметров. - - - Коллекция недоступна - - - Продолжить в ограниченном режиме - - - Копировать файл - - - Копировать выбранный текст - - - Текущая иконка не может быть удалена. - - - Не удалось удалить иконку. - - - Не удалось переименовать коллекцию - - - Не удалось установить иконку коллекции. - - - Текущая коллекция: - - - Коллекция по умолчанию - - - Удалить - - - Удалить файл - - - Удалить бесконечное полотно - - - Удалить объект - - - Вы уверены, что хотите удалить этот объект? - - - Удалить навсегда - - - Удалить упоминание - - - Перетащите или вставьте для добавления содержимого - - - Недавно вставленные объекты будут отображаться на временной шкале здесь - - - Включить автовставку - - - Ошибка - - - Ошибка при переопределении упоминания. Ошибка: {0} - - - Правило размера файла не применяется к папкам. - - - Найти следующее - - - Найти предыдущее - - - Щелкните правой кнопкой мыши по коллекции и установите ее в качестве цели автовставки. - - - Выберите цель автовставки - - - Бесконечное полотно пусто - - - Недопустимый файл. - - - Нет объектов для предпросмотра. - - - Получите представление о ваших файлах с высоты птичьего полета. Быстро находите то, что вам нужно, благодаря функции поиска в разделе предпросмотра коллекции. - - - Предпросмотр ваших коллекций - - - Используйте коллекции для быстрого перемещения по рабочему пространству. Настраивайте коллекции в соответствии со своими потребностями. Группируйте работу в отдельные папки. - - - Управление рабочим пространством с помощью коллекций - - - Теперь вы готовы начать использовать Clipboard Canvas! Вы можете настроить работу с приложением в соответствующем разделе. - - - Вы готовы к работе! - - - Просматривайте свои файлы на бесконечном полотне. Бесконечное полотно представляет собой настольную доску, позволяющую гибко управлять работой. Перетаскивайте вставленные файлы и получайте полный контроль над ними. - - - Бесконечное полотно - - - Быстрая вставка и взаимодействие с содержимым на одном полотне. Одно полотно дает возможность интерактивного предварительного просмотра различных файлов в натуральную величину: - - - Предпросмотр изображений - - Предпросмотр мультимедиа - - Предпросмотр текста - - Предпросмотр формата Markdown - - Предпросмотр папок и файлов - - - Одно полотно - - - С файлами упоминания вам не придется беспокоиться о заполнении жесткого диска. Файлы упоминания экономят место, поскольку содержат ссылку, указывающую на исходный файл. Благодаря бесшовной интеграции с Clipboard Canvas файлы упоминания отлично работают на любом полотне. - - - Экономьте место с файлами упоминания - - - Никогда не пропускайте объекты с временной шкалой на вашей домашней странице. Временная шкала отслеживает недавно вставленные объекты, поэтому вам не придется беспокоиться о том, что файл или папка ускользнет от вашего взора! - - - Просмотр последних действий на временной шкале - - - Спасибо, что попробовали Clipboard Canvas! Чтобы вы могли начать работу, в этой презентации мы расскажем о самых важных функциях приложения. - - - Добро пожаловать в Clipboard Canvas! - - - Открыть полотно - - - Открыть расположение коллекции - - - Открыть содержащую папку - - - Открыть файл - - - Открыть папку бесконечного полотна - - - Открыть новое полотно - - - Открыть новое бесконечное полотно - - - Открыть папку, содержащую упоминания - - - Открыть параметры - - - Операция была отменена. - - - Вставить упоминание - - - Файл вставлен как упоминание - - - Этот файл был вставлен как упоминание исходного файла. Clipboard Canvas загружает исходный файл, на который указывает ссылка. - -Вы можете отменить упоминание и скопировать объект непосредственно в эту коллекцию, нажав кнопку ниже. - - - Вставить из буфера обмена - - - Файлы упоминания - - - Перезагрузить коллекцию - - - Удалить коллекцию - - - Удалить из этого раздела - - - Удалить иконку - - - Переименовать - - - Сбросить позицию объектов - - - Перезапустить приложение - - - Ограниченный доступ - - - Для корректной работы Clipboard Canvas требуется разрешение на доступ к файловой системе. Без этого разрешения некоторые функции будут отключены и/или ограничены. - - - Вы можете предоставить это разрешение, перейдя в параметры, после чего приложение будет закрыто. - - - Вы также можете продолжить работу в режиме ограниченного доступа с заблокированными функциями. - - - В настоящее время Clipboard Canvas находится в режиме ограниченного доступа. Нажмите для получения более подробной информации. - - - Повторить - - - Поиск - - - Выбрать все - - - Установить в качестве цели автовставки - - - Параметры - - - О приложении - - - Версия {0} - - - Открыть логи - - - Политика конфиденциальности - - - В ходе загрузки политики конфиденциальности произошла ошибка - - - Получение политики конфиденциальности Clipboard Canvas' из GitHub - - - Примечания к выпуску - - - Отметить Clipboard Canvas на GitHub - - - Отправить отзыв - - - Просмотреть вводную страницу - - - Общие - - - Как в системе - - - Использовать бесконечное полотно по умолчанию - - - Язык - - - Удаление навсегда по умолчанию - - - Показывать диалог подтверждения при удалении - - - Показывать временную шкалу на домашней странице - - - Уведомления - - - Показывать уведомление при неудачной автовставке - - - Показывать уведомление, когда начинается автовставка - - - Показывать уведомление при сбое приложения - - - Вставка - - - Открывать новое полотно при вставке - - - Вставлять объекты как файлы упоминания - - - Файлы упоминания позволяют вставлять объекты без создания их копий. При включении этого параметра каждый объект вставляется как упоминание. - -Файл упоминания, указывающий на исходный объект, создается и беспрепятственно отображается в Clipboard Canvas. - - - Невозможно включить этот параметр в режиме ограниченного доступа. - - - Использовать формат Markdown вместо текстовых файлов - - - Показывать в коллекции - - - Центр состояния - - - Завершено 0.00% - - - Операция была отменена - - - Операция отменена - - - Операция успешно выполнена - - - Операция выполнена - - - Переопределение упоминания отменено - - - Переопределение упоминания выполнено - - - Вставка была отменена - - - Вставка успешно выполнена - - - Завершено {0}% - - - Обработка... - - - Начало... - - - Переключиться на бесконечное полотно - - - Переключиться на одно полотно - - - Временная шкала - - - Произошла неизвестная ошибка. - - - Просмотреть на GitHub - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/ru/Resources.resw b/ClipboardCanvas/Strings/ru/Resources.resw deleted file mode 100644 index 791487e2..00000000 --- a/ClipboardCanvas/Strings/ru/Resources.resw +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Add a collection - - - The app will need to be restarted in order to apply the changes. - - - Autopaste - - - Add rule - - - Content is being pasted - - - The content has been pasted - - - Autopaste was unable to paste content. Error: {0} - - - Exclude type - - - Autopaste pasted successfully - - - Autopaste is disabled - - - Larger than - - - No target - - - Paste to: - - - Autopaste failed - - - File size... - - - Rule set - - - Type filter... - - - Smaller than - - - File - - - Folder - - - Image - - - Text - - - Url - - - Autopaste is working - - - Cancel - - - You're in Infinite Canvas mode - - - You're in One Canvas mode - - - Change - - - Change icon - - - Fetching data from GitHub - - - An error occurred while trying to fetch Clipboard Canvas' release notes from GitHub - - - Clipboard Canvas has been updated! - - - View on GitHub - - - Report this issue - - - We've encountered an issue that we couldn't recover from. - - - Clipboard Canvas crashed spectacularly! - - - Close Search - - - {0} Error: {1} - - - The folder associated with this collection was not found. - - - The Collection is being initialized - - - We've noticed some items went missing. We're reloading the Collection for you. - - - Collection Preview: - - - Collections - - - Double click to open this Collection. -Right click for more options. - - - Collection unavailable - - - Continue in Restricted Access - - - Copy file - - - Copy selected text - - - Current icon could not be deleted. - - - Couldn't remove icon. - - - Couldn't rename Collection - - - Couldn't set custom Collection icon. - - - Current Collection: - - - Default Collection - - - Delete - - - Delete file - - - Delete Infinite Canvas - - - Delete item - - - Are you sure you want to delete this item? - - - Permanently delete - - - Delete Reference - - - Drag and drop or paste to add content - - - Recently pasted items will show up on your Timeline here - - - Enable Autopaste - - - Error - - - Error whilst overriding reference. Error: {0} - - - File size rule does not apply to folders. - - - Find next - - - Find previous - - - Right click desired collection and set it as an autopaste target. - - - Select autopaste target - - - Infinite Canvas is empty - - - Invalid file. - - - There are no items to preview. - - - Get a bird's eye view of your files. Quickly locate what you need thanks to search function in Collection Preview. - - - Preview your Collections - - - Use Collections to swiftly move around your workspaces. Customize collections to fit your needs. Group your work in separate folders. - - - Manage your workspace using Collections - - - You are now ready to start using Clipboard Canvas! You can customize your app experience by heading to Settings. - - - You're good to go! - - - View your files on limit-free canvas. Infinite Canvas is your desktop sticky board that allows you to manage your work in a flexible fashion. Drag around pasted files and take a full control of them. - - - Infinite Canvas - - - Quickly paste and interact with your content on One Canvas. One Canvas gives you a fully-sized interactive preview of various files: - - - Image preview - - Media preview - - Text preview - - Markdown format preview - - Folder and file preview - - - One Canvas - - - With Reference Files you don't have to worry about filling up your hard drive. Reference Files save space by holding a reference that points to original file. Thanks to Clipboard Canvas seamless integration, Reference Files work great in both One Canvas and Infinite Canvas. - - - Save storage space with Reference Files - - - Never miss a file or folder with Timeline on your homepage. Timeline keeps track of recently pasted items so you don't have to worry about anything sliding past unnoticed! - - - See a run-down of recent activity on your Timeline - - - Thank you for trying out Clipboard Canvas! To get you started, this presentation will guide you through most notable features of the app. - - - Welcome to Clipboard Canvas! - - - Open canvas - - - Open Collection location - - - Open containing folder - - - Open file - - - Open Infinite Canvas folder - - - Open new Canvas - - - Open new Infinite Canvas - - - Open reference containing folder - - - Open Settings - - - The operation was canceled. - - - Paste reference - - - File pasted as reference - - - This file has been pasted as a reference to the original file. Clipboard Canvas loads the original file that the reference is pointing to. - -You can override the reference and copy the item directly to this collection by pressing the button below. - - - Paste from Clipboard - - - Reference Files - - - Reload Collection - - - Remove Collection - - - Remove from this section - - - Remove icon - - - Rename - - - Reset item positions - - - Restart Application - - - Restricted Access - - - Clipboard Canvas requires permission to access the file system for it to work correctly. Without the permission, some features will be disabled and/or limited. - - - You can grant this permission by heading to settings, whereupon the app will be closed. - - - You can also continue in Restricted Access mode with limited features. - - - Clipboard Canvas is currently in Restricted Access mode. Click for more details. - - - Retry - - - Search - - - Select all - - - Set as Autopaste target - - - Settings - - - About - - - Version {0} - - - Open log file location - - - Privacy Policy - - - An error occurred while trying to load privacy policy - - - Pulling Clipboard Canvas' privacy policy from GitHub - - - Release notes - - - Star Clipboard Canvas on GitHub - - - Submit feedback - - - View introduction page - - - General - - - Windows default - - - Use Infinite Canvas as default - - - Language - - - Permanently delete items as default - - - Show confirmation dialog when deleting items - - - Show Timeline widget on the Homepage - - - Notifications - - - Show a notification when autopaste fails - - - Show a notification when autopaste starts pasting - - - Show error notification if app crashes - - - Pasting - - - Open new canvas on paste - - - Paste files as reference - - - Reference Files allow you to paste files without creating copies of them. With this setting enabled, every file is pasted as a reference. - -A reference file is created pointing to the original file which is seamlessly displayed by Clipboard Canvas. - - - Cannot enable this setting while in Restricted Access mode. - - - Use markdown format instead of text files - - - Show in Collection - - - Status Center - - - Completed 0.00% - - - The operation was canceled - - - Operation canceled - - - The operation is complete - - - Operation complete - - - Overwriting Reference was canceled - - - Overwriting Reference complete - - - Pasting was canceled - - - Pasting complete - - - Completed {0}% - - - Processing... - - - Starting... - - - Switch to Infinite Canvas - - - Switch to One Canvas - - - Timeline - - - An unknown error occurred. - - - View on GitHub - - \ No newline at end of file diff --git a/ClipboardCanvas/Strings/zh-CN/Resources.resw b/ClipboardCanvas/Strings/zh-CN/Resources.resw deleted file mode 100644 index 2f43aa51..00000000 --- a/ClipboardCanvas/Strings/zh-CN/Resources.resw +++ /dev/null @@ -1,529 +0,0 @@ - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 添加合集 - - - 需要重新启动应用程序才能应用更改。 - - - 自动粘贴 - - - 添加规则 - - - 正在粘贴内容 - - - 内容已粘贴 - - - 自动粘贴无法粘贴该内容。 错误:{0} - - - 排除类型 - - - 自动粘贴成功 - - - 自动粘贴已关闭 - - - 大于 - - - - - - 粘贴到: - - - 自动粘贴失败 - - - 文件大小... - - - 规则列表 - - - 类型筛选... - - - 小于 - - - 文件 - - - 文件夹 - - - 图片 - - - 文本 - - - 链接 - - - 自动粘贴正在工作 - - - 取消 - - - 正在使用无限画布模式 - - - 正在使用单画布模式 - - - 修改 - - - 修改图标 - - - 正在从 GitHub 获取数据 - - - 尝试从 GitHub 获取 Clipboard Canvas 的发行说明时出错 - - - Clipboard Canvas 已更新! - - - 在 GitHub 上查看 - - - 报告此问题 - - - 出现了无法恢复的问题。 - - - Clipboard Canvas 出现严重崩溃! - - - 关闭搜索 - - - {0} 错误: {1} - - - 找不到与此合集关联的文件夹。 - - - 正在初始化合集 - - - 检测到部分文件丢失,正在为您重新加载合集。 - - - - 预览合集: - - - 合集 - - - 双击打开此合集。 -右键单击可查看更多选项。 - - - 合集不可用 - - - 继续受限访问 - - - 复制文件 - - - 复制所选文本 - - - 无法删除当前图标。 - - - 无法删除图标。 - - - 无法重命名合集 - - - 无法设置自定义合集图标。 - - - 当前合集: - - - 默认合集 - - - 删除 - - - 删除文件 - - - 删除无限画布 - - - 删除项目 - - - 确定删除此项目? - - - 永久删除 - - - 删除引用 - - - 通过拖放或粘贴添加内容 - - - 在时间轴上显示最近粘贴的项目 - - - 开启自动粘贴 - - - 错误 - - - 重写引用时错误. Error: {0} - - - 文件大小规则不适用于文件夹。 - - - 查找下一个 - - - 查找上一个 - - - 右键单击所需合集并将其设置为自动粘贴目标。 - - - 选择自动粘贴目标 - - - 无限画布为空 - - - 文件无效。 - - - 没有可预览的项目。 - - - 查找的文件。通过预览合集中的搜索功能,可以快速找到您所需要的内容。 - - - 预览你的合集 - - - 使用合集在您的工作区中快速移动。 自定义合集可以满足您的需求。 将工作分组到不同的文件夹中。 - - - 使用合集管理你的工作区 - - - 您现在可以开始使用Clipboard Canvas!了! 您可以通过前往“设置”来自定义您的应用体验。 - - - 现在开始吧! - - - 在无限画布上查看文件。无限画布是您的桌面粘性板,允许您以灵活的方式管理您的工作。拖动粘贴的文件并完全控制它们。 - - - 无限画布 - - - 快速粘贴并与单画布上的内容交互。单画布为您提供各种文件的全尺寸交互式预览: - --图像预览 --媒体预览 --文本预览 --标记格式预览 --文件夹和文件预览 - - - 单画布 - - - 使用“引用文件”,您不必担心硬盘驱动器会被填满。引用文件通过保持指向原始文件的引用来节省空间。得益于Clipboard Canvas的无缝集成,“引用文件”在“单画布”和“无限画布”中都能更好的工作。 - - - 使用引用文件节省存储空间 - - - 千万不要错过主页上带有时间轴的文件或文件夹。时间轴会跟踪最近粘贴的项目,因此您不必担心没有注意而被忽视! - - - 在时间轴上查看最近活动的摘要 - - - 感谢您使用剪贴板画布!为了帮助您快速开始,本演示将引导您了解应用程序的最显著的功能。 - - - 欢迎使用Clipboard Canvas! - - - 打开画布 - - - 打开合集位置 - - - 打开包含文件夹 - - - 打开文件 - - - 打开无限画布文件夹 - - - 打开新画布 - - - 打开新的无限画布 - - - 打开包含文件夹的引用 - - - 打开设置 - - - 操作已取消。 - - - 粘贴引用 - - - 作为引用粘贴文件 - - - 此文件已粘贴为对原始文件的引用。Clipboard Canvas加载引用所指向的原始文件。 -通过按下下面的按钮,可以覆盖引用并将项目直接复制到此集合。 - - - 从剪贴板粘贴 - - - 引用文件 - - - 重新加载合集 - - - 删除合集 - - - 从分区中删除 - - - 删除图标 - - - 重命名 - - - 重置项目位置 - - - 重启应用程序 - - - 受限访问 - - - Clipboard Canvas需要访问文件系统的权限才能正常工作。未经许可,某些功能将被禁用或限制。 - - - 您可以通过指向设置授予此权限,然后应用程序将关闭。 - - - 您也可以在受限访问模式下继续使用受限功能。 - - - Clipboard Canvas 当前处于受限访问模式。单击了解更多详细信息。 - - - 重试 - - - 搜索 - - - 全选 - - - 设置为自动粘贴目标 - - - 设置 - - - 关于 - - - 版本 {0} - - - 打开日志文件位置 - - - 隐私政策 - - - 尝试加载隐私策略时出错 - - - 从GitHub中提取剪贴板画布的隐私策略 - - - 发行说明 - - - Clipboard Canvas在GitHub上的星标数量 - - - 提交反馈 - - - 查看介绍页 - - - 常规 - - - Windows默认值 - - - 使用无限画布作为默认值 - - - 语言 - - - 永久删除默认项目 - - - 删除项目时显示确认对话框 - - - 在主页上显示时间轴小部件 - - - 通知 - - - 自动粘贴失败时显示通知 - - - 自动粘贴开始粘贴时显示通知 - - - 当应用程序崩溃时显示错误通知 - - - 粘贴 - - - 粘贴时打开新画布 - - - 将文件作为引用粘贴 - - - “引用文件”允许您粘贴文件,而无需创建它们的副本。启用此设置后,每个文件都将作为引用粘贴。 -将创建一个引用文件,指向剪贴板画布无缝显示的原始文件。 - - - 在受限访问模式下无法启用此设置。 - - - 使用markdown格式替代文本文件 - - - 在合集中显示 - - - 状态中心 - - - 完成 0.00% - - - 操作已取消 - - - 操作已取消 - - - 操作已完成 - - - 操作完成 - - - 覆盖引用已取消 - - - 覆盖引用完成 - - - 粘贴已取消 - - - 粘贴完成 - - - 完成 {0}% - - - 处理... - - - 启动... - - - 切换到无限画布 - - - 切换到单画布 - - - 时间轴 - - - 发生未知错误。 - - - 去GitHub查看 - - \ No newline at end of file diff --git a/ClipboardCanvas/TemplateSelectors/AutopasteTemplateSelector.cs b/ClipboardCanvas/TemplateSelectors/AutopasteTemplateSelector.cs deleted file mode 100644 index 7dede2d6..00000000 --- a/ClipboardCanvas/TemplateSelectors/AutopasteTemplateSelector.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules; - -namespace ClipboardCanvas.TemplateSelectors -{ - public class AutopasteTemplateSelector : DataTemplateSelector - { - public DataTemplate FileSizeDataTemplate { get; set; } - - public DataTemplate TypeFilterDataTemplate { get; set; } - - protected override DataTemplate SelectTemplateCore(object item) - { - switch (item) - { - case FileSizeRuleViewModel: - { - return FileSizeDataTemplate; - } - - case TypeFilterRuleViewModel: - { - return TypeFilterDataTemplate; - } - - default: - return null; - } - } - } -} diff --git a/ClipboardCanvas/UnsafeNative/UnsafeNativeApis.cs b/ClipboardCanvas/UnsafeNative/UnsafeNativeApis.cs deleted file mode 100644 index fc109aac..00000000 --- a/ClipboardCanvas/UnsafeNative/UnsafeNativeApis.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using static ClipboardCanvas.UnsafeNative.UnsafeNativeDataModels; - -namespace ClipboardCanvas.UnsafeNative -{ - public static unsafe class UnsafeNativeApis - { - [DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, - SetLastError = true)] - public static extern IntPtr CreateFileFromApp( - string lpFileName, - uint dwDesiredAccess, - uint dwShareMode, - IntPtr SecurityAttributes, - uint dwCreationDisposition, - uint dwFlagsAndAttributes, - IntPtr hTemplateFile - ); - - [DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, - SetLastError = true)] - public static extern bool CreateDirectoryFromApp( - string lpPathName, - IntPtr SecurityAttributes - ); - - [DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, - SetLastError = true)] - public unsafe static extern bool ReadFile( - IntPtr hFile, - byte* lpBuffer, - int nBufferLength, - int* lpBytesReturned, - IntPtr lpOverlapped - ); - - [DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall, - SetLastError = true)] - public unsafe static extern bool WriteFile( - IntPtr hFile, - byte* lpBuffer, - int nBufferLength, - int* lpBytesWritten, - IntPtr lpOverlapped - ); - - [DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", SetLastError = true, CharSet = CharSet.Auto)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetFileAttributesExFromApp( - string lpFileName, - GET_FILEEX_INFO_LEVELS fInfoLevelId, - out WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); - - [DllImport("api-ms-win-core-file-l2-1-1.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetFileInformationByHandleEx( - IntPtr hFile, - FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - out BY_HANDLE_FILE_INFORMATION lpFileInformation, - uint dwBufferSize); - - [DllImport("api-ms-win-core-errorhandling-l1-1-1.dll")] - public static extern uint GetLastError(); - - [DllImport("api-ms-win-core-handle-l1-1-0.dll")] - public static extern bool CloseHandle(IntPtr hObject); - } -} diff --git a/ClipboardCanvas/UnsafeNative/UnsafeNativeDataModels.cs b/ClipboardCanvas/UnsafeNative/UnsafeNativeDataModels.cs deleted file mode 100644 index b4c9a84d..00000000 --- a/ClipboardCanvas/UnsafeNative/UnsafeNativeDataModels.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; - -namespace ClipboardCanvas.UnsafeNative -{ - public static class UnsafeNativeDataModels - { - [StructLayout(LayoutKind.Sequential)] - public struct WIN32_FILE_ATTRIBUTE_DATA - { - public System.IO.FileAttributes dwFileAttributes; - public FILETIME ftCreationTime; - public FILETIME ftLastAccessTime; - public FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct BY_HANDLE_FILE_INFORMATION - { - public uint FileAttributes; - public FILETIME CreationTime; - public FILETIME LastAccessTime; - public FILETIME LastWriteTime; - public uint VolumeSerialNumber; - public uint FileSizeHigh; - public uint FileSizeLow; - public uint NumberOfLinks; - public uint FileIndexHigh; - public uint FileIndexLow; - } - - public enum GET_FILEEX_INFO_LEVELS - { - GetFileExInfoStandard, - } - - public enum File_Attributes : uint - { - Readonly = 0x00000001, - Hidden = 0x00000002, - System = 0x00000004, - Directory = 0x00000010, - Archive = 0x00000020, - Device = 0x00000040, - Normal = 0x00000080, - Temporary = 0x00000100, - SparseFile = 0x00000200, - ReparsePoint = 0x00000400, - Compressed = 0x00000800, - Offline = 0x00001000, - NotContentIndexed = 0x00002000, - Encrypted = 0x00004000, - Write_Through = 0x80000000, - Overlapped = 0x40000000, - NoBuffering = 0x20000000, - RandomAccess = 0x10000000, - SequentialScan = 0x08000000, - DeleteOnClose = 0x04000000, - BackupSemantics = 0x02000000, - PosixSemantics = 0x01000000, - OpenReparsePoint = 0x00200000, - OpenNoRecall = 0x00100000, - FirstPipeInstance = 0x00080000 - } - - public enum FILE_INFO_BY_HANDLE_CLASS - { - FileBasicInfo = 0, - FileStandardInfo = 1, - FileNameInfo = 2, - FileRenameInfo = 3, - FileDispositionInfo = 4, - FileAllocationInfo = 5, - FileEndOfFileInfo = 6, - FileStreamInfo = 7, - FileCompressionInfo = 8, - FileAttributeTagInfo = 9, - FileIdBothDirectoryInfo = 10, - FileIdBothDirectoryRestartInfo = 11, - FileIoPriorityHintInfo = 12, - FileRemoteProtocolInfo = 13, - FileFullDirectoryInfo = 14, - FileFullDirectoryRestartInfo = 15, - FileStorageInfo = 16, - FileAlignmentInfo = 17, - FileIdInfo = 18, - FileIdExtdDirectoryInfo = 19, - FileIdExtdDirectoryRestartInfo = 20, - MaximumFileInfoByHandlesClass = 21 - } - - public const uint GENERIC_READ = 0x80000000; - public const uint GENERIC_WRITE = 0x40000000; - - public const uint CREATE_ALWAYS = 2; - public const uint CREATE_NEW = 1; - public const uint OPEN_ALWAYS = 4; - public const uint OPEN_EXISTING = 3; - public const uint TRUNCATE_EXISTING = 5; - - public const uint FILE_SHARE_READ = 0x00000001; - public const uint FILE_SHARE_WRITE = 0x00000002; - - public const int MONITOR_DEFAULTTONULL = 0; - public const int MONITOR_DEFAULTTOPRIMARY = 1; - public const int MONITOR_DEFAULTTONEAREST = 2; - } -} diff --git a/ClipboardCanvas/UnsafeNative/UnsafeNativeHelpers.cs b/ClipboardCanvas/UnsafeNative/UnsafeNativeHelpers.cs deleted file mode 100644 index 0f216410..00000000 --- a/ClipboardCanvas/UnsafeNative/UnsafeNativeHelpers.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using static ClipboardCanvas.UnsafeNative.UnsafeNativeDataModels; - -namespace ClipboardCanvas.UnsafeNative -{ - public static class UnsafeNativeHelpers - { - public static IntPtr CreateFileForWrite(string filePath, bool overwrite = true) - { - return UnsafeNativeApis.CreateFileFromApp(filePath, GENERIC_WRITE, 0, IntPtr.Zero, overwrite ? CREATE_ALWAYS : OPEN_ALWAYS, (uint)File_Attributes.BackupSemantics, IntPtr.Zero); - } - - public static IntPtr CreateFileForRead(string filePath) - { - return UnsafeNativeApis.CreateFileFromApp(filePath, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, (uint)File_Attributes.BackupSemantics, IntPtr.Zero); - } - - public static string ReadStringFromFile(string filePath) - { - IntPtr hFile = UnsafeNativeApis.CreateFileFromApp(filePath, - GENERIC_READ, - FILE_SHARE_READ, - IntPtr.Zero, - OPEN_EXISTING, - (uint)File_Attributes.BackupSemantics, - IntPtr.Zero); - - if (hFile.ToInt64() == -1) - { - return null; - } - - const int BUFFER_LENGTH = 4096; - - byte[] buffer = new byte[BUFFER_LENGTH]; - int dwBytesRead; - string szRead = string.Empty; - - unsafe - { - bool bRead = false; - - using (MemoryStream msBuffer = new MemoryStream(buffer)) - { - using (StreamReader reader = new StreamReader(msBuffer, true)) - { - do - { - fixed (byte* pBuffer = buffer) - { - Array.Clear(buffer, 0, buffer.Length); - msBuffer.Position = 0; - - if (bRead = UnsafeNativeApis.ReadFile(hFile, pBuffer, BUFFER_LENGTH - 1, &dwBytesRead, IntPtr.Zero) && dwBytesRead > 0) - { - string szRead2 = reader.ReadToEnd(); - szRead = szRead2.Substring(0, Math.Min(szRead2.Length, dwBytesRead)); - } - else - { - break; - } - } - - } while (bRead); - } - } - } - - UnsafeNativeApis.CloseHandle(hFile); - - return szRead; - } - - public static bool WriteStringToFile(string filePath, string write) - { - IntPtr hFile = UnsafeNativeApis.CreateFileFromApp(filePath, - GENERIC_WRITE, - 0, - IntPtr.Zero, - CREATE_ALWAYS, - (uint)File_Attributes.BackupSemantics, IntPtr.Zero); - - if (hFile.ToInt64() == -1) - { - return false; - } - - byte[] buffer = Encoding.UTF8.GetBytes(write); - int dwBytesWritten; - unsafe - { - fixed (byte* pBuffer = buffer) - { - UnsafeNativeApis.WriteFile(hFile, pBuffer, buffer.Length, &dwBytesWritten, IntPtr.Zero); - } - } - - UnsafeNativeApis.CloseHandle(hFile); - return true; - } - - public static long GetFileId(string filePath) - { - IntPtr hFile = UnsafeNativeApis.CreateFileFromApp(filePath, - GENERIC_READ, - (uint)FileShare.ReadWrite, - IntPtr.Zero, - OPEN_EXISTING, - (uint)File_Attributes.BackupSemantics, IntPtr.Zero); - - if (hFile.ToInt64() == -1) - { - return -1; - } - - BY_HANDLE_FILE_INFORMATION lpFileInformation = new BY_HANDLE_FILE_INFORMATION(); - uint dwFileInformationLength = (uint)Marshal.SizeOf(lpFileInformation); - - bool result = UnsafeNativeApis.GetFileInformationByHandleEx(hFile, FILE_INFO_BY_HANDLE_CLASS.FileIdBothDirectoryInfo, out lpFileInformation, dwFileInformationLength); - - long lFileId = -1; - if (result) - { - lFileId = ((long)lpFileInformation.FileIndexHigh << 32) + (long)lpFileInformation.FileIndexLow; - } - - UnsafeNativeApis.CloseHandle(hFile); - - return lFileId; - } - } -} diff --git a/ClipboardCanvas/UserControls/AutopasteControl.xaml b/ClipboardCanvas/UserControls/AutopasteControl.xaml deleted file mode 100644 index 07fb278a..00000000 --- a/ClipboardCanvas/UserControls/AutopasteControl.xaml +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/AutopasteControl.xaml.cs b/ClipboardCanvas/UserControls/AutopasteControl.xaml.cs deleted file mode 100644 index b26977c8..00000000 --- a/ClipboardCanvas/UserControls/AutopasteControl.xaml.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.UserControls.Autopaste; -using Microsoft.UI.Xaml; -using ClipboardCanvas.Services; -using CommunityToolkit.Mvvm.DependencyInjection; -using Microsoft.UI.Xaml.Controls.Primitives; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class AutopasteControl : UserControl - { - private IAutopasteService AutopasteService { get; } = Ioc.Default.GetService(); - - public AutopasteControlViewModel ViewModel - { - get => (AutopasteControlViewModel)GetValue(ViewModelProperty); - set - { - SetValue(ViewModelProperty, value); - if (this.AutopasteService is Services.Implementation.AutopasteService autopasteService) - { - autopasteService.AutopasteControlViewModel = value; - } - } - } - - public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register( - "ViewModel", - typeof(AutopasteControlViewModel), - typeof(AutopasteControl), - null - ); - - public AutopasteControl() - { - this.InitializeComponent(); - } - - private void HyperlinkButton_Click(object sender, RoutedEventArgs e) - { - FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender); - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/CanvasPreviewControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/CanvasPreviewControl.xaml deleted file mode 100644 index 7b936ce8..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/CanvasPreviewControl.xaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/CanvasPreviewControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/CanvasPreviewControl.xaml.cs deleted file mode 100644 index 647a5fc4..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/CanvasPreviewControl.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasPreview; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class CanvasPreviewControl : UserControl, IBaseCanvasPreviewControlView - { - public CanvasPreviewControlViewModel ViewModel - { - get => (CanvasPreviewControlViewModel)DataContext; - set => DataContext = value; - } - - public ICollectionModel CollectionModel { get; set; } - - public CanvasPreviewControl() - { - this.InitializeComponent(); - - this.ViewModel = new CanvasPreviewControlViewModel(this); - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/FallbackCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/FallbackCanvasControl.xaml deleted file mode 100644 index 0944e601..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/FallbackCanvasControl.xaml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/FallbackCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/FallbackCanvasControl.xaml.cs deleted file mode 100644 index c9554d4b..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/FallbackCanvasControl.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using System.Collections.Generic; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class FallbackCanvasControl : UserControl - { - public FallbackCanvasViewModel ViewModel - { - get => (FallbackCanvasViewModel)DataContext; - } - - public FallbackCanvasControl() - { - this.InitializeComponent(); - } - - private async void Image_DragStarting(Microsoft.UI.Xaml.UIElement sender, Microsoft.UI.Xaml.DragStartingEventArgs args) - { - IReadOnlyList dragData = await ViewModel.ProvideDragData(); - - args.Data.SetData(StandardDataFormats.StorageItems, dragData); - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/ImageCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/ImageCanvasControl.xaml deleted file mode 100644 index ca70034b..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/ImageCanvasControl.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/ImageCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/ImageCanvasControl.xaml.cs deleted file mode 100644 index 5bc124bb..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/ImageCanvasControl.xaml.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class ImageCanvasControl : UserControl - { - public ImageCanvasViewModel ViewModel - { - get => (ImageCanvasViewModel)DataContext; - } - - public ImageCanvasControl() - { - this.InitializeComponent(); - } - - private async void Image_DragStarting(Microsoft.UI.Xaml.UIElement sender, Microsoft.UI.Xaml.DragStartingEventArgs args) - { - await ViewModel.SetDragData(args.Data); - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/InfiniteCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/InfiniteCanvasControl.xaml deleted file mode 100644 index 5e958549..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/InfiniteCanvasControl.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/InfiniteCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/InfiniteCanvasControl.xaml.cs deleted file mode 100644 index c52252af..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/InfiniteCanvasControl.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Models; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class InfiniteCanvasControl : UserControl, IInfiniteCanvasControlView - { - public InfiniteCanvasViewModel ViewModel - { - get => (InfiniteCanvasViewModel)DataContext; - } - - public IInteractableCanvasControlModel InteractableCanvasModel => InteractableCanvas.ViewModel; - - public InfiniteCanvasControl() - { - this.InitializeComponent(); - } - - private void UserControl_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - this.ViewModel.ControlView = this; - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/MarkdownCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/MarkdownCanvasControl.xaml deleted file mode 100644 index b4e4825c..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/MarkdownCanvasControl.xaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/MarkdownCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/MarkdownCanvasControl.xaml.cs deleted file mode 100644 index a32d6caa..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/MarkdownCanvasControl.xaml.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.ModelViews; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class MarkdownCanvasControl : UserControl - { - public MarkdownCanvasViewModel ViewModel - { - get => (MarkdownCanvasViewModel)DataContext; - } - - public MarkdownCanvasControl() - { - this.InitializeComponent(); - - ContentText.ContextFlyout = null; - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/MediaCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/MediaCanvasControl.xaml deleted file mode 100644 index 86074c5d..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/MediaCanvasControl.xaml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/MediaCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/MediaCanvasControl.xaml.cs deleted file mode 100644 index 92b00d66..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/MediaCanvasControl.xaml.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using Windows.Storage; -using System.IO; -using Microsoft.Web.WebView2.Core; -using System.Web; -using System.Threading.Tasks; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class MediaCanvasControl : UserControl, IMediaCanvasControlView - { - private StorageFile _htmlTempFile; - - public MediaCanvasViewModel ViewModel - { - get => (MediaCanvasViewModel)DataContext; - } - - public TimeSpan Position - { - get => TimeSpan.FromMilliseconds(0);// MediaPlayerContent.MediaPlayer.PlaybackSession.Position; - set { }// MediaPlayerContent.MediaPlayer.PlaybackSession.Position = value; - } - - public bool IsLoopingEnabled - { - get => false;// MediaPlayerContent.MediaPlayer.IsLoopingEnabled; - set { }// MediaPlayerContent.MediaPlayer.IsLoopingEnabled = value; - } - - public double Volume - { - get => 0.0d;//MediaPlayerContent.MediaPlayer.Volume; - set { }// MediaPlayerContent.MediaPlayer.Volume = value; - } - - public MediaCanvasControl() - { - this.InitializeComponent(); - } - - private void UserControl_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - this.ViewModel.ControlView = this; - this.ViewModel.UpdateMediaControl(); - } - - private async void ContentWebView_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - await ContentWebView.EnsureCoreWebView2Async(); // Init - - await this.ViewModel.NotifyWebViewLoaded(); - } - - public async Task LoadFromMedia(IStorageFile file) - { - ContentWebView.Source = await CreateUriToHtmlFileForDisplaying(file); - } - - public async Task LoadFromAudio(IStorageFile file) - { - ContentWebView.Source = await CreateUriToHtmlFileForDisplaying(file); - } - - private async Task CreateUriToHtmlFileForDisplaying(IStorageFile file) - { - StorageFolder htmlTempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(Constants.LocalSettings.HTML_TEMPDATA_FOLDERNAME, CreationCollisionOption.OpenIfExists); - - _htmlTempFile = await htmlTempFolder.CreateFileAsync("mediahtml.html", CreationCollisionOption.ReplaceExisting); - - Uri uri = new Uri(file.Path); - string encodedPath = uri.AbsoluteUri; - string html = $"
"; - - await FileIO.WriteTextAsync(_htmlTempFile, html); - - return new Uri(_htmlTempFile.Path); - } - - public void Dispose() - { - this.ContentWebView.Close(); - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/TextCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/TextCanvasControl.xaml deleted file mode 100644 index 9f37a94f..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/TextCanvasControl.xaml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/TextCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/TextCanvasControl.xaml.cs deleted file mode 100644 index c395dfb3..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/TextCanvasControl.xaml.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class TextCanvasControl : UserControl, ITextCanvasControlView - { - public TextCanvasViewModel ViewModel - { - get => (TextCanvasViewModel)DataContext; - } - - public TextCanvasControl() - { - this.InitializeComponent(); - - // Set the ContentText's context to null to override it in the ViewModel - ContentText.ContextFlyout = null; - ContentText.SelectionFlyout = null; - } - - public bool IsTextSelected - { - get => ContentText.SelectedText.Length > 0; - } - - public int SelectedTextLength - { - get => ContentText.SelectedText.Length; - } - - private void UserControl_Loaded(object sender, RoutedEventArgs e) - { - this.ViewModel.ControlView = this; - } - - private void ContentText_ContextMenuOpening(object sender, ContextMenuEventArgs e) - { - e.Handled = true; - } - - public void TextSelectAll() - { - ContentText.SelectAll(); - ContentText.Focus(FocusState.Programmatic); - } - - public void CopySelectedText() - { - ContentText.CopySelectionToClipboard(); - } - } -} diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/WebViewCanvasControl.xaml b/ClipboardCanvas/UserControls/CanvasDisplay/WebViewCanvasControl.xaml deleted file mode 100644 index d186f6f5..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/WebViewCanvasControl.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - diff --git a/ClipboardCanvas/UserControls/CanvasDisplay/WebViewCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/CanvasDisplay/WebViewCanvasControl.xaml.cs deleted file mode 100644 index c4dbc2e0..00000000 --- a/ClipboardCanvas/UserControls/CanvasDisplay/WebViewCanvasControl.xaml.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.ModelViews; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.CanvasDisplay -{ - public sealed partial class WebViewCanvasControl : UserControl, IWebViewCanvasControlView - { - public WebViewCanvasViewModel ViewModel - { - get => (WebViewCanvasViewModel)DataContext; - } - - public WebViewCanvasControl() - { - this.InitializeComponent(); - } - - private async void ContentWebView_Loaded(object sender, RoutedEventArgs e) - { - this.ViewModel.ControlView = this; - - await ContentWebView.EnsureCoreWebView2Async(); // Init - - this.ViewModel.NotifyWebViewLoaded(); - } - - public void NavigateToHtml(string html) - { - this.ContentWebView.NavigateToString(html); - } - - public void NavigateToSource(string source) - { - this.ContentWebView.Source = new Uri(source); - } - - #region IDisposable - - public void Dispose() - { - ContentWebView.Close(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/UserControls/DisplayControl.xaml b/ClipboardCanvas/UserControls/DisplayControl.xaml deleted file mode 100644 index 1cd5ccfa..00000000 --- a/ClipboardCanvas/UserControls/DisplayControl.xaml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/ClipboardCanvas/UserControls/DisplayControl.xaml.cs b/ClipboardCanvas/UserControls/DisplayControl.xaml.cs deleted file mode 100644 index 3df620af..00000000 --- a/ClipboardCanvas/UserControls/DisplayControl.xaml.cs +++ /dev/null @@ -1,88 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using CommunityToolkit.Mvvm.DependencyInjection; -using System.Diagnostics; - -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.Pages; -using ClipboardCanvas.ViewModels.UserControls; -using ClipboardCanvas.Services; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class DisplayControl : UserControl, IDisplayControlView - { - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - public DisplayControlViewModel ViewModel - { - get => (DisplayControlViewModel)DataContext; - set => DataContext = value; - } - - public bool IntroductionPanelLoad - { - get => MainWindow.Instance.MainWindowContentPage.IntroductionPanelLoad; - set => MainWindow.Instance.MainWindowContentPage.IntroductionPanelLoad = value; - } - - public IWindowTitleBarControlModel WindowTitleBarControlModel { get; set; } - - public INavigationToolBarControlModel NavigationToolBarControlModel { get; set; } - - public IIntroductionScreenPanelModel IntroductionScreenPanelModel { get; set; } - - public IPasteCanvasPageModel PasteCanvasPageModel - { - get - { - if ((DisplayFrame.Content as Page)?.DataContext is CanvasPageViewModel viewModel) - { - return viewModel; - } - - return null; - } - } - - public ICollectionPreviewPageModel CollectionPreviewPageModel - { - get - { - if ((DisplayFrame.Content as Page)?.DataContext is CollectionPreviewPageViewModel viewModel) - { - return viewModel; - } - - return null; - } - } - - public DisplayControl() - { - this.InitializeComponent(); - - this.ViewModel = new DisplayControlViewModel(this); - } - - private async void UserControl_Loaded(object sender, RoutedEventArgs e) - { - // Configure navigation - if (this.NavigationService is Services.Implementation.NavigationService navigationServiceImpl) - { - navigationServiceImpl.DisplayFrame = this.DisplayFrame; - navigationServiceImpl.CheckCollectionAvailabilityBeforePageNavigation = this.ViewModel.CheckCollectionAvailabilityBeforePageNavigation; - } - else - { - Debugger.Break(); // Shouldn't even happen - } - - // Initialize the rest when the view is loaded - await this.ViewModel.InitializeAfterLoad(); - } - } -} diff --git a/ClipboardCanvas/UserControls/InAppNotificationControl.xaml b/ClipboardCanvas/UserControls/InAppNotificationControl.xaml deleted file mode 100644 index 4e836477..00000000 --- a/ClipboardCanvas/UserControls/InAppNotificationControl.xaml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - diff --git a/ClipboardCanvas/UserControls/InAppNotificationControl.xaml.cs b/ClipboardCanvas/UserControls/InAppNotificationControl.xaml.cs deleted file mode 100644 index d3fbaca3..00000000 --- a/ClipboardCanvas/UserControls/InAppNotificationControl.xaml.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Enums; -using System.Threading.Tasks; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class InAppNotificationControl : UserControl, IInAppNotification - { - public InAppNotificationControlViewModel ViewModel - { - get => (InAppNotificationControlViewModel)DataContext; - set => DataContext = value; - } - - public event EventHandler OnInAppNotificationDismissedEvent; - - public InAppNotificationControl() - { - this.InitializeComponent(); - - this.ViewModel = new InAppNotificationControlViewModel(InAppNotificationButtonType.OkButton); - this.ViewModel.OnInAppNotificationDismissedEvent += ViewModel_OnInAppNotificationDismissedEvent; - } - - public void Show(int milliseconds = 0) - { - ViewModel.Show(milliseconds); - } - - public void Dismiss() - { - ViewModel.Dismiss(); - } - - private void ViewModel_OnInAppNotificationDismissedEvent(object sender, InAppNotificationDismissedEventArgs e) - { - this.ViewModel.OnInAppNotificationDismissedEvent -= ViewModel_OnInAppNotificationDismissedEvent; - OnInAppNotificationDismissedEvent?.Invoke(sender, e); - } - } -} diff --git a/ClipboardCanvas/UserControls/InteractableCanvasControl.xaml b/ClipboardCanvas/UserControls/InteractableCanvasControl.xaml deleted file mode 100644 index e7b6837d..00000000 --- a/ClipboardCanvas/UserControls/InteractableCanvasControl.xaml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ClipboardCanvas/UserControls/InteractableCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/InteractableCanvasControl.xaml.cs deleted file mode 100644 index b31d9a7b..00000000 --- a/ClipboardCanvas/UserControls/InteractableCanvasControl.xaml.cs +++ /dev/null @@ -1,251 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; -using Windows.ApplicationModel.DataTransfer; -using Microsoft.UI.Xaml; -using Windows.Foundation; -using System.Collections.Generic; -using Windows.Storage; -using System.Threading.Tasks; -using Windows.Storage.Streams; -using Microsoft.UI.Xaml.Media.Imaging; -using System.Numerics; - -using ClipboardCanvas.ViewModels.UserControls; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Models; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.DataModels; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class InteractableCanvasControl : UserControl, IInteractableCanvasControlView - { - private Canvas _canvasPanel; - - private Point _savedClickPosition; - - public InteractableCanvasControlViewModel ViewModel - { - get => (InteractableCanvasControlViewModel)DataContext; - set => DataContext = value; - } - - public InteractableCanvasControl() - { - this.InitializeComponent(); - - this.ViewModel = new InteractableCanvasControlViewModel(this); - } - - private async void Canvas_Loaded(object sender, RoutedEventArgs e) - { - _canvasPanel = sender as Canvas; - await this.ViewModel.CanvasLoaded(); - } - - private void Canvas_Drop(object sender, DragEventArgs e) - { - Point dropPoint = e.GetPosition(_canvasPanel); - - FrameworkElement element = e.DataView.Properties[Constants.UI.CanvasContent.INFINITE_CANVAS_DRAGGED_OBJECT_ID] as FrameworkElement; - if (element?.DataContext == null && e.DataView != null) - { - // Save position and dataPackage - this.ViewModel.DataPackageComparisionDataModel = new InteractableCanvasDataPackageComparisionDataModel(e.DataView, dropPoint); - } - else - { - int indexOfItem = this.ViewModel.Items.IndexOf(element.DataContext as InteractableCanvasControlItemViewModel); - FrameworkElement container = ItemsHolder.ContainerFromIndex(indexOfItem) as FrameworkElement; - - double dropX = dropPoint.X - _savedClickPosition.X; - double dropY = dropPoint.Y - _savedClickPosition.Y; - - double leftMostBound = dropX + container.ActualWidth; - double topMostBound = dropY + container.ActualHeight; - - // Align - if (leftMostBound > _canvasPanel.ActualWidth) - { - dropX = _canvasPanel.ActualWidth - container.ActualWidth; - } - else if (dropX < 0.0d) - { - dropX = 0.0d; - } - - if (topMostBound > _canvasPanel.ActualHeight) - { - dropY = _canvasPanel.ActualHeight - container.ActualHeight; - } - else if (dropY < 0.0d) - { - dropY = 0.0d; - } - - Canvas.SetLeft(container, dropX); - Canvas.SetTop(container, dropY); - - element.Opacity = 1.0d; - - // Update the ZIndex of the element - set it on top - SetOnTop(container); // TODO: Fix this - sometimes other item can shown higher - - this.ViewModel.ItemRearranged(); - } - } - - private void SetOnTop(UIElement element) - { - if (element == null) - { - return; - } - - int elementZIndex = Canvas.GetZIndex(element); - int highestZIndex = Math.Max(elementZIndex, 1); - - foreach (object item in ItemsHolder.Items) - { - UIElement uiItemContainer = ItemsHolder.ContainerFromItem(item) as UIElement; - - int itemZIndex = Canvas.GetZIndex(uiItemContainer); - highestZIndex = Math.Max(itemZIndex, highestZIndex); - - if (itemZIndex > elementZIndex) - { - Canvas.SetZIndex(uiItemContainer, itemZIndex - 1); - } - } - - // Set the highest ZIndex - Canvas.SetZIndex(element, highestZIndex); - } - - private void Canvas_DragOver(object sender, DragEventArgs e) - { - e.AcceptedOperation = DataPackageOperation.Move; - e.DragUIOverride.IsCaptionVisible = false; - e.DragUIOverride.IsGlyphVisible = false; - - // Hide element when dragging over the canvas - if (e.DataView.Properties[Constants.UI.CanvasContent.INFINITE_CANVAS_DRAGGED_OBJECT_ID] is FrameworkElement element - && this.ViewModel.Items.Contains(element.DataContext as InteractableCanvasControlItemViewModel)) - { - element.Opacity = 0.0d; - } - } - - private async void RootContentGrid_DragStarting(UIElement sender, DragStartingEventArgs args) - { - if (sender is FrameworkElement draggedElement) - { - Point point = args.GetPosition(draggedElement); - _savedClickPosition = point; - - // Add the dragged element to properties which we can later retrieve it from - args.Data.Properties.Add(Constants.UI.CanvasContent.INFINITE_CANVAS_DRAGGED_OBJECT_ID, draggedElement); - - // Also set data associated from the dragged element - if (draggedElement.DataContext is IDragDataProviderModel dragDataProvider) - { - await dragDataProvider.SetDragData(args.Data); - } - } - } - - private void Canvas_DragLeave(object sender, DragEventArgs e) - { - e.AcceptedOperation = DataPackageOperation.Copy; - e.DragUIOverride.IsCaptionVisible = true; - e.DragUIOverride.IsGlyphVisible = true; - - if (e.DataView.Properties[Constants.UI.CanvasContent.INFINITE_CANVAS_DRAGGED_OBJECT_ID] is FrameworkElement draggedElement) - { - draggedElement.Opacity = 1.0d; - } - } - - private async void RootContentGrid_DoubleTapped(object sender, Microsoft.UI.Xaml.Input.DoubleTappedRoutedEventArgs e) - { - if ((sender as FrameworkElement)?.DataContext is InteractableCanvasControlItemViewModel itemViewModel) - { - await itemViewModel.OpenFile(); - } - } - - public Vector2 GetItemPosition(InteractableCanvasControlItemViewModel itemViewModel) - { - int indexOfItem = this.ViewModel.Items.IndexOf(itemViewModel); - - if (ItemsHolder.ContainerFromIndex(indexOfItem) is UIElement container) - { - float x = (float)Canvas.GetLeft(container); - float y = (float)Canvas.GetTop(container); - - return new Vector2(x, y); - } - - return new Vector2(0, 0); - } - - public void SetItemPosition(InteractableCanvasControlItemViewModel itemViewModel, Vector2 position) - { - int indexOfItem = this.ViewModel.Items.IndexOf(itemViewModel); - - if (ItemsHolder.ContainerFromIndex(indexOfItem) is UIElement container) - { - Canvas.SetLeft(container, (double)position.X); - Canvas.SetTop(container, (double)position.Y); - } - } - - public async Task<(IBuffer buffer, uint pixelWidth, uint pixelHeight)> GetCanvasImageBuffer() - { - try - { - if (RootGrid == null) - { - return (null, 0, 0); - } - - RenderTargetBitmap rtb = new RenderTargetBitmap(); - await rtb.RenderAsync(RootGrid); - - IBuffer pixelBuffer = await rtb.GetPixelsAsync(); - - return (pixelBuffer, (uint)rtb.PixelWidth, (uint)rtb.PixelHeight); - } - catch - { - return (null, 0, 0); - } - } - - public void SetOnTop(InteractableCanvasControlItemViewModel itemViewModel) - { - SetOnTop(ItemsHolder.ContainerFromItem(itemViewModel) as UIElement); - } - - public int GetCanvasTopIndex(InteractableCanvasControlItemViewModel itemViewModel) - { - if (ItemsHolder.ContainerFromItem(itemViewModel) is UIElement container) - { - return Canvas.GetZIndex(container); - } - - return 0; - } - - public void SetCanvasTopIndex(InteractableCanvasControlItemViewModel itemViewModel, int topIndex) - { - if (ItemsHolder.ContainerFromItem(itemViewModel) is UIElement container) - { - Canvas.SetZIndex(container, topIndex); - } - } - } -} diff --git a/ClipboardCanvas/UserControls/NavigationControl.xaml b/ClipboardCanvas/UserControls/NavigationControl.xaml deleted file mode 100644 index eab05e27..00000000 --- a/ClipboardCanvas/UserControls/NavigationControl.xaml +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/NavigationControl.xaml.cs b/ClipboardCanvas/UserControls/NavigationControl.xaml.cs deleted file mode 100644 index f4a05886..00000000 --- a/ClipboardCanvas/UserControls/NavigationControl.xaml.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -using ClipboardCanvas.ViewModels.UserControls; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class NavigationControl : UserControl - { - public NavigationControlViewModel ViewModel - { - get => (NavigationControlViewModel)GetValue(ViewModelProperty); - set => SetValue(ViewModelProperty, value); - } - - public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register( - "ViewModel", - typeof(NavigationControlViewModel), - typeof(NavigationControl), - null - ); - - public NavigationControl() - { - this.InitializeComponent(); - } - - private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) - { - this.ViewModel?.DefaultKeyboardAcceleratorInvokedCommand?.Execute(args); - } - } -} diff --git a/ClipboardCanvas/UserControls/NavigationToolBarControl.xaml b/ClipboardCanvas/UserControls/NavigationToolBarControl.xaml deleted file mode 100644 index c6e12699..00000000 --- a/ClipboardCanvas/UserControls/NavigationToolBarControl.xaml +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/NavigationToolBarControl.xaml.cs b/ClipboardCanvas/UserControls/NavigationToolBarControl.xaml.cs deleted file mode 100644 index 518eb04b..00000000 --- a/ClipboardCanvas/UserControls/NavigationToolBarControl.xaml.cs +++ /dev/null @@ -1,33 +0,0 @@ -using CommunityToolkit.Mvvm.DependencyInjection; -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.UserControls; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class NavigationToolBarControl : UserControl - { - private IStatusCenterService StatusCenterService { get; } = Ioc.Default.GetService(); - - public NavigationToolBarControlViewModel ViewModel - { - get => (NavigationToolBarControlViewModel)DataContext; - set => DataContext = value; - } - - public NavigationToolBarControl() - { - this.InitializeComponent(); - - this.ViewModel = new NavigationToolBarControlViewModel(); - - if (this.StatusCenterService is Services.Implementation.StatusCenterService statusCenterServiceImpl) - { - statusCenterServiceImpl.NavigationToolBarControlModel = this.ViewModel; - } - } - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollectionPreview.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollectionPreview.xaml deleted file mode 100644 index a8d4bfaa..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollectionPreview.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollectionPreview.xaml.cs b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollectionPreview.xaml.cs deleted file mode 100644 index ad781d4d..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollectionPreview.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.OOBE -{ - public sealed partial class IntroductionScreenCollectionPreview : UserControl - { - public IntroductionScreenCollectionPreview() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollections.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollections.xaml deleted file mode 100644 index f7a6033c..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollections.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollections.xaml.cs b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollections.xaml.cs deleted file mode 100644 index 30294134..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenCollections.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.OOBE -{ - public sealed partial class IntroductionScreenCollections : UserControl - { - public IntroductionScreenCollections() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenFinish.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenFinish.xaml deleted file mode 100644 index 077c7a04..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenFinish.xaml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenFinish.xaml.cs b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenFinish.xaml.cs deleted file mode 100644 index 9bfab3c5..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenFinish.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.OOBE -{ - public sealed partial class IntroductionScreenFinish : UserControl - { - public IntroductionScreenFinish() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenGenericPreview.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenGenericPreview.xaml deleted file mode 100644 index 7534ae4d..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenGenericPreview.xaml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenGenericPreview.xaml.cs b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenGenericPreview.xaml.cs deleted file mode 100644 index 3c4c87d1..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenGenericPreview.xaml.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.OOBE -{ - public sealed partial class IntroductionScreenGenericPreview : UserControl - { - public IntroductionScreenGenericPreview() - { - this.InitializeComponent(); - } - - - public ImageSource PreviewImage - { - get { return (ImageSource)GetValue(PreviewImageProperty); } - set { SetValue(PreviewImageProperty, value); } - } - public static readonly DependencyProperty PreviewImageProperty = - DependencyProperty.Register("PreviewImage", typeof(ImageSource), typeof(IntroductionScreenGenericPreview), new PropertyMetadata(null)); - - - public string Title - { - get { return (string)GetValue(TitleProperty); } - set { SetValue(TitleProperty, value); } - } - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register("Title", typeof(string), typeof(IntroductionScreenGenericPreview), new PropertyMetadata(null)); - - - public string Description - { - get { return (string)GetValue(DescriptionProperty); } - set { SetValue(DescriptionProperty, value); } - } - public static readonly DependencyProperty DescriptionProperty = - DependencyProperty.Register("Description", typeof(string), typeof(IntroductionScreenGenericPreview), new PropertyMetadata(null)); - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenInfiniteCanvas.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenInfiniteCanvas.xaml deleted file mode 100644 index af9e8f0d..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenInfiniteCanvas.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenInfiniteCanvas.xaml.cs b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenInfiniteCanvas.xaml.cs deleted file mode 100644 index 49420994..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenInfiniteCanvas.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.OOBE -{ - public sealed partial class IntroductionScreenInfiniteCanvas : UserControl - { - public IntroductionScreenInfiniteCanvas() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenOneCanvas.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenOneCanvas.xaml deleted file mode 100644 index 8f338374..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenOneCanvas.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenOneCanvas.xaml.cs b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenOneCanvas.xaml.cs deleted file mode 100644 index 8b4ee5d8..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenOneCanvas.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.OOBE -{ - public sealed partial class IntroductionScreenOneCanvas : UserControl - { - public IntroductionScreenOneCanvas() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenPanel.xaml b/ClipboardCanvas/UserControls/OOBE/IntroductionScreenPanel.xaml deleted file mode 100644 index e4d360d9..00000000 --- a/ClipboardCanvas/UserControls/OOBE/IntroductionScreenPanel.xaml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/SearchControl.xaml.cs b/ClipboardCanvas/UserControls/SearchControl.xaml.cs deleted file mode 100644 index d2ee92ae..00000000 --- a/ClipboardCanvas/UserControls/SearchControl.xaml.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Input; - -using ClipboardCanvas.ViewModels; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class SearchControl : UserControl - { - public SearchControlViewModel ViewModel - { - get => (SearchControlViewModel)DataContext; - set => DataContext = value; - } - - public SearchControl() - { - this.InitializeComponent(); - - this.ViewModel = new SearchControlViewModel(); - } - - private void TextBox_Loaded(object sender, RoutedEventArgs e) - { - InputBox.Focus(FocusState.Programmatic); - } - - private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) - { - this.ViewModel?.DefaultKeyboardAcceleratorInvokedCommand?.Execute(args); - } - } -} diff --git a/ClipboardCanvas/UserControls/Settings/SettingBlockControl.xaml b/ClipboardCanvas/UserControls/Settings/SettingBlockControl.xaml deleted file mode 100644 index b36f74e8..00000000 --- a/ClipboardCanvas/UserControls/Settings/SettingBlockControl.xaml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/Settings/SettingBlockControl.xaml.cs b/ClipboardCanvas/UserControls/Settings/SettingBlockControl.xaml.cs deleted file mode 100644 index c20e8cce..00000000 --- a/ClipboardCanvas/UserControls/Settings/SettingBlockControl.xaml.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Windows.Input; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Markup; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.Settings -{ - [ContentProperty(Name = nameof(ActionElement))] - public sealed partial class SettingBlockControl : UserControl - { - public SettingBlockControl() - { - this.InitializeComponent(); - } - - - public ICommand ButtonCommand - { - get { return (ICommand)GetValue(ButtonCommandProperty); } - set { SetValue(ButtonCommandProperty, value); } - } - public static readonly DependencyProperty ButtonCommandProperty = - DependencyProperty.Register("ButtonCommand", typeof(ICommand), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public ICommand ExpanderExpandingCommand - { - get { return (ICommand)GetValue(ExpanderExpandingCommandProperty); } - set { SetValue(ExpanderExpandingCommandProperty, value); } - } - public static readonly DependencyProperty ExpanderExpandingCommandProperty = - DependencyProperty.Register("ExpanderExpandingCommand", typeof(ICommand), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public FrameworkElement ExpanderContent - { - get { return (FrameworkElement)GetValue(ExpanderContentProperty); } - set { SetValue(ExpanderContentProperty, value); } - } - public static readonly DependencyProperty ExpanderContentProperty = - DependencyProperty.Register("ExpanderContent", typeof(FrameworkElement), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public bool IsClickable - { - get => (bool)GetValue(IsClickableProperty); - set => SetValue(IsClickableProperty, value); - } - public static readonly DependencyProperty IsClickableProperty = - DependencyProperty.Register("IsClickable", typeof(bool), typeof(SettingBlockControl), new PropertyMetadata(false)); - - - public IconElement Icon - { - get { return (IconElement)GetValue(IconProperty); } - set { SetValue(IconProperty, value); } - } - public static readonly DependencyProperty IconProperty = - DependencyProperty.Register("Icon", typeof(IconElement), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public string Description - { - get { return (string)GetValue(DescriptionProperty); } - set { SetValue(DescriptionProperty, value); } - } - public static readonly DependencyProperty DescriptionProperty = - DependencyProperty.Register("Description", typeof(string), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public FrameworkElement AdditionalDescription - { - get { return (FrameworkElement)GetValue(AdditionalDescriptionProperty); } - set { SetValue(AdditionalDescriptionProperty, value); } - } - public static readonly DependencyProperty AdditionalDescriptionProperty = - DependencyProperty.Register("AdditionalDescription", typeof(FrameworkElement), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public FrameworkElement ActionElement - { - get { return (FrameworkElement)GetValue(ActionElementProperty); } - set { SetValue(ActionElementProperty, value); } - } - public static readonly DependencyProperty ActionElementProperty = - DependencyProperty.Register("ActionElement", typeof(FrameworkElement), typeof(SettingBlockControl), new PropertyMetadata(null)); - - - public FrameworkElement AdditionalActionElement - { - get { return (FrameworkElement)GetValue(AdditionalActionElementProperty); } - set { SetValue(AdditionalActionElementProperty, value); } - } - public static readonly DependencyProperty AdditionalActionElementProperty = - DependencyProperty.Register("AdditionalActionElement", typeof(FrameworkElement), typeof(SettingBlockControl), new PropertyMetadata(null)); - - private void Expander_Expanding(Microsoft.UI.Xaml.Controls.Expander sender, Microsoft.UI.Xaml.Controls.ExpanderExpandingEventArgs args) - { - ExpanderExpandingCommand?.Execute(null); - } - } -} diff --git a/ClipboardCanvas/UserControls/Settings/SettingBlockHeaderContentControl.xaml b/ClipboardCanvas/UserControls/Settings/SettingBlockHeaderContentControl.xaml deleted file mode 100644 index faa52a50..00000000 --- a/ClipboardCanvas/UserControls/Settings/SettingBlockHeaderContentControl.xaml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/Settings/SettingBlockHeaderContentControl.xaml.cs b/ClipboardCanvas/UserControls/Settings/SettingBlockHeaderContentControl.xaml.cs deleted file mode 100644 index 840ecc22..00000000 --- a/ClipboardCanvas/UserControls/Settings/SettingBlockHeaderContentControl.xaml.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.Settings -{ - public sealed partial class SettingBlockHeaderContentControl : UserControl - { - public SettingBlockHeaderContentControl() - { - this.InitializeComponent(); - } - - public IconElement Icon - { - get { return (IconElement)GetValue(IconProperty); } - set { SetValue(IconProperty, value); } - } - public static readonly DependencyProperty IconProperty = - DependencyProperty.Register("Icon", typeof(IconElement), typeof(SettingBlockHeaderContentControl), new PropertyMetadata(null)); - - - public string Description - { - get { return (string)GetValue(DescriptionProperty); } - set { SetValue(DescriptionProperty, value); } - } - public static readonly DependencyProperty DescriptionProperty = - DependencyProperty.Register("Description", typeof(string), typeof(SettingBlockHeaderContentControl), new PropertyMetadata(null)); - - - public FrameworkElement AdditionalDescription - { - get { return (FrameworkElement)GetValue(AdditionalDescriptionProperty); } - set { SetValue(AdditionalDescriptionProperty, value); } - } - public static readonly DependencyProperty AdditionalDescriptionProperty = - DependencyProperty.Register("AdditionalDescription", typeof(FrameworkElement), typeof(SettingBlockHeaderContentControl), new PropertyMetadata(null)); - - - public FrameworkElement ActionElement - { - get { return (FrameworkElement)GetValue(ActionElementProperty); } - set { SetValue(ActionElementProperty, value); } - } - public static readonly DependencyProperty ActionElementProperty = - DependencyProperty.Register("ActionElement", typeof(FrameworkElement), typeof(SettingBlockHeaderContentControl), new PropertyMetadata(null)); - - - public FrameworkElement AdditionalActionElement - { - get { return (FrameworkElement)GetValue(AdditionalActionElementProperty); } - set { SetValue(AdditionalActionElementProperty, value); } - } - public static readonly DependencyProperty AdditionalActionElementProperty = - DependencyProperty.Register("AdditionalActionElement", typeof(FrameworkElement), typeof(SettingBlockHeaderContentControl), new PropertyMetadata(null)); - } -} diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/SimpleCanvasPreviewControl.xaml b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/SimpleCanvasPreviewControl.xaml deleted file mode 100644 index ef6b0864..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/SimpleCanvasPreviewControl.xaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/SimpleCanvasPreviewControl.xaml.cs b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/SimpleCanvasPreviewControl.xaml.cs deleted file mode 100644 index 260202b3..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/SimpleCanvasPreviewControl.xaml.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.UI.Xaml; - -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasPreview; -using ClipboardCanvas.Helpers; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.SimpleCanvasDisplay -{ - public sealed partial class SimpleCanvasPreviewControl : ObservableUserControl, IBaseCanvasPreviewControlView - { - public SimpleCanvasPreviewControlViewModel ViewModel - { - get => (SimpleCanvasPreviewControlViewModel)DataContext; - set - { - DataContext = value; - TwoWayReadOnlyCanvasPreview?.NotifyPropertyValueUpdated(value); - } - } - - public ICollectionModel CollectionModel { get; set; } - - private TwoWayPropertyUpdater _TwoWayReadOnlyCanvasPreview; - public TwoWayPropertyUpdater TwoWayReadOnlyCanvasPreview - { - get => _TwoWayReadOnlyCanvasPreview; - set - { - if (_TwoWayReadOnlyCanvasPreview != value) - { - _TwoWayReadOnlyCanvasPreview = value; - - if (ViewModel != null) - { - _TwoWayReadOnlyCanvasPreview.NotifyPropertyValueUpdated(ViewModel); - } - } - } - } - - - public static readonly DependencyProperty SimpleCanvasPreviewModelProperty = - DependencyProperty.Register(nameof(SimpleCanvasPreviewModel), typeof(IReadOnlyCanvasPreviewModel), typeof(SimpleCanvasPreviewControl), new PropertyMetadata(null)); - public IReadOnlyCanvasPreviewModel SimpleCanvasPreviewModel - { - get { return (IReadOnlyCanvasPreviewModel)GetValue(SimpleCanvasPreviewModelProperty); } - set { SetValueDP(SimpleCanvasPreviewModelProperty, value); } - } - - - public SimpleCanvasPreviewControl() - { - this.InitializeComponent(); - - this.ViewModel = new SimpleCanvasPreviewControlViewModel(this); - } - - private void UserControl_Loaded(object sender, RoutedEventArgs e) - { - if (ViewModel != null) - { - SimpleCanvasPreviewModel = ViewModel; - } - } - } -} diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/TextSimpleCanvasControl.xaml b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/TextSimpleCanvasControl.xaml deleted file mode 100644 index deb644da..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/TextSimpleCanvasControl.xaml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/TextSimpleCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/TextSimpleCanvasControl.xaml.cs deleted file mode 100644 index 8575b6d5..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/TextSimpleCanvasControl.xaml.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.SimpleCanvasDisplay -{ - public sealed partial class TextSimpleCanvasControl : UserControl - { - public TextSimpleCanvasViewModel ViewModel - { - get => (TextSimpleCanvasViewModel)DataContext; - } - - public TextSimpleCanvasControl() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasControl.xaml b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasControl.xaml deleted file mode 100644 index 42e3989d..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasControl.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasControl.xaml.cs deleted file mode 100644 index 2f8fbb95..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasControl.xaml.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.SimpleCanvasDisplay -{ - public sealed partial class ThumbnailSimpleCanvasControl : UserControl - { - public ThumbnailSimpleCanvasViewModel ViewModel - { - get => (ThumbnailSimpleCanvasViewModel)DataContext; - } - - public ThumbnailSimpleCanvasControl() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasControl.xaml b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasControl.xaml deleted file mode 100644 index e7aaeeba..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasControl.xaml +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasControl.xaml.cs b/ClipboardCanvas/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasControl.xaml.cs deleted file mode 100644 index e74da7f6..00000000 --- a/ClipboardCanvas/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasControl.xaml.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -using ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.SimpleCanvasDisplay -{ - public sealed partial class UrlSimpleCanvasControl : UserControl - { - public UrlSimpleCanvasViewModel ViewModel - { - get => (UrlSimpleCanvasViewModel)DataContext; - } - - public UrlSimpleCanvasControl() - { - this.InitializeComponent(); - } - } -} diff --git a/ClipboardCanvas/UserControls/StatusCenterControl.xaml b/ClipboardCanvas/UserControls/StatusCenterControl.xaml deleted file mode 100644 index d8df4c93..00000000 --- a/ClipboardCanvas/UserControls/StatusCenterControl.xaml +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/StatusCenterControl.xaml.cs b/ClipboardCanvas/UserControls/StatusCenterControl.xaml.cs deleted file mode 100644 index 8edbbd94..00000000 --- a/ClipboardCanvas/UserControls/StatusCenterControl.xaml.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.ViewModels.UserControls.StatusCenter; -using ClipboardCanvas.Services; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class StatusCenterControl : UserControl - { - private IStatusCenterService StatusCenterService { get; } = Ioc.Default.GetService(); - - public StatusCenterViewModel ViewModel - { - get => (StatusCenterViewModel)DataContext; - set => DataContext = value; - } - - public StatusCenterControl() - { - this.InitializeComponent(); - - this.ViewModel = new StatusCenterViewModel(); - - if (this.StatusCenterService is Services.Implementation.StatusCenterService statusCenterServiceImpl) - { - statusCenterServiceImpl.StatusCenterViewModel = this.ViewModel; - } - } - } -} diff --git a/ClipboardCanvas/UserControls/SuggestedActionsControl.xaml b/ClipboardCanvas/UserControls/SuggestedActionsControl.xaml deleted file mode 100644 index b36ea381..00000000 --- a/ClipboardCanvas/UserControls/SuggestedActionsControl.xaml +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/SuggestedActionsControl.xaml.cs b/ClipboardCanvas/UserControls/SuggestedActionsControl.xaml.cs deleted file mode 100644 index b070ebf3..00000000 --- a/ClipboardCanvas/UserControls/SuggestedActionsControl.xaml.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -using ClipboardCanvas.ViewModels.UserControls; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class SuggestedActionsControl : UserControl - { - public SuggestedActionsControlViewModel ViewModel - { - get => (SuggestedActionsControlViewModel)GetValue(ViewModelProperty); - set => SetValue(ViewModelProperty, value); - } - - public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register( - "ViewModel", - typeof(SuggestedActionsControlViewModel), - typeof(SuggestedActionsControl), - new PropertyMetadata(null)); - - public SuggestedActionsControl() - { - this.InitializeComponent(); - - // TODO: Use AttachedViewModel and set there DataContext? - } - - private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) - { - this.ViewModel?.DefaultKeyboardAcceleratorInvokedCommand?.Execute(args); - } - - private void ListView_ItemClick(object sender, ItemClickEventArgs e) - { - this.ViewModel?.ItemClickCommand?.Execute(e); - } - } -} diff --git a/ClipboardCanvas/UserControls/Widgets/CollectionsWidget.xaml b/ClipboardCanvas/UserControls/Widgets/CollectionsWidget.xaml deleted file mode 100644 index 70227f95..00000000 --- a/ClipboardCanvas/UserControls/Widgets/CollectionsWidget.xaml +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/Widgets/CollectionsWidget.xaml.cs b/ClipboardCanvas/UserControls/Widgets/CollectionsWidget.xaml.cs deleted file mode 100644 index 6de925e2..00000000 --- a/ClipboardCanvas/UserControls/Widgets/CollectionsWidget.xaml.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Media; - -using ClipboardCanvas.ViewModels.UserControls.Collections; -using Microsoft.UI.Xaml.Input; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.Widgets -{ - public sealed partial class CollectionsWidget : UserControl - { - public CollectionsWidgetViewModel ViewModel - { - get => (CollectionsWidgetViewModel)DataContext; - set => DataContext = value; - } - - public CollectionsWidget() - { - this.InitializeComponent(); - - this.ViewModel = new CollectionsWidgetViewModel(); - } - - private void UserControl_Loaded(object sender, RoutedEventArgs e) - { - if (ViewModel.SelectedItem != null) - { - CollectionsItemsHolder.ScrollIntoView(ViewModel.SelectedItem); - } - } - - private void RootGrid_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e) - { - e.Handled = true; - ((sender as FrameworkElement).DataContext as BaseCollectionViewModel).OpenCollectionCommand.Execute(null); - } - - private void RootGrid_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - (sender as Grid).Background = (Brush)Resources["ButtonBackgroundPointerOver"]; - (sender as Grid).BorderBrush = (Brush)Resources["ButtonBorderBrushPointerOver"]; - } - - private void RootGrid_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - (sender as Grid).Background = (Brush)Resources["ButtonBackgroundPressed"]; - (sender as Grid).BorderBrush = (Brush)Resources["ButtonBorderBrushPressed"]; - } - - private void RootGrid_PointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) - { - (sender as Grid).Background = (Brush)Resources["ButtonBackground"]; - (sender as Grid).BorderBrush = (Brush)Resources["ButtonBorderBrush"]; - } - - private void Grid_DragOver(object sender, DragEventArgs e) - { - this.ViewModel?.DragOverCommand?.Execute(e); - } - - private void Grid_Drop(object sender, DragEventArgs e) - { - this.ViewModel?.DropCommand?.Execute(e); - } - - private void EditBox_KeyDown(object sender, KeyRoutedEventArgs e) - { - ((sender as FrameworkElement)?.DataContext as BaseCollectionViewModel)?.RenameBoxKeyDownCommand?.Execute(e); - } - - private void EditBox_LostFocus(object sender, RoutedEventArgs e) - { - ((sender as FrameworkElement)?.DataContext as BaseCollectionViewModel)?.RenameBoxLostFocusCommand?.Execute(e); - } - } -} diff --git a/ClipboardCanvas/UserControls/Widgets/TimelineWidget.xaml b/ClipboardCanvas/UserControls/Widgets/TimelineWidget.xaml deleted file mode 100644 index 66e72fa0..00000000 --- a/ClipboardCanvas/UserControls/Widgets/TimelineWidget.xaml +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/Widgets/TimelineWidget.xaml.cs b/ClipboardCanvas/UserControls/Widgets/TimelineWidget.xaml.cs deleted file mode 100644 index f91bb21b..00000000 --- a/ClipboardCanvas/UserControls/Widgets/TimelineWidget.xaml.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.Widgets.Timeline; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls.Widgets -{ - public sealed partial class TimelineWidget : UserControl - { - public TimelineWidgetViewModel ViewModel - { - get => (TimelineWidgetViewModel)DataContext; - set => DataContext = value; - } - - public TimelineWidget() - { - this.InitializeComponent(); - - this.ViewModel = new TimelineWidgetViewModel(); - } - } -} diff --git a/ClipboardCanvas/UserControls/WindowTitleBarControl.xaml b/ClipboardCanvas/UserControls/WindowTitleBarControl.xaml deleted file mode 100644 index 5812e5e3..00000000 --- a/ClipboardCanvas/UserControls/WindowTitleBarControl.xaml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ClipboardCanvas/UserControls/WindowTitleBarControl.xaml.cs b/ClipboardCanvas/UserControls/WindowTitleBarControl.xaml.cs deleted file mode 100644 index 4b3ef1ab..00000000 --- a/ClipboardCanvas/UserControls/WindowTitleBarControl.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.UI.Xaml.Controls; -using ClipboardCanvas.ViewModels.UserControls; -using ClipboardCanvas.Helpers; - -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - -namespace ClipboardCanvas.UserControls -{ - public sealed partial class WindowTitleBarControl : UserControl - { - public WindowTitleBarControlViewModel ViewModel - { - get => (WindowTitleBarControlViewModel)DataContext; - set => DataContext = value; - } - - public WindowTitleBarControl() - { - this.InitializeComponent(); - - this.ViewModel = new WindowTitleBarControlViewModel(); - } - - // TODO: Move to view model?? - private async void RestrictedAccess_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e) - { - await InitialApplicationChecksHelpers.HandleFileSystemPermissionDialog(ViewModel); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/BooleanSearchedItemToShadowOpacityConverter.cs b/ClipboardCanvas/ValueConverters/BooleanSearchedItemToShadowOpacityConverter.cs deleted file mode 100644 index 0e560918..00000000 --- a/ClipboardCanvas/ValueConverters/BooleanSearchedItemToShadowOpacityConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class BooleanSearchedItemToShadowOpacityConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not bool boolValue) - { - return 0.0d; - } - - return boolValue ? 0.9d : 0.0d; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/BooleanToOpacityConverter.cs b/ClipboardCanvas/ValueConverters/BooleanToOpacityConverter.cs deleted file mode 100644 index 9333eaa0..00000000 --- a/ClipboardCanvas/ValueConverters/BooleanToOpacityConverter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class BooleanToOpacityConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not bool boolParam) - { - return 0.0d; - } - - if (boolParam) - { - return 1.0d; - } - else - { - return 0.0d; - } - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/BooleanToVisibilityConverter.cs b/ClipboardCanvas/ValueConverters/BooleanToVisibilityConverter.cs deleted file mode 100644 index c04e3b92..00000000 --- a/ClipboardCanvas/ValueConverters/BooleanToVisibilityConverter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class BooleanToVisibilityConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not bool boolParam) - { - return Visibility.Collapsed; - } - - if (parameter is not string stringParam) - { - return boolParam ? Visibility.Visible : Visibility.Collapsed; - } - else - { - if (stringParam.ToLower() == "invert") - { - return boolParam ? Visibility.Collapsed : Visibility.Visible; - } - - return boolParam ? Visibility.Visible : Visibility.Collapsed; - } - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/ControlToFocusActionConverter.cs b/ClipboardCanvas/ValueConverters/ControlToFocusActionConverter.cs deleted file mode 100644 index 957ab91b..00000000 --- a/ClipboardCanvas/ValueConverters/ControlToFocusActionConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class ControlToFocusActionConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not Control control) - { - return null; - } - - - return new Action(() => control.Focus(FocusState.Programmatic)); - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/DateTimeToStringConverter.cs b/ClipboardCanvas/ValueConverters/DateTimeToStringConverter.cs deleted file mode 100644 index b22b3c35..00000000 --- a/ClipboardCanvas/ValueConverters/DateTimeToStringConverter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class DateTimeToStringConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not DateTime dateTime) - { - return value; - } - - if (parameter is string format) - { - return dateTime.ToString(format); - } - else - { - return dateTime.ToString(); - } - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/ImplicitDataTemplateConverter.cs b/ClipboardCanvas/ValueConverters/ImplicitDataTemplateConverter.cs deleted file mode 100644 index 5beec727..00000000 --- a/ClipboardCanvas/ValueConverters/ImplicitDataTemplateConverter.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class ImplicitDataTemplateConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value == null) - { - return null; - } - - string key = value.GetType().Name; - if (App.Current.Resources.TryGetValue(key, out object dataTemplate)) - { - return dataTemplate; - } - - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/InterfaceToNavigationControlViewModelConverter.cs b/ClipboardCanvas/ValueConverters/InterfaceToNavigationControlViewModelConverter.cs deleted file mode 100644 index 0152e21d..00000000 --- a/ClipboardCanvas/ValueConverters/InterfaceToNavigationControlViewModelConverter.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ClipboardCanvas.ViewModels.UserControls; -using System; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class InterfaceToNavigationControlViewModelConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - return value as NavigationControlViewModel; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - return value; - } - } -} diff --git a/ClipboardCanvas/ValueConverters/InterfaceToSuggestedActionsControlViewModelConverter.cs b/ClipboardCanvas/ValueConverters/InterfaceToSuggestedActionsControlViewModelConverter.cs deleted file mode 100644 index fc16c7b9..00000000 --- a/ClipboardCanvas/ValueConverters/InterfaceToSuggestedActionsControlViewModelConverter.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; -using ClipboardCanvas.ViewModels.UserControls; - -namespace ClipboardCanvas.ValueConverters -{ - public class InterfaceToSuggestedActionsControlViewModelConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - return value as SuggestedActionsControlViewModel; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - return value; - } - } -} diff --git a/ClipboardCanvas/ValueConverters/NullToBooleanConverter.cs b/ClipboardCanvas/ValueConverters/NullToBooleanConverter.cs deleted file mode 100644 index 30cb312d..00000000 --- a/ClipboardCanvas/ValueConverters/NullToBooleanConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public sealed class NullToBooleanConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (parameter is string strParam && strParam.ToLower() == "invert") - { - return value is null; - } - - return value is not null; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/SafeWrapperResultToErrorConverter.cs b/ClipboardCanvas/ValueConverters/SafeWrapperResultToErrorConverter.cs deleted file mode 100644 index c1230ff3..00000000 --- a/ClipboardCanvas/ValueConverters/SafeWrapperResultToErrorConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Data; - -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.ValueConverters -{ - public class SafeWrapperResultToErrorConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not SafeWrapperResult safeWrapperResult) - { - return null; - } - - return safeWrapperResult.Details?.message; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ValueConverters/SelectedItemToBorderThicknessConverter.cs b/ClipboardCanvas/ValueConverters/SelectedItemToBorderThicknessConverter.cs deleted file mode 100644 index e6bf2661..00000000 --- a/ClipboardCanvas/ValueConverters/SelectedItemToBorderThicknessConverter.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Data; - -namespace ClipboardCanvas.ValueConverters -{ - public class SelectedItemToBorderThicknessConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value is not bool boolParam) - { - return new Thickness(0); - } - - if (boolParam) - { - return new Thickness(2); - } - else - { - return new Thickness(0); - } - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} diff --git a/ClipboardCanvas/ViewModels/CollectionPreviewItemViewModel.cs b/ClipboardCanvas/ViewModels/CollectionPreviewItemViewModel.cs deleted file mode 100644 index f81cb60b..00000000 --- a/ClipboardCanvas/ViewModels/CollectionPreviewItemViewModel.cs +++ /dev/null @@ -1,231 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.IO; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.ComponentModel; -using System.Threading; -using Windows.ApplicationModel.DataTransfer; -using Windows.Graphics.Printing3D; -using Windows.Storage; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Interfaces.Search; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ReferenceItems; -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.ContextMenu; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.DependencyInjection; - -namespace ClipboardCanvas.ViewModels -{ - public class CollectionPreviewItemViewModel : ObservableObject, ISearchItem, IDisposable - { - #region Private Members - - private CancellationTokenSource _cancellationTokenSource; - - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService(); - - #endregion - - #region Public Properties - - private string _DisplayName; - public string DisplayName - { - get => _DisplayName; - private set => SetProperty(ref _DisplayName, value); - } - - private bool _IsSelected; - public bool IsSelected - { - get => _IsSelected; - set => SetProperty(ref _IsSelected, value); - } - - private bool _IsHighlighted; - public bool IsHighlighted - { - get => _IsHighlighted; - set => SetProperty(ref _IsHighlighted, value); - } - - private bool _IsCanvasPreviewVisible; - public bool IsCanvasPreviewVisible - { - get => _IsCanvasPreviewVisible; - set => SetProperty(ref _IsCanvasPreviewVisible, value); - } - - public ObservableCollection ContextMenuItems { get; } - - - public TwoWayPropertyUpdater TwoWayReadOnlyCanvasPreview { get; set; } - - public IReadOnlyCanvasPreviewModel ReadOnlyCanvasPreviewModel { get; private set; } - - public ICollectionModel CollectionModel { get; private set; } - - public CollectionItemViewModel CollectionItemViewModel { get; set; } - - #endregion - - #region Constructor - - private CollectionPreviewItemViewModel() - { - this._cancellationTokenSource = new CancellationTokenSource(); - this.ContextMenuItems = new(); - - this.TwoWayReadOnlyCanvasPreview = new TwoWayPropertyUpdater(); - this.TwoWayReadOnlyCanvasPreview.OnPropertyValueUpdatedEvent += TwoWayReadOnlyCanvasPreview_OnPropertyValueUpdatedEvent; - } - - #endregion - - #region Event Handlers - - private void TwoWayReadOnlyCanvasPreview_OnPropertyValueUpdatedEvent(object sender, IReadOnlyCanvasPreviewModel e) - { - ReadOnlyCanvasPreviewModel = e; - } - - #endregion - - #region Public Helpers - - public async Task RequestCanvasLoad() - { - // Wait for control to load - if (ReadOnlyCanvasPreviewModel == null) - { - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - if (ReadOnlyCanvasPreviewModel == null) - { - return; - } - } - - await ReadOnlyCanvasPreviewModel.TryLoadExistingData(CollectionItemViewModel, _cancellationTokenSource.Token); - } - - public async Task RequestCanvasUnload() - { - _cancellationTokenSource.Cancel(); - - if (ReadOnlyCanvasPreviewModel == null) - { - // Wait for control to load if we unload too quickly - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - - if (ReadOnlyCanvasPreviewModel == null) - { - return; - } - } - - ReadOnlyCanvasPreviewModel.DiscardData(); - - _cancellationTokenSource.Dispose(); - _cancellationTokenSource = new CancellationTokenSource(); - } - - public static async Task GetCollectionPreviewItemModel(ICollectionModel collectionModel, CollectionItemViewModel collectionItemViewModel) - { - CollectionPreviewItemViewModel viewModel = new CollectionPreviewItemViewModel() - { - CollectionModel = collectionModel, - CollectionItemViewModel = collectionItemViewModel - }; - - await viewModel.LoadContextMenuItems(); - await viewModel.UpdateDisplayName(); - - return viewModel; - } - - public async Task UpdateDisplayName() - { - DisplayName = Path.GetFileName(await CanvasHelpers.SafeGetCanvasItemPath(CollectionItemViewModel)); - } - - #endregion - - #region Private Helpers - - private async Task LoadContextMenuItems() - { - if (!ContextMenuItems.IsEmpty()) - return; - - var sourceItem = await CollectionItemViewModel.SourceItem; - if (sourceItem is IStorageFolder && sourceItem.Name.EndsWith(Constants.FileSystem.INFINITE_CANVAS_EXTENSION)) - { - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(PasteToInfiniteCanvas), - IconGlyph = "\uE77F", - Text = "PasteFromClipboard".GetLocalized2() - }); - } - else - { - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(CopyFile), - IconGlyph = "\uE8C8", - Text = "CopyFile".GetLocalized2() - }); - } - } - - private async Task CopyFile() - { - DataPackage data = new DataPackage(); - bool result = await ReadOnlyCanvasPreviewModel.SetDataToDataPackage(data); - ClipboardHelpers.CopyDataPackage(data); - } - - private async Task PasteToInfiniteCanvas() - { - var clipboardData = ClipboardHelpers.GetClipboardData(); - if (!clipboardData) - return; - - var pastedItemContentType = await BaseContentTypeModel.GetContentTypeFromDataPackage(clipboardData); - if (pastedItemContentType is InvalidContentTypeDataModel) - return; - - var canvasItem = new InfiniteCanvasItem(CollectionItemViewModel.AssociatedItem); - var infiniteCanvasFileReceiver = new InfiniteCanvasFileReceiver(canvasItem); - var canvasPasteModel = CanvasHelpers.GetPasteModelFromContentType(pastedItemContentType, infiniteCanvasFileReceiver, new StatusCenterOperationReceiver()); - await canvasPasteModel.PasteData(clipboardData, UserSettingsService.AlwaysPasteFilesAsReference, default); - } - - #endregion - - #region IDisposable - - public void Dispose() - { - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); - ReadOnlyCanvasPreviewModel?.Dispose(); - - if (TwoWayReadOnlyCanvasPreview != null) - { - this.TwoWayReadOnlyCanvasPreview.OnPropertyValueUpdatedEvent -= TwoWayReadOnlyCanvasPreview_OnPropertyValueUpdatedEvent; - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/ContextMenu/BaseMenuFlyoutItemViewModel.cs b/ClipboardCanvas/ViewModels/ContextMenu/BaseMenuFlyoutItemViewModel.cs deleted file mode 100644 index 8d358ba9..00000000 --- a/ClipboardCanvas/ViewModels/ContextMenu/BaseMenuFlyoutItemViewModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using CommunityToolkit.Mvvm.ComponentModel; - -namespace ClipboardCanvas.ViewModels.ContextMenu -{ - public abstract class BaseMenuFlyoutItemViewModel : ObservableObject - { - public object Tag { get; set; } - - public Func IsShown { get; set; } = () => true; - - public bool IsEnabled { get; set; } = true; - } -} diff --git a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutItemViewModel.cs b/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutItemViewModel.cs deleted file mode 100644 index 85662ac0..00000000 --- a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutItemViewModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Windows.Input; - -namespace ClipboardCanvas.ViewModels.ContextMenu -{ - public class MenuFlyoutItemViewModel : BaseMenuFlyoutItemViewModel - { - public ICommand Command { get; set; } - - public object CommandParameter { get; set; } - - public string IconGlyph { get; set; } - - public string Text { get; set; } - } -} diff --git a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutSeparatorViewModel.cs b/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutSeparatorViewModel.cs deleted file mode 100644 index 2dec9ae2..00000000 --- a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutSeparatorViewModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ClipboardCanvas.ViewModels.ContextMenu -{ - public sealed class MenuFlyoutSeparatorViewModel : BaseMenuFlyoutItemViewModel - { - } -} diff --git a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutSubItemViewModel.cs b/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutSubItemViewModel.cs deleted file mode 100644 index d0e63f83..00000000 --- a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutSubItemViewModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace ClipboardCanvas.ViewModels.ContextMenu -{ - public sealed class MenuFlyoutSubItemViewModel : MenuFlyoutItemViewModel - { - public List SubItems { get; set; } = new List(); - } -} diff --git a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutToggleItemViewModel.cs b/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutToggleItemViewModel.cs deleted file mode 100644 index 4da9e2e7..00000000 --- a/ClipboardCanvas/ViewModels/ContextMenu/MenuFlyoutToggleItemViewModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ClipboardCanvas.ViewModels.ContextMenu -{ - public class MenuFlyoutToggleItemViewModel : MenuFlyoutItemViewModel - { - public bool IsChecked { get; set; } - } -} diff --git a/ClipboardCanvas/ViewModels/Dialogs/DeleteConfirmationDialogViewModel.cs b/ClipboardCanvas/ViewModels/Dialogs/DeleteConfirmationDialogViewModel.cs deleted file mode 100644 index c69b458f..00000000 --- a/ClipboardCanvas/ViewModels/Dialogs/DeleteConfirmationDialogViewModel.cs +++ /dev/null @@ -1,30 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; - -namespace ClipboardCanvas.ViewModels.Dialogs -{ - public class DeleteConfirmationDialogViewModel : ObservableObject - { - #region Public Properties - - private bool _PermanentlyDelete; - public bool PermanentlyDelete - { - get => _PermanentlyDelete; - set => SetProperty(ref _PermanentlyDelete, value); - } - - public string FileName { get; private set; } - - #endregion - - #region Constructor - - public DeleteConfirmationDialogViewModel(string fileName, bool permanentlyDelete) - { - this.FileName = fileName; - this.PermanentlyDelete = permanentlyDelete; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Dialogs/FileSystemAccessDialogViewModel.cs b/ClipboardCanvas/ViewModels/Dialogs/FileSystemAccessDialogViewModel.cs deleted file mode 100644 index 319195d5..00000000 --- a/ClipboardCanvas/ViewModels/Dialogs/FileSystemAccessDialogViewModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; - -namespace ClipboardCanvas.ViewModels.Dialogs -{ - public class FileSystemAccessDialogViewModel : ObservableObject - { - #region Commands - - public ICommand OpenSettingsCommand { get; private set; } - - #endregion - - #region Constructor - - public FileSystemAccessDialogViewModel() - { - // Create commands - OpenSettingsCommand = new AsyncRelayCommand(OpenSettings); - } - - #endregion - - #region Command Implementation - - private async Task OpenSettings() - { - await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-broadfilesystemaccess")); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Dialogs/IDialog.cs b/ClipboardCanvas/ViewModels/Dialogs/IDialog.cs deleted file mode 100644 index 5982d83d..00000000 --- a/ClipboardCanvas/ViewModels/Dialogs/IDialog.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Threading.Tasks; - -using ClipboardCanvas.Enums; - -namespace ClipboardCanvas.ViewModels.Dialogs -{ - public interface IDialog - { - TViewModel ViewModel { get; set; } - - Task ShowAsync(); - - void Hide(); - } -} diff --git a/ClipboardCanvas/ViewModels/Dialogs/SettingsDialogViewModel.cs b/ClipboardCanvas/ViewModels/Dialogs/SettingsDialogViewModel.cs deleted file mode 100644 index 9f6cad2b..00000000 --- a/ClipboardCanvas/ViewModels/Dialogs/SettingsDialogViewModel.cs +++ /dev/null @@ -1,42 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using System.Windows.Input; -using CommunityToolkit.Mvvm.Input; - -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.Enums; -using ClipboardCanvas.ModelViews; - -namespace ClipboardCanvas.ViewModels.Dialogs -{ - public class SettingsDialogViewModel : ObservableObject - { - private SettingsFrameNavigationDataModel _CurrentPageNavigation; - public SettingsFrameNavigationDataModel CurrentPageNavigation - { - get => _CurrentPageNavigation; - private set => SetProperty(ref _CurrentPageNavigation, value); - } - - public ISettingsDialogView View { get; set; } - - public ICommand CloseDialogCommand { get; private set; } - - public SettingsDialogViewModel() - { - CurrentPageNavigation = new SettingsFrameNavigationDataModel(SettingsPageType.General); - - // Create commands - CloseDialogCommand = new RelayCommand(CloseDialog); - } - - private void CloseDialog() - { - this.View?.CloseDialog(); - } - - public void UpdateNavigation(SettingsPageType settingsPage) - { - CurrentPageNavigation = new SettingsFrameNavigationDataModel(settingsPage); - } - } -} diff --git a/ClipboardCanvas/ViewModels/Dialogs/UpdateChangeLogDialogViewModel.cs b/ClipboardCanvas/ViewModels/Dialogs/UpdateChangeLogDialogViewModel.cs deleted file mode 100644 index 8f27ace7..00000000 --- a/ClipboardCanvas/ViewModels/Dialogs/UpdateChangeLogDialogViewModel.cs +++ /dev/null @@ -1,169 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using Octokit; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Windows.Input; -using Windows.System; -using CommunityToolkit.Mvvm.DependencyInjection; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.ViewModels.Dialogs -{ - public class UpdateChangeLogDialogViewModel : ObservableObject - { - #region Private Members - - private bool _dataFetchedSuccessfully = false; - - #endregion - - #region Properties - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - private bool _IsLoadingData; - public bool IsLoadingData - { - get => _IsLoadingData; - set => SetProperty(ref _IsLoadingData, value); - } - - private string _UpdateMarkdownInfoText = string.Empty; - public string UpdateMarkdownInfoText - { - get => _UpdateMarkdownInfoText; - set => SetProperty(ref _UpdateMarkdownInfoText, value); - } - - private bool _UpdateMarkdownLoad; - public bool UpdateMarkdownLoad - { - get => _UpdateMarkdownLoad; - set => SetProperty(ref _UpdateMarkdownLoad, value); - } - - #endregion - - #region Commands - - public ICommand OpenReleasesOnGitHubCommand { get; private set; } - - #endregion - - #region Constructor - - public UpdateChangeLogDialogViewModel() - { - // Create commands - OpenReleasesOnGitHubCommand = new AsyncRelayCommand(OpenReleasesOnGitHub); - } - - #endregion - - #region Command Implementation - - private async Task OpenReleasesOnGitHub() - { - await Launcher.LaunchUriAsync(new Uri(@"https://github.com/d2dyno1/ClipboardCanvas/releases")); - } - - #endregion - - #region Public Helpers - - public async Task LoadUpdateDataFromGitHub(bool onlyCompareCurrent = false) - { - IsLoadingData = true; - string currentVersion = ApplicationService.AppVersion; - List<(string Name, string Body)> preparedReleases = null; - - try - { - const string owner = Constants.ClipboardCanvasRepository.REPOSITORY_OWNER; - const string repositoryName = Constants.ClipboardCanvasRepository.REPOSITORY_NAME; - - // Get all releases - GitHubClient client = new GitHubClient(new ProductHeaderValue(owner)); - IReadOnlyList releases = await client.Repository.Release.GetAll(owner, repositoryName); - - preparedReleases = new List<(string Name, string Body)>(); - - // Prepare releases - foreach (var item in releases) - { - string itemVersion = item.TagName; - itemVersion = itemVersion.Replace("v", string.Empty, StringComparison.OrdinalIgnoreCase); - - if (!item.Draft) - { - if (onlyCompareCurrent) - { - if (VersionHelpers.IsVersionEqualTo(itemVersion, currentVersion)) - { - preparedReleases.Add((item.Name, item.Body)); - break; - } - } - else - { - if (VersionHelpers.IsVersionBiggerThanOrEqual(itemVersion, currentVersion)) - { - preparedReleases.Add((item.Name, item.Body)); - } - else if (VersionHelpers.IsVersionSmallerThan(itemVersion, currentVersion)) - { - break; - } - } - } - } - - _dataFetchedSuccessfully = true; - - // Compile update string - foreach (var item in preparedReleases) - { - _UpdateMarkdownInfoText += item.Name; - _UpdateMarkdownInfoText += "\n---"; - _UpdateMarkdownInfoText += "\n"; - _UpdateMarkdownInfoText += item.Body.Replace("\r\n", "\r\n\n"); - _UpdateMarkdownInfoText += "\n"; - _UpdateMarkdownInfoText += "\n"; - } - - IsLoadingData = false; - UpdateMarkdownLoad = true; - - // Update the UI - OnPropertyChanged(nameof(UpdateMarkdownInfoText)); - } - catch (Exception e) - { - _dataFetchedSuccessfully = false; - } - - if (!_dataFetchedSuccessfully || preparedReleases.IsEmpty()) - { - // Getting data failed, display fallback update info - _UpdateMarkdownInfoText += $"Error".GetLocalized2(); - _UpdateMarkdownInfoText += "\n---"; - _UpdateMarkdownInfoText += "\n"; - _UpdateMarkdownInfoText += "ChangelogFetchingError".GetLocalized2(); - - IsLoadingData = false; - UpdateMarkdownLoad = true; - - // Update the UI - OnPropertyChanged(nameof(UpdateMarkdownInfoText)); - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/CanvasPageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/CanvasPageViewModel.cs deleted file mode 100644 index 2af36d31..00000000 --- a/ClipboardCanvas/ViewModels/Pages/CanvasPageViewModel.cs +++ /dev/null @@ -1,631 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System; -using System.Threading; -using System.Windows.Input; -using Windows.ApplicationModel.DataTransfer; -using Windows.System; -using Microsoft.UI.Xaml.Input; -using System.Threading.Tasks; -using Microsoft.UI.Xaml; -using System.Collections.Generic; -using Windows.Storage; -using System.Collections.ObjectModel; - -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Enums; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.ViewModels.UserControls.CanvasPreview; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Services; -using CommunityToolkit.Mvvm.DependencyInjection; - -namespace ClipboardCanvas.ViewModels.Pages -{ - public class CanvasPageViewModel : ObservableObject, IPasteCanvasPageModel, IDisposable - { - #region Private Members - - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - private readonly ICanvasPageView _view; - - private const string DEFAULT_TITLE_TEXT = "Press Ctrl + V to paste in content"; - - private const string DRAG_TITLE_TEXT = "Release to paste in content"; - - private bool _contentFinishedLoading; - - private bool _isInTemporaryErrorLoadPhase; - - #endregion - - #region Public Properties - - public ICollectionModel CollectionModel => _view?.AssociatedCollectionModel; - - public ICanvasPreviewModel PasteCanvasModel => _view?.CanvasPreviewModel; - - private CanvasType _RequestedCanvasType; - public CanvasType RequestedCanvasType - { - get => _RequestedCanvasType; - set - { - if (_RequestedCanvasType != value) - { - _RequestedCanvasType = value; - - OnPropertyChanged(nameof(SwitchCanvasModeText)); - OnPropertyChanged(nameof(CanvasTypeText)); - } - - CollectionModel.AssociatedCanvasType = value; - } - } - - public ObservableCollection CanvasContextMenuItems - { - get => PasteCanvasModel?.ContextMenuItems; - } - - private bool _NewCanvasScreenLoad = true; - public bool NewCanvasScreenLoad - { - get => _NewCanvasScreenLoad; - set => SetProperty(ref _NewCanvasScreenLoad, value); - } - - public string SwitchCanvasModeText - { - get => RequestedCanvasType == CanvasType.OneCanvas ? "SwitchToInfiniteCanvas".GetLocalized2() : "SwitchToOneCanvas".GetLocalized2(); - } - - private bool _InfiniteCanvasCaptionLoad; - public bool InfiniteCanvasCaptionLoad - { - get => _InfiniteCanvasCaptionLoad; - set => SetProperty(ref _InfiniteCanvasCaptionLoad, value); - } - - private bool _CanvasRingLoad; - public bool CanvasRingLoad - { - get => _CanvasRingLoad; - set => SetProperty(ref _CanvasRingLoad, value); - } - - private bool _ShowInCollectionLoad; - public bool ShowInCollectionLoad - { - get => _ShowInCollectionLoad; - set => SetProperty(ref _ShowInCollectionLoad, value); - } - - private bool _InfiniteCanvasProgressLoad = false; - public bool InfiniteCanvasProgressLoad - { - get => _InfiniteCanvasProgressLoad; - set => SetProperty(ref _InfiniteCanvasProgressLoad, value); - } - - private string _TitleText = DEFAULT_TITLE_TEXT; - public string TitleText - { - get => _TitleText; - set => SetProperty(ref _TitleText, value); - } - - public string CanvasTypeText - { - get => RequestedCanvasType == CanvasType.OneCanvas ? "CanvasTypeInfoCurrentOneCanvas".GetLocalized2() : "CanvasTypeInfoCurrentInfiniteCanvas".GetLocalized2(); - } - - private string _TipText; - public string TipText - { - get => _TipText; - set => SetProperty(ref _TipText, value); - } - - private bool _TipTextLoad; - public bool TipTextLoad - { - get => _TipTextLoad; - set => SetProperty(ref _TipTextLoad, value); - } - - private bool _ErrorTextLoad = true; - public bool ErrorTextLoad - { - get => _ErrorTextLoad; - set => SetProperty(ref _ErrorTextLoad, value); - } - - private string _ErrorText; - public string ErrorText - { - get => _ErrorText; - set => SetProperty(ref _ErrorText, value); - } - - private bool _PastedAsReferenceLoad; - public bool PastedAsReferenceLoad - { - get => _PastedAsReferenceLoad; - set => SetProperty(ref _PastedAsReferenceLoad, value); - } - - private bool _OverrideReferenceEnabled = true; - public bool OverrideReferenceEnabled - { - get => _OverrideReferenceEnabled; - set => SetProperty(ref _OverrideReferenceEnabled, value); - } - - #endregion - - #region Commands - - public ICommand DefaultKeyboardAcceleratorInvokedCommand { get; private set; } - - public ICommand DragEnterCommand { get; private set; } - - public ICommand DragLeaveCommand { get; private set; } - - public ICommand DropCommand { get; private set; } - - public ICommand OverrideReferenceCommand { get; private set; } - - public ICommand CanvasContextMenuOpeningCommand { get; private set; } - - public ICommand SwitchCanvasModeCommand { get; private set; } - - public ICommand ShowInCollectionCommand { get; private set; } - - #endregion - - #region Constructor - - public CanvasPageViewModel(ICanvasPageView view) - { - this._view = view; - - HookEvents(); - - (PasteCanvasModel as BaseCanvasPreviewControlViewModel).GetRequestedCanvasTypeFunc = () => RequestedCanvasType; // TODO: This class casting is bad, refactor entire code - - // Create commands - DefaultKeyboardAcceleratorInvokedCommand = new AsyncRelayCommand(DefaultKeyboardAcceleratorInvoked); - DragEnterCommand = new AsyncRelayCommand(DragEnter); - DragLeaveCommand = new RelayCommand(DragLeave); - DropCommand = new AsyncRelayCommand(Drop); - OverrideReferenceCommand = new AsyncRelayCommand(OverrideReference); - CanvasContextMenuOpeningCommand = new RelayCommand(CanvasContextMenuOpening); - SwitchCanvasModeCommand = new RelayCommand(SwitchCanvasMode); - ShowInCollectionCommand = new RelayCommand(ShowInCollection); - } - - #endregion - - #region Command Implementation - - private async Task DefaultKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs e) - { - e.Handled = true; - bool ctrl = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); - bool shift = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Shift); - bool alt = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Menu); - bool win = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Windows); - VirtualKey vkey = e.KeyboardAccelerator.Key; - uint uVkey = (uint)e.KeyboardAccelerator.Key; - - switch (c: ctrl, s: shift, a: alt, w: win, k: vkey) - { - case (c: true, s: false, a: false, w: false, k: VirtualKey.V): - { - await PasteDataInternal(); - break; - } - - case (c: true, s: false, a: false, w: false, k: VirtualKey.C): - { - if (PasteCanvasModel != null) - { - await PasteCanvasModel.CopyData(); - } - break; - } - - case (c: false, s: _, a: false, w: false, k: VirtualKey.Delete): - { - if (PasteCanvasModel != null) - { - await PasteCanvasModel.TryDeleteData(); - } - break; - } - } - } - - private async Task DragEnter(DragEventArgs e) - { - DragOperationDeferral deferral = null; - - try - { - deferral = e.GetDeferral(); - - // Make sure we don't check dragged Infinite Canvas object - if (e.DataView.Properties.ContainsKey(Constants.UI.CanvasContent.INFINITE_CANVAS_DRAGGED_OBJECT_ID)) - { - e.AcceptedOperation = DataPackageOperation.Copy; - } - else if (e.DataView.Contains(StandardDataFormats.Text)) - { - e.AcceptedOperation = DataPackageOperation.Copy; - TitleText = DRAG_TITLE_TEXT; - } - else if (e.DataView.Contains(StandardDataFormats.StorageItems)) - { - SafeWrapper> draggedItems = await SafeWrapperRoutines.SafeWrapAsync(async () => - await e.DataView.GetStorageItemsAsync()); - - if (draggedItems) - { - if (CollectionModel.IsOnNewCanvas) - { - e.AcceptedOperation = DataPackageOperation.Copy; - TitleText = DRAG_TITLE_TEXT; - return; - } - else - { - bool canPaste = true; - - foreach (var item in draggedItems.Result) - { - if (item.Path == (await CollectionModel.CurrentCollectionItemViewModel.SourceItem).Path) - { - canPaste = false; - break; - } - } - - if (canPaste) - { - e.AcceptedOperation = DataPackageOperation.Copy; - TitleText = DRAG_TITLE_TEXT; - return; - } - } - } - } - else - { - e.AcceptedOperation = DataPackageOperation.None; - TitleText = DEFAULT_TITLE_TEXT; - } - } - finally - { - e.Handled = true; - deferral?.Complete(); - } - } - - private void DragLeave(DragEventArgs e) - { - TitleText = DEFAULT_TITLE_TEXT; - } - - private async Task Drop(DragEventArgs e) - { - DragOperationDeferral deferral = null; - - try - { - deferral = e.GetDeferral(); - - // Ignore dragged Infinite Canvas object - if (e.DataView.Properties.ContainsKey(Constants.UI.CanvasContent.INFINITE_CANVAS_DRAGGED_OBJECT_ID)) - { - return; - } - - DataPackageView dataPackage = e.DataView; - await PasteDataInternal(dataPackage); - } - finally - { - e.Handled = true; - deferral?.Complete(); - } - } - - private async Task OverrideReference() - { - OverrideReferenceEnabled = false; - SafeWrapperResult result = await PasteCanvasModel.PasteOverrideReference(); - - if (result) - { - PastedAsReferenceLoad = false; - } - else - { - // TODO: Show error here - } - - OverrideReferenceEnabled = true; - } - - private void CanvasContextMenuOpening() - { - // Always refresh all context menu items - OnPropertyChanged(nameof(CanvasContextMenuItems)); - } - - private void SwitchCanvasMode() - { - if (RequestedCanvasType == CanvasType.InfiniteCanvas) - { - RequestedCanvasType = CanvasType.OneCanvas; - } - else - { - RequestedCanvasType = CanvasType.InfiniteCanvas; - } - } - - private void ShowInCollection() - { - Dispose(); - NavigationService.OpenCollectionPreviewPage(CollectionModel); - } - - #endregion - - #region Event Handlers - - private async void PasteCanvasModel_OnTipTextUpdateRequestedEvent(object sender, TipTextUpdateRequestedEventArgs e) - { - await SetTipText(e.infoText, e.tipShowDelay); - } - - private void PasteCanvasModel_OnProgressReportedEvent(object sender, ProgressReportedEventArgs e) - { - if (e.value == 100.0f) - { - ShowOrHideCanvasLoadingProgress(false, e.contentType); - } - else - { - ShowOrHideCanvasLoadingProgress(true, e.contentType); - } - } - - private async void PasteCanvasModel_OnErrorOccurredEvent(object sender, ErrorOccurredEventArgs e) - { - ErrorTextLoad = true; - ErrorText = e.errorMessage; - ShowOrHideCanvasLoadingProgress(false, null); - - TimeSpan errorMessageDelay = e.errorMessageAutoHide; - if (e.contentType is not InfiniteCanvasContentType) - { - NewCanvasScreenLoad = false; - ShowInCollectionLoad = false; - TipTextLoad = false; - PasteCanvasModel?.DiscardData(); - } - else - { - if (errorMessageDelay == TimeSpan.Zero) - { - errorMessageDelay = TimeSpan.FromMilliseconds(Constants.UI.CanvasContent.INFINITE_CANVAS_ERROR_SHOW_TIME); - } - } - - if (errorMessageDelay != TimeSpan.Zero) - { - _isInTemporaryErrorLoadPhase = true; - await Task.Delay(errorMessageDelay); - ErrorText = null; - ErrorTextLoad = false; - } - - _isInTemporaryErrorLoadPhase = false; - } - - private async void PasteCanvasModel_OnContentStartedLoadingEvent(object sender, ContentStartedLoadingEventArgs e) - { - PastedAsReferenceLoad = false; - InfiniteCanvasCaptionLoad = e.contentType is InfiniteCanvasContentType; - await PrepareForContentStartLoading(e.contentType); - } - - private void PasteCanvasModel_OnContentLoadedEvent(object sender, ContentLoadedEventArgs e) - { - PastedAsReferenceLoad = e.pastedAsReference; - OverrideReferenceEnabled = e.canPasteReference; - ShowOrHideCanvasLoadingProgress(false, e.contentType); - _contentFinishedLoading = true; - NewCanvasScreenLoad = false; - ShowInCollectionLoad = true; - TipTextLoad = false; - ErrorTextLoad = _isInTemporaryErrorLoadPhase; - - _view?.FinishConnectedAnimation(); - } - - private void PasteCanvasModel_OnContentLoadFailedEvent(object sender, ErrorOccurredEventArgs e) - { - _contentFinishedLoading = true; - ShowOrHideCanvasLoadingProgress(false, null); - PastedAsReferenceLoad = false; - - _view?.FinishConnectedAnimation(); - } - - private async void PasteCanvasModel_OnPasteInitiatedEvent(object sender, PasteInitiatedEventArgs e) - { - await PrepareForContentStartLoading(e.contentType); - } - - #endregion - - #region IPasteCanvasPageModel - - public async Task SetTipText(string text) - { - await SetTipText(text, TimeSpan.Zero); - } - - public async Task SetTipText(string text, TimeSpan tipShowDelay) - { - if (!string.IsNullOrWhiteSpace(text)) - { - if (tipShowDelay != TimeSpan.Zero) - { - await Task.Delay(tipShowDelay); - } - - if (!_contentFinishedLoading) - { - TipTextLoad = true; - TipText = text; - } - } - else - { - TipTextLoad = false; - } - } - - #endregion - - #region Private Helpers - - private void ShowOrHideCanvasLoadingProgress(bool show, BaseContentTypeModel contentType) - { - if (show) - { - if (contentType is InfiniteCanvasContentType) - { - InfiniteCanvasProgressLoad = true; - CanvasRingLoad = false; - } - else - { - InfiniteCanvasProgressLoad = false; - CanvasRingLoad = true; - } - } - else - { - InfiniteCanvasProgressLoad = false; - CanvasRingLoad = false; - } - } - - private async Task PrepareForContentStartLoading(BaseContentTypeModel contentType) - { - _contentFinishedLoading = false; - NewCanvasScreenLoad = false; - TipTextLoad = false; - ShowOrHideCanvasLoadingProgress(false, contentType); - - // Await a short delay before showing the loading ring - await Task.Delay(Constants.UI.CanvasContent.SHOW_LOADING_RING_DELAY); - - if (!_contentFinishedLoading) // The value might have changed - { - ShowOrHideCanvasLoadingProgress(true, contentType); - } - } - - private async Task PasteDataInternal(DataPackageView dataPackage = null) - { - SafeWrapperResult result = null; - BaseReadOnlyCanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource.Cancel(); - BaseReadOnlyCanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource = new CancellationTokenSource(); - - if (dataPackage == null) - { - SafeWrapper dataPackageWrapper = ClipboardHelpers.GetClipboardData(); - - if (dataPackageWrapper) - { - result = await PasteCanvasModel.TryPasteData(dataPackageWrapper, CanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource.Token); - } - } - else - { - result = await PasteCanvasModel.TryPasteData(dataPackage, CanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource.Token); - } - - if (result.Exception is ObjectDisposedException) - { - // The last instance was disposed - // That's probably because user tried pasting data to a filled canvas, so new canvas was opened and this disposed - return; - } - else if (!result) // Check if anything went wrong - { - //Debugger.Break(); TODO: Uncomment later - } - } - - #endregion - - #region Event Hooks - - private void HookEvents() - { - UnhookEvents(); - if (PasteCanvasModel != null) - { - PasteCanvasModel.OnPasteInitiatedEvent += PasteCanvasModel_OnPasteInitiatedEvent; - PasteCanvasModel.OnContentStartedLoadingEvent += PasteCanvasModel_OnContentStartedLoadingEvent; - PasteCanvasModel.OnContentLoadedEvent += PasteCanvasModel_OnContentLoadedEvent; - PasteCanvasModel.OnContentLoadFailedEvent += PasteCanvasModel_OnContentLoadFailedEvent; - PasteCanvasModel.OnErrorOccurredEvent += PasteCanvasModel_OnErrorOccurredEvent; - PasteCanvasModel.OnProgressReportedEvent += PasteCanvasModel_OnProgressReportedEvent; - PasteCanvasModel.OnTipTextUpdateRequestedEvent += PasteCanvasModel_OnTipTextUpdateRequestedEvent; - } - } - - private void UnhookEvents() - { - if (PasteCanvasModel != null) - { - PasteCanvasModel.OnPasteInitiatedEvent -= PasteCanvasModel_OnPasteInitiatedEvent; - PasteCanvasModel.OnContentStartedLoadingEvent -= PasteCanvasModel_OnContentStartedLoadingEvent; - PasteCanvasModel.OnContentLoadedEvent -= PasteCanvasModel_OnContentLoadedEvent; - PasteCanvasModel.OnContentLoadFailedEvent -= PasteCanvasModel_OnContentLoadFailedEvent; - PasteCanvasModel.OnErrorOccurredEvent -= PasteCanvasModel_OnErrorOccurredEvent; - PasteCanvasModel.OnProgressReportedEvent -= PasteCanvasModel_OnProgressReportedEvent; - PasteCanvasModel.OnTipTextUpdateRequestedEvent -= PasteCanvasModel_OnTipTextUpdateRequestedEvent; - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - UnhookEvents(); - PasteCanvasModel?.Dispose(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/CollectionPreviewPageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/CollectionPreviewPageViewModel.cs deleted file mode 100644 index d9168153..00000000 --- a/ClipboardCanvas/ViewModels/Pages/CollectionPreviewPageViewModel.cs +++ /dev/null @@ -1,569 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.DependencyInjection; -using ClipboardCanvas.GlobalizationExtensions; -using System; -using System.Linq; -using System.Windows.Input; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Microsoft.UI.Dispatching; - -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments.CollectionPreview; -using ClipboardCanvas.EventArguments.Collections; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.Interfaces.Search; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Services; -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers; -using Windows.System; -using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue; -using CommunityToolkit.WinUI; - -namespace ClipboardCanvas.ViewModels.Pages -{ - public class CollectionPreviewPageViewModel : ObservableObject, ICollectionPreviewPageModel, ISearchItems, IDisposable - { - #region Private Members - - private readonly ICollectionPreviewPageView _view; - - private bool _collectionInitializationFinishedEventHooked; - - private bool _suppressIndexReset; - - #endregion - - #region Properties - - private IUserSettingsService UserSettings { get; } = Ioc.Default.GetService(); - - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - private ICollectionModel AssociatedCollectionModel => _view?.AssociatedCollectionModel; - - private ISearchControlModel SearchControlModel => _view?.SearchControlModel; - - public RangeObservableCollection Items { get; private set; } - - private CollectionPreviewItemViewModel _SelectedItem; - public CollectionPreviewItemViewModel SelectedItem - { - get => _SelectedItem; - set - { - if (SetProperty(ref _SelectedItem, value)) - { - // Set selection property - foreach (var item in Items) - { - item.IsSelected = false; - } - - if (!_suppressIndexReset) - { - SearchControlModel.ResetIndex(); - } - - if (_SelectedItem != null) - { - _SelectedItem.IsSelected = true; - } - - OnCanvasPreviewSelectedItemChangedEvent?.Invoke(this, new CanvasPreviewSelectedItemChangedEventArgs(_SelectedItem)); - } - } - } - - private bool _CollectionLoadingIndicatorLoad; - public bool CollectionLoadingIndicatorLoad - { - get => _CollectionLoadingIndicatorLoad; - set => SetProperty(ref _CollectionLoadingIndicatorLoad, value); - } - - private bool _NoItemsInfoTextLoad; - public bool NoItemsInfoTextLoad - { - get => _NoItemsInfoTextLoad; - set => SetProperty(ref _NoItemsInfoTextLoad, value); - } - - private bool _IsSearchEnabled; - public bool IsSearchEnabled - { - get => _IsSearchEnabled; - set => SetProperty(ref _IsSearchEnabled, value); - } - - private bool _SearchControlVisible; - public bool SearchControlVisible - { - get => _SearchControlVisible; - set => SetProperty(ref _SearchControlVisible, value); - } - - public string SplitButtonMainOptionText - { - get => UserSettings.UseInfiniteCanvasAsDefault ? "OpenNewInfiniteCanvas".GetLocalized2() : "OpenNewCanvas".GetLocalized2(); - } - - public bool SplitButtonShowInfiniteCanvasOption - { - get - { - if (UserSettings.UseInfiniteCanvasAsDefault) - { - // Infinite Canvas is default, so show normal Canvas -> return false - return false; - } - else - { - // ...else, true - return true; - } - } - } - - #endregion - - #region Events - - public event EventHandler OnCanvasPreviewSelectedItemChangedEvent; - - public event EventHandler OnCanvasPreviewPasteRequestedEvent; - - #endregion - - #region Commands - - public ICommand SplitButtonDefaultOptionCommand { get; private set; } - - public ICommand OpenNewCanvasCommand { get; private set; } - - public ICommand OpenNewInfiniteCanvasCommand { get; private set; } - - public ICommand ShowOrHideSearchCommand { get; private set; } - - public ICommand ContainerChangingCommand { get; private set; } - - public ICommand DefaultKeyboardAcceleratorInvokedCommand { get; private set; } - - #endregion - - #region Constructor - - public CollectionPreviewPageViewModel(ICollectionPreviewPageView view) - { - this._view = view; - - HookEvents(); - - this.Items = new RangeObservableCollection(); - SearchControlModel.SearchItems = this; - SearchControlModel.IsKeyboardAcceleratorEnabled = true; - - // Create commands - SplitButtonDefaultOptionCommand = new RelayCommand(SplitButtonDefaultOption); - OpenNewCanvasCommand = new RelayCommand(OpenNewCanvas); - OpenNewInfiniteCanvasCommand = new RelayCommand(OpenNewInfiniteCanvas); - ShowOrHideSearchCommand = new RelayCommand(ShowOrHideSearch); - ContainerChangingCommand = new RelayCommand(ContainerContentChanging); - DefaultKeyboardAcceleratorInvokedCommand = new RelayCommand(DefaultKeyboardAcceleratorInvoked); - } - - #endregion - - #region Command Implementation - - private void SplitButtonDefaultOption() - { - if (UserSettings.UseInfiniteCanvasAsDefault) - { - OpenNewInfiniteCanvas(); - } - else - { - OpenNewCanvas(); - } - } - - private void OpenNewCanvas() - { - NavigationService.OpenNewCanvas(AssociatedCollectionModel, canvasType: CanvasType.OneCanvas); - } - - private void OpenNewInfiniteCanvas() - { - NavigationService.OpenNewCanvas(AssociatedCollectionModel, canvasType: CanvasType.InfiniteCanvas); - } - - private void ShowOrHideSearch() - { - if (SearchControlVisible) - { - HideSearch(); - } - else - { - ShowSearch(); - } - } - - private void ContainerContentChanging(ContainerContentChangingEventArgs e) - { - if (!e.InRecycleQueue) - { - if (e.Item is CollectionPreviewItemViewModel itemViewModel) - { - e.RegisterUpdateCallback(3, async (s, e1) => - { - await itemViewModel.RequestCanvasLoad(); - }); - } - } - else - { - if (e.Item is CollectionPreviewItemViewModel itemViewModel) - { - e.RegisterUpdateCallback(3, async (s, e1) => - { - await itemViewModel.RequestCanvasUnload(); - }); - } - } - } - - private void DefaultKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs e) - { - e.Handled = true; - bool ctrl = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); - bool shift = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Shift); - bool alt = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Menu); - bool win = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Windows); - VirtualKey vkey = e.KeyboardAccelerator.Key; - uint uVkey = (uint)e.KeyboardAccelerator.Key; - - switch (c: ctrl, s: shift, a: alt, w: win, k: vkey) - { - case (c: true, s: false, a: false, w: false, k: VirtualKey.F): // Show Search - { - ShowSearch(); - break; - } - - case (c: false, s: false, a: false, w: false, k: VirtualKey.F3): // Find next - { - SearchControlModel.FindNext(); - break; - } - - case (c: false, s: true, a: false, w: false, k: VirtualKey.F3): // Find previous - { - SearchControlModel.FindPrevious(); - break; - } - - case (c: false, s: false, a: false, w: false, k: VirtualKey.Enter): // Open - { - this.OpenItem(SelectedItem); - break; - } - - case (c: true, s: false, a: false, w: false, k: VirtualKey.V): // Paste - { - SafeWrapper dataPackage = ClipboardHelpers.GetClipboardData(); - if (dataPackage) - { - OnCanvasPreviewPasteRequestedEvent?.Invoke(this, new CanvasPreviewPasteRequestedEventArgs(dataPackage, AssociatedCollectionModel)); - } - break; - } - } - } - - #endregion - - #region ISearchItems - - public int Count => Items.Count; - - public int CurrentIndex => Items.IndexOf(SelectedItem); - - public IEnumerable CompareItemsToPhrase(string phrase) - { - return Items.Where((item) => item.DisplayName.Contains(phrase, StringComparison.InvariantCultureIgnoreCase)); - } - - public int IndexOfItemInCollection(ISearchItem item) - { - return Items.IndexOf(item as CollectionPreviewItemViewModel); - } - - public void SetSelectedIndex(int index) - { - _suppressIndexReset = true; - SelectedItem = Items[index]; - _suppressIndexReset = false; - - _view?.ScrollItemToView(SelectedItem); - } - - #endregion - - #region Public Helpers - - public void OpenItem(CollectionPreviewItemViewModel itemToOpen) - { - if (itemToOpen == null) - { - return; - } - - int indexOfSelectedItem = Items.IndexOf(itemToOpen); - _view.PrepareConnectedAnimation(indexOfSelectedItem); - - // Navigate to canvas and suppress transition since we use ConnectedAnimation - NavigationService.OpenCanvasPage( - AssociatedCollectionModel, - itemToOpen.CollectionItemViewModel, - new CanvasPageNavigationParameterModel(AssociatedCollectionModel, AssociatedCollectionModel.AssociatedCanvasType) - { - CollectionPreviewIDisposable = this - }, - NavigationTransitionType.Suppress); - } - - public void CheckSearchContext() - { - if (AssociatedCollectionModel.SearchContext != null) - { - ShowSearch(); - SearchControlModel.RestoreSearchContext(AssociatedCollectionModel.SearchContext); - } - } - - public async Task Initialize() - { - _view.AssociatedCollectionModel.OnCollectionItemAddedEvent += AssociatedCollectionModel_OnCollectionItemAddedEvent; - _view.AssociatedCollectionModel.OnCollectionItemRemovedEvent += AssociatedCollectionModel_OnCollectionItemRemovedEvent; - _view.AssociatedCollectionModel.OnCollectionItemRenamedEvent += AssociatedCollectionModel_OnCollectionItemRenamedEvent; - _view.AssociatedCollectionModel.OnCollectionItemContentsChangedEvent += AssociatedCollectionModel_OnCollectionItemContentsChangedEvent; - - await InitializeItems(); - } - - #endregion - - #region Private Helpers - - private async Task InitializeItems() - { - if (AssociatedCollectionModel.IsCollectionInitializing) - { - // The collection is still initializing, show loading indicator - CollectionLoadingIndicatorLoad = true; - NoItemsInfoTextLoad = false; - - // Hook event when the collection initialization finishes to update the UI - CollectionsWidgetViewModel.OnCollectionItemsInitializationFinishedEvent += CollectionsControlViewModel_OnCollectionItemsInitializationFinishedEvent; - _collectionInitializationFinishedEventHooked = true; - } - else - { - List> itemTaskDelegates = new List>(); - foreach (var item in AssociatedCollectionModel.CollectionItems) - { - itemTaskDelegates.Add(CollectionPreviewItemViewModel.GetCollectionPreviewItemModel(AssociatedCollectionModel, item)); - } - - CollectionLoadingIndicatorLoad = true; - Items.AddRange(await Task.WhenAll(itemTaskDelegates)); - CollectionLoadingIndicatorLoad = false; - - bool itemsEmpty = Items.IsEmpty(); - NoItemsInfoTextLoad = itemsEmpty; - IsSearchEnabled = !itemsEmpty; - - SetSelectedItemAfterInitialization(); - } - } - - private void SetSelectedItemAfterInitialization() - { - if (AssociatedCollectionModel.CurrentCollectionItemViewModel != null) - { - SelectedItem = Items.FirstOrDefault((item) => item.CollectionItemViewModel == AssociatedCollectionModel.CurrentCollectionItemViewModel); - - _view?.ScrollToItemOnInitialization(SelectedItem); - } - else - { - // If _canvasItemToScrollTo was set -- it will scroll to it, otherwise it'll do nothing - _view?.ScrollToItemOnInitialization(null); - } - } - - private void ShowSearch() - { - SearchControlVisible = true; - SearchControlModel.OnSearchShown(); - } - - private void HideSearch() - { - SearchControlVisible = false; - SearchControlModel.OnSearchHidden(); - } - - #endregion - - #region Event Handlers - - private void UserSettings_OnSettingChangedEvent(object sender, SettingChangedEventArgs e) - { - // If the setting corresponding to new canvas button changed, update the split button - if (e.settingName == nameof(UserSettings.UseInfiniteCanvasAsDefault)) - { - OnPropertyChanged(nameof(SplitButtonMainOptionText)); - OnPropertyChanged(nameof(SplitButtonShowInfiniteCanvasOption)); - } - } - - private async void AssociatedCollectionModel_OnCollectionItemAddedEvent(object sender, CollectionItemAddedEventArgs e) - { - if (AssociatedCollectionModel.IsCollectionInitializing) - { - // Don't add items when the collection is initializing - return; - } - - await DispatcherQueue.GetForCurrentThread().EnqueueAsync(async () => - { - var itemToAdd = await CollectionPreviewItemViewModel.GetCollectionPreviewItemModel(AssociatedCollectionModel, e.itemChanged); - Items.Add(itemToAdd); - }); - } - - private async void AssociatedCollectionModel_OnCollectionItemRemovedEvent(object sender, CollectionItemRemovedEventArgs e) - { - await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() => - { - var itemToRemove = Items.FirstOrDefault((item) => item.CollectionItemViewModel.AssociatedItem.Path == e.itemChanged.AssociatedItem.Path); - - if (itemToRemove != null) - { - Items.Remove(itemToRemove); - } - }); - } - - private async void AssociatedCollectionModel_OnCollectionItemRenamedEvent(object sender, CollectionItemRenamedEventArgs e) - { - await DispatcherQueue.GetForCurrentThread().EnqueueAsync(async () => - { - var itemToChange = Items.FirstOrDefault((item) => item.CollectionItemViewModel.AssociatedItem.Path == e.oldPath); - - if (itemToChange != null) - { - itemToChange.CollectionItemViewModel = e.itemChanged; - - await itemToChange.UpdateDisplayName(); - } - }); - } - - private async void AssociatedCollectionModel_OnCollectionItemContentsChangedEvent(object sender, CollectionItemContentsChangedEventArgs e) - { - await DispatcherQueue.GetForCurrentThread().EnqueueAsync(async () => - { - var itemToChange = Items.FirstOrDefault((item) => item.CollectionItemViewModel.AssociatedItem.Path == e.itemChanged.AssociatedItem.Path); - - if (itemToChange != null) - { - await itemToChange.RequestCanvasLoad(); - } - }); - } - - private void SearchControlModel_OnSearchCloseRequestedEvent(object sender, SearchCloseRequestedEventArgs e) - { - HideSearch(); - } - - private async void CollectionsControlViewModel_OnCollectionItemsInitializationFinishedEvent(object sender, CollectionItemsInitializationFinishedEventArgs e) - { - // Make sure the event was invoked for correct collection - if (AssociatedCollectionModel == e.baseCollectionViewModel) - { - // Initialize items again - await InitializeItems(); - } - } - - #endregion - - #region Event Hooks - - private void HookEvents() - { - UserSettings.OnSettingChangedEvent += UserSettings_OnSettingChangedEvent; - - if (_view.SearchControlModel != null) - { - _view.SearchControlModel.OnSearchCloseRequestedEvent += SearchControlModel_OnSearchCloseRequestedEvent; - } - } - - private void UnhookEvents() - { - UserSettings.OnSettingChangedEvent -= UserSettings_OnSettingChangedEvent; - _view.AssociatedCollectionModel.OnCollectionItemAddedEvent -= AssociatedCollectionModel_OnCollectionItemAddedEvent; - _view.AssociatedCollectionModel.OnCollectionItemRemovedEvent -= AssociatedCollectionModel_OnCollectionItemRemovedEvent; - _view.AssociatedCollectionModel.OnCollectionItemRenamedEvent -= AssociatedCollectionModel_OnCollectionItemRenamedEvent; - _view.AssociatedCollectionModel.OnCollectionItemContentsChangedEvent -= AssociatedCollectionModel_OnCollectionItemContentsChangedEvent; - - if (_view.SearchControlModel != null) - { - _view.SearchControlModel.OnSearchCloseRequestedEvent -= SearchControlModel_OnSearchCloseRequestedEvent; - } - - if (_collectionInitializationFinishedEventHooked) - { - CollectionsWidgetViewModel.OnCollectionItemsInitializationFinishedEvent -= CollectionsControlViewModel_OnCollectionItemsInitializationFinishedEvent; - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - UnhookEvents(); - - if (SearchControlVisible) - { - AssociatedCollectionModel.SearchContext = SearchControlModel.ConstructSearchContext(); - } - else - { - AssociatedCollectionModel.SearchContext = null; - } - - Items.DisposeClear(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/HomePageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/HomePageViewModel.cs deleted file mode 100644 index 6900c6d1..00000000 --- a/ClipboardCanvas/ViewModels/Pages/HomePageViewModel.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using System.Threading.Tasks; - -using ClipboardCanvas.Services; -using ClipboardCanvas.EventArguments; - -namespace ClipboardCanvas.ViewModels.Pages -{ - public class HomePageViewModel : ObservableObject, IDisposable - { - #region Properties - - private ITimelineService TimelineService { get; } = Ioc.Default.GetService(); - - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService(); - - public bool IsTimelineWidgetEnabled - { - get => UserSettingsService.ShowTimelineOnHomepage; - } - - private bool _IsAutopasteTeachingTipShown; - public bool IsAutopasteTeachingTipShown - { - get => _IsAutopasteTeachingTipShown; - set => SetProperty(ref _IsAutopasteTeachingTipShown, value); - } - - #endregion - - public HomePageViewModel() - { - // Hook events - UserSettingsService.OnSettingChangedEvent += UserSettingsService_OnSettingChangedEvent; - } - - public async Task LoadWidgets() - { - await TimelineService.LoadAllSectionsAsync(); - } - - public void OpenTeachingTip() - { - IsAutopasteTeachingTipShown = true; - } - - private void UserSettingsService_OnSettingChangedEvent(object sender, SettingChangedEventArgs e) - { - if (e.settingName == nameof(UserSettingsService.ShowTimelineOnHomepage)) - { - OnPropertyChanged(nameof(IsTimelineWidgetEnabled)); - } - } - - #region IDisposable - - public void Dispose() - { - UserSettingsService.OnSettingChangedEvent -= UserSettingsService_OnSettingChangedEvent; - TimelineService.UnloadAllSections(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsAboutPageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsAboutPageViewModel.cs deleted file mode 100644 index 6136afcc..00000000 --- a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsAboutPageViewModel.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Windows.Input; -using Windows.Storage; -using Windows.System; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.DependencyInjection; -using Windows.ApplicationModel.DataTransfer; -using Octokit; -using System.Linq; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.Services; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.ViewModels.Pages.SettingsPages -{ - public class SettingsAboutPageViewModel : ObservableObject - { - private bool _privacyPolicyTextLoaded; - - private readonly ISettingsAboutPageView _view; - - private IDialogService DialogService { get; } = Ioc.Default.GetService(); - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - public string AppVersionText - { - get => string.Format("SettingsAboutPageAppVersion".GetLocalized2(), ApplicationService.AppVersion); - } - - private bool _PrivacyPolicyProgressRingLoad; - public bool PrivacyPolicyProgressRingLoad - { - get => _PrivacyPolicyProgressRingLoad; - set => SetProperty(ref _PrivacyPolicyProgressRingLoad, value); - } - - private bool _PrivacyPolicyLoadError; - public bool PrivacyPolicyLoadError - { - get => _PrivacyPolicyLoadError; - set => SetProperty(ref _PrivacyPolicyLoadError, value); - } - - private string _PrivacyPolicyText; - public string PrivacyPolicyText - { - get => _PrivacyPolicyText; - set => SetProperty(ref _PrivacyPolicyText, value); - } - - public ICommand LoadPrivacyPolicyCommand { get; private set; } - - public ICommand CopyVersionCommand { get; private set; } - - public ICommand OpenOnGitHubCommand { get; private set; } - - public ICommand OpenLogLocationCommand { get; private set; } - - public ICommand ShowIntroductionScreenCommand { get; private set; } - - public ICommand ShowChangeLogCommand { get; private set; } - - public ICommand SubmitFeedbackCommand { get; private set; } - - public ICommand OpenPrivacyPolicyCommand { get; private set; } - - public SettingsAboutPageViewModel(ISettingsAboutPageView view) - { - this._view = view; - - // Create commands - LoadPrivacyPolicyCommand = new AsyncRelayCommand(LoadPrivacyPolicy); - CopyVersionCommand = new RelayCommand(CopyVersion); - OpenOnGitHubCommand = new AsyncRelayCommand(OpenOnGitHub); - OpenPrivacyPolicyCommand = new AsyncRelayCommand(OpenPrivacyPolicy); - OpenLogLocationCommand = new AsyncRelayCommand(OpenLogLocation); - ShowIntroductionScreenCommand = new RelayCommand(ShowIntroductionScreen); - ShowChangeLogCommand = new AsyncRelayCommand(ShowChangeLog); - SubmitFeedbackCommand = new AsyncRelayCommand(SubmitFeedback); - } - - private async Task LoadPrivacyPolicy() - { - if (_privacyPolicyTextLoaded) - { - return; - } - PrivacyPolicyLoadError = false; - _privacyPolicyTextLoaded = true; - - try - { - PrivacyPolicyProgressRingLoad = true; - - const string owner = Constants.ClipboardCanvasRepository.REPOSITORY_OWNER; - const string repositoryName = Constants.ClipboardCanvasRepository.REPOSITORY_NAME; - - const string privacyPolicyFileName = Constants.ClipboardCanvasRepository.PRIVACY_POLICY_FILENAME; - - GitHubClient client = new GitHubClient(new ProductHeaderValue(owner)); - var fileContents = await client.Repository.Content.GetAllContents(owner, repositoryName, privacyPolicyFileName); - RepositoryContent content = fileContents.FirstOrDefault(); - - if (content != null) - { - string formatted = content.Content.Replace("\r\n", "\r\n\n").Replace("
", "\n"); - PrivacyPolicyText = formatted; - } - else - { - PrivacyPolicyLoadError = true; - } - } - catch - { - PrivacyPolicyLoadError = true; - _privacyPolicyTextLoaded = false; - } - finally - { - PrivacyPolicyProgressRingLoad = false; - } - } - - private void CopyVersion() - { - DataPackage dataPackage = new DataPackage(); - dataPackage.SetText(AppVersionText); - - ClipboardHelpers.CopyDataPackage(dataPackage); - } - - private async Task OpenOnGitHub() - { - await Launcher.LaunchUriAsync(new Uri(@"https://github.com/d2dyno1/ClipboardCanvas")); - } - - private async Task OpenPrivacyPolicy() - { - await Launcher.LaunchUriAsync(new Uri(@"https://github.com/d2dyno1/ClipboardCanvas/blob/master/Privacy.md")); - } - - private void ShowIntroductionScreen() - { - DialogService.CloseDialog(); - _view.IntroductionPanelLoad = true; - } - - private async Task SubmitFeedback() - { - await Launcher.LaunchUriAsync(new Uri(@"https://github.com/d2dyno1/ClipboardCanvas/issues")); - } - - private async Task ShowChangeLog() - { - DialogService.CloseDialog(); - await DialogService.ShowDialog(new UpdateChangeLogDialogViewModel()); - } - - private async Task OpenLogLocation() - { - SafeWrapper exceptionLogFile = await StorageHelpers.GetExceptionLogFile(); - if (exceptionLogFile) - { - await StorageHelpers.OpenContainingFolder(exceptionLogFile.Result); - } - else - { - await Launcher.LaunchFolderAsync(ApplicationData.Current.LocalFolder); - } - } - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsGeneralPageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsGeneralPageViewModel.cs deleted file mode 100644 index a0f4bc3c..00000000 --- a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsGeneralPageViewModel.cs +++ /dev/null @@ -1,109 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using System.Collections.ObjectModel; - -using ClipboardCanvas.Services; -using ClipboardCanvas.DataModels; - -namespace ClipboardCanvas.ViewModels.Pages.SettingsPages -{ - public class SettingsGeneralPageViewModel : ObservableObject - { - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService(); - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - public ObservableCollection AppLanguages { get; set; } - - public SettingsGeneralPageViewModel() - { - AppLanguages = new ObservableCollection(ApplicationService.AppLanguages); - _SelectedLanguageIndex = ApplicationService.AppLanguages.IndexOf(ApplicationService.AppLanguage); - } - - private int _SelectedLanguageIndex; - public int SelectedLanguageIndex - { - get => _SelectedLanguageIndex; - set - { - if (SetProperty(ref _SelectedLanguageIndex, value)) - { - ApplicationService.AppLanguage = AppLanguages[value]; - - if (ApplicationService.CurrentAppLanguage.Id != AppLanguages[value].Id) - { - RestartRequiredLoad = true; - } - else - { - RestartRequiredLoad = false; - } - } - } - } - - private bool _RestartRequiredLoad; - public bool RestartRequiredLoad - { - get => _RestartRequiredLoad; - set => SetProperty(ref _RestartRequiredLoad, value); - } - - public bool UseInfiniteCanvasAsDefault - { - get => UserSettingsService.UseInfiniteCanvasAsDefault; - set - { - if (value != UserSettingsService.UseInfiniteCanvasAsDefault) - { - UserSettingsService.UseInfiniteCanvasAsDefault = value; - - OnPropertyChanged(nameof(UseInfiniteCanvasAsDefault)); - } - } - } - - public bool ShowDeleteConfirmationDialog - { - get => UserSettingsService.ShowDeleteConfirmationDialog; - set - { - if (value != UserSettingsService.ShowDeleteConfirmationDialog) - { - UserSettingsService.ShowDeleteConfirmationDialog = value; - - OnPropertyChanged(nameof(ShowDeleteConfirmationDialog)); - } - } - } - - public bool DeletePermanentlyAsDefault - { - get => UserSettingsService.DeletePermanentlyAsDefault; - set - { - if (value != UserSettingsService.DeletePermanentlyAsDefault) - { - UserSettingsService.DeletePermanentlyAsDefault = value; - - OnPropertyChanged(nameof(DeletePermanentlyAsDefault)); - } - } - } - - public bool ShowTimelineOnHomepage - { - get => UserSettingsService.ShowTimelineOnHomepage; - set - { - if (value != UserSettingsService.ShowTimelineOnHomepage) - { - UserSettingsService.ShowTimelineOnHomepage = value; - - OnPropertyChanged(nameof(ShowTimelineOnHomepage)); - } - } - } - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsNotificationsPageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsNotificationsPageViewModel.cs deleted file mode 100644 index 0d6765bd..00000000 --- a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsNotificationsPageViewModel.cs +++ /dev/null @@ -1,54 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.ViewModels.Pages.SettingsPages -{ - public class SettingsNotificationsPageViewModel : ObservableObject - { - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService(); - - public bool PushErrorNotification - { - get => UserSettingsService.PushErrorNotification; - set - { - if (value != UserSettingsService.PushErrorNotification) - { - UserSettingsService.PushErrorNotification = value; - - OnPropertyChanged(); - } - } - } - - public bool PushAutopasteNotification - { - get => UserSettingsService.PushAutopasteNotification; - set - { - if (value != UserSettingsService.PushAutopasteNotification) - { - UserSettingsService.PushAutopasteNotification = value; - - OnPropertyChanged(); - } - } - } - - public bool PushAutopasteFailedNotification - { - get => UserSettingsService.PushAutopasteFailedNotification; - set - { - if (value != UserSettingsService.PushAutopasteFailedNotification) - { - UserSettingsService.PushAutopasteFailedNotification = value; - - OnPropertyChanged(); - } - } - } - } -} diff --git a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsPastingPageViewModel.cs b/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsPastingPageViewModel.cs deleted file mode 100644 index 40749726..00000000 --- a/ClipboardCanvas/ViewModels/Pages/SettingsPages/SettingsPastingPageViewModel.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Windows.Input; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.Mvvm.Input; - -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.ViewModels.Pages.SettingsPages -{ - public class SettingsPastingPageViewModel : ObservableObject - { - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService(); - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - public bool OpenNewCanvasOnPaste - { - get => UserSettingsService.OpenNewCanvasOnPaste; - set - { - if (value != UserSettingsService.OpenNewCanvasOnPaste) - { - UserSettingsService.OpenNewCanvasOnPaste = value; - - OnPropertyChanged(nameof(OpenNewCanvasOnPaste)); - } - } - } - - public bool AlwaysPasteFilesAsReference - { - get => ApplicationService.IsInRestrictedAccessMode ? false : UserSettingsService.AlwaysPasteFilesAsReference; - set - { - if (value != UserSettingsService.AlwaysPasteFilesAsReference) - { - UserSettingsService.AlwaysPasteFilesAsReference = value; - - OnPropertyChanged(nameof(AlwaysPasteFilesAsReference)); - } - } - } - - public bool PrioritizeMarkdownOverText - { - get => UserSettingsService.PrioritizeMarkdownOverText; - set - { - if (value != UserSettingsService.PrioritizeMarkdownOverText) - { - UserSettingsService.PrioritizeMarkdownOverText = value; - - OnPropertyChanged(nameof(PrioritizeMarkdownOverText)); - } - } - } - - private bool _IsReferenceFilesTeachingTipVisible; - public bool IsReferenceFilesTeachingTipVisible - { - get => _IsReferenceFilesTeachingTipVisible; - set => SetProperty(ref _IsReferenceFilesTeachingTipVisible, value); - } - - public bool IsInRestrictedAccessMode - { - get => ApplicationService.IsInRestrictedAccessMode; - } - - public ICommand ShowReferenceFilesTeachingTipCommand { get; private set; } - - public SettingsPastingPageViewModel() - { - // Create commands - ShowReferenceFilesTeachingTipCommand = new RelayCommand(ShowReferenceFilesTeachingTip); - } - - private void ShowReferenceFilesTeachingTip() - { - IsReferenceFilesTeachingTipVisible = !IsReferenceFilesTeachingTipVisible; - } - } -} diff --git a/ClipboardCanvas/ViewModels/SearchControlViewModel.cs b/ClipboardCanvas/ViewModels/SearchControlViewModel.cs deleted file mode 100644 index 48c38fae..00000000 --- a/ClipboardCanvas/ViewModels/SearchControlViewModel.cs +++ /dev/null @@ -1,311 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.UI.Xaml.Input; -using Windows.System; -using System.Windows.Input; - -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Interfaces.Search; -using ClipboardCanvas.Models; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Contexts; - -namespace ClipboardCanvas.ViewModels -{ - public class SearchControlViewModel : ObservableObject, ISearchControlModel - { - #region Private Members - - private IEnumerable _searchMatchingItems; - - private int _indexInSearch = 0; - - #endregion - - #region Public Properties - - public ISearchItems SearchItems { get; set; } - - private bool _IsKeyboardAcceleratorEnabled; - public bool IsKeyboardAcceleratorEnabled - { - get => _IsKeyboardAcceleratorEnabled; - set => SetProperty(ref _IsKeyboardAcceleratorEnabled, value); - } - - private string _SearchBoxText; - public string SearchBoxText - { - get => _SearchBoxText; - set - { - if (SetProperty(ref _SearchBoxText, value)) - { - Search(_SearchBoxText); - } - } - } - - private bool _IsNextPreviousEnabled; - public bool IsNextPreviousEnabled - { - get => _IsNextPreviousEnabled; - set => SetProperty(ref _IsNextPreviousEnabled, value); - } - - private bool _SearchBoxFocus; - public bool SearchBoxFocus - { - get => _SearchBoxFocus; - set => SetProperty(ref _SearchBoxFocus, value); - } - - #endregion - - #region Events - - public event EventHandler OnSearchCloseRequestedEvent; - - #endregion - - #region Commands - - public ICommand FindNextCommand { get; private set; } - - public ICommand FindPreviousCommand { get; private set; } - - public ICommand HideSearchCommand { get; private set; } - - public ICommand DefaultKeyboardAcceleratorInvokedCommand { get; private set; } - - #endregion - - #region Constructor - - public SearchControlViewModel() - { - // Create Commands - FindNextCommand = new RelayCommand(FindNext); - FindPreviousCommand = new RelayCommand(FindPrevious); - HideSearchCommand = new RelayCommand(HideSearch); - DefaultKeyboardAcceleratorInvokedCommand = new RelayCommand(DefaultKeyboardAcceleratorInvoked); - } - - #endregion - - #region Command Implementation - - private void DefaultKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs e) - { - e.Handled = true; - bool ctrl = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); - bool shift = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Shift); - bool alt = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Menu); - bool win = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Windows); - VirtualKey vkey = e.KeyboardAccelerator.Key; - uint uVkey = (uint)e.KeyboardAccelerator.Key; - - switch (c: ctrl, s: shift, a: alt, w: win, k: vkey) - { - case (c: false, s: false, a: false, w: false, k: VirtualKey.Escape): // Close Search - { - HideSearch(); - break; - } - } - } - - #endregion - - #region ISearchControlModel - - public void FindNext() - { - _indexInSearch++; - - if (_indexInSearch >= _searchMatchingItems.Count()) - { - _indexInSearch = 0; - UpdateItemSelectionOnForward(true); - } - else - { - UpdateItemSelectionOnForward(false); - } - } - - public void FindPrevious() - { - _indexInSearch--; - - if (_indexInSearch < 0) - { - _indexInSearch = _searchMatchingItems.Count() - 1; - UpdateItemSelectionOnBack(true); - } - else - { - UpdateItemSelectionOnBack(false); - } - } - - public void OnSearchShown() - { - SearchBoxFocus = true; - SearchBoxFocus = false; - } - - public void OnSearchHidden() - { - SearchBoxText = string.Empty; - _indexInSearch = 0; - } - - public void ResetIndex() - { - _indexInSearch = 0; - } - - public void RestoreSearchContext(SearchContext searchContext) - { - if (searchContext != null) - { - _indexInSearch = searchContext.indexInSearch; - SearchBoxText = searchContext.phrase; - - Search(SearchBoxText); - FitIndexIfOutOfBounds(); - } - } - - public SearchContext ConstructSearchContext() - { - return new SearchContext(SearchBoxText, _indexInSearch); - } - - #endregion - - #region Private Helpers - - private void Search(string phrase) - { - if (!_searchMatchingItems.IsEmpty()) - { - // Unselect previous items - foreach (var item in _searchMatchingItems) - { - item.IsHighlighted = false; - } - } - - // Don't search empty phrases - if (string.IsNullOrEmpty(phrase)) - { - IsNextPreviousEnabled = false; - return; - } - - // Get matching items - _searchMatchingItems = SearchItems.CompareItemsToPhrase(phrase); - - if (_searchMatchingItems.IsEmpty()) - { - IsNextPreviousEnabled = false; - } - else - { - // Select matching items - foreach (var item in _searchMatchingItems) - { - item.IsHighlighted = true; - } - - IsNextPreviousEnabled = true; - } - } - - private void UpdateItemSelectionOnForward(bool ignoreCurrentIndex) - { - int indexToSelect; - int currentSelectedIndex = SearchItems.CurrentIndex; - int searchIndexInCollection = SearchItems.IndexOfItemInCollection(_searchMatchingItems.ElementAt(_indexInSearch)); - - if (!ignoreCurrentIndex && currentSelectedIndex >= searchIndexInCollection) - { - while (currentSelectedIndex >= searchIndexInCollection) - { - _indexInSearch++; - - if (FitIndexIfOutOfBounds()) - { - // Reached end of the sequence - searchIndexInCollection = SearchItems.IndexOfItemInCollection(_searchMatchingItems.ElementAt(_indexInSearch)); - break; - } - - searchIndexInCollection = SearchItems.IndexOfItemInCollection(_searchMatchingItems.ElementAt(_indexInSearch)); - } - } - - indexToSelect = searchIndexInCollection; - - SearchItems.SetSelectedIndex(indexToSelect); - } - - private void UpdateItemSelectionOnBack(bool ignoreCurrentIndex) - { - int indexToSelect; - int currentSelectedIndex = SearchItems.CurrentIndex; - int searchIndexInCollection = SearchItems.IndexOfItemInCollection(_searchMatchingItems.ElementAt(_indexInSearch)); - - if (!ignoreCurrentIndex && currentSelectedIndex <= searchIndexInCollection) - { - while (currentSelectedIndex <= searchIndexInCollection) - { - _indexInSearch--; - - if (FitIndexIfOutOfBounds()) - { - // Reached end of the sequence - searchIndexInCollection = SearchItems.IndexOfItemInCollection(_searchMatchingItems.ElementAt(_indexInSearch)); - break; - } - - searchIndexInCollection = SearchItems.IndexOfItemInCollection(_searchMatchingItems.ElementAt(_indexInSearch)); - } - } - - indexToSelect = searchIndexInCollection; - - SearchItems.SetSelectedIndex(indexToSelect); - } - - private bool FitIndexIfOutOfBounds() - { - if (_indexInSearch > _searchMatchingItems.Count()) - { - _indexInSearch = 0; - return true; - } - else if (_indexInSearch < 0) - { - _indexInSearch = _searchMatchingItems.Count() - 1; - return true; - } - - return false; - } - - private void HideSearch() - { - OnSearchHidden(); - - OnSearchCloseRequestedEvent?.Invoke(this, new SearchCloseRequestedEventArgs()); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Autopaste/AutopasteControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Autopaste/AutopasteControlViewModel.cs deleted file mode 100644 index 5d7f631f..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Autopaste/AutopasteControlViewModel.cs +++ /dev/null @@ -1,335 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.Mvvm.Input; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Input; -using Windows.ApplicationModel.DataTransfer; -using System.Collections.Specialized; -using System.IO; -using Windows.Storage; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.Models.Autopaste; -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules; -using ClipboardCanvas.ViewModels.UserControls.Collections; - -#nullable enable - -namespace ClipboardCanvas.ViewModels.UserControls.Autopaste -{ - public class AutopasteControlViewModel : ObservableObject, IAutopasteControlModel, IRuleActions, IDisposable - { - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - - private readonly List _autopasteDataQueue = new List(); - - private int _internalCollectionCount; - - private bool _itemAddedInternally; - - private bool _autopasteRoutineStarted = false; - - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - private IAutopasteSettingsService AutopasteSettingsService { get; } = Ioc.Default.GetService(); - - private ITimelineService TimelineService { get; } = Ioc.Default.GetService(); - - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService(); - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - private INotificationService NotificationService { get; } = Ioc.Default.GetService(); - - public RangeObservableCollection AutopasteRules { get; } = new RangeObservableCollection(); - - public IAutopasteTarget AutopasteTarget { get; private set; } - - public string AutopasteTargetName - { - get => AutopasteTarget?.DisplayName ?? "AutopasteNoTarget".GetLocalized2(); - } - - public bool EnableAutopaste - { - get => UserSettingsService.IsAutopasteEnabled; - set - { - if (value != UserSettingsService.IsAutopasteEnabled) - { - UserSettingsService.IsAutopasteEnabled = value; - OnPropertyChanged(); - } - } - } - - private bool _IsInfoBarOpen; - public bool IsInfoBarOpen - { - get => _IsInfoBarOpen; - set => SetProperty(ref _IsInfoBarOpen, value); - } - - #region Commands - - public ICommand ChangeTargetCommand { get; private set; } - - public ICommand AddFileSizeRuleCommand { get; private set; } - - public ICommand AddTypeFilterCommand { get; private set; } - - public ICommand CloseInfoBarCommand { get; private set; } - - #endregion - - public AutopasteControlViewModel() - { - ChangeTargetCommand = new RelayCommand(ChangeTarget); - AddFileSizeRuleCommand = new RelayCommand(AddFileSizeRule); - AddTypeFilterCommand = new RelayCommand(AddTypeFilter); - CloseInfoBarCommand = new RelayCommand(CloseInfoBar); - - AutopasteSettingsService.SavedRules ??= new List(); - - AutopasteRules.CollectionChanged += AutopasteRules_CollectionChanged; - Clipboard.ContentChanged += Clipboard_ContentChanged; - } - - #region Command Implementation - - private void ChangeTarget() - { - NavigationService.OpenHomepage(new FromAutopasteHomepageNavigationParameterModel( - CanvasHelpers.GetDefaultCanvasType())); - } - - private void AddFileSizeRule() - { - AddRuleToRuleset(new FileSizeRuleViewModel(this)); - - if (!AutopasteSettingsService.FileSizeRuleDoesNotApplyToFoldersWarningDismissed) - { - IsInfoBarOpen = true; - } - } - - private void AddTypeFilter() - { - AddRuleToRuleset(new TypeFilterRuleViewModel(this)); - } - - private void CloseInfoBar() - { - AutopasteSettingsService.FileSizeRuleDoesNotApplyToFoldersWarningDismissed = true; - } - - #endregion - - #region Helpers - - public async Task Initialize() - { - if (!string.IsNullOrEmpty(AutopasteSettingsService.AutopastePath)) - { - IAutopasteTarget autopasteTarget = CollectionsWidgetViewModel.FindCollection(AutopasteSettingsService.AutopastePath); - if (autopasteTarget is null) - { - var destinationFolder = await StorageHelpers.ToStorageItem(AutopasteSettingsService.AutopastePath); - if (destinationFolder is null) - return; - - var parentFolder = Path.GetDirectoryName(destinationFolder.Path); - autopasteTarget = new AutopasteTargetWrapper("OOBEInfiniteCanvasTitle".GetLocalized2() + " - " + Path.GetFileName(parentFolder), destinationFolder.Path, - async (dataPackageView, cancellationToken) => - { - var pastedItemContentType = await BaseContentTypeModel.GetContentTypeFromDataPackage(dataPackageView); - if (pastedItemContentType is InvalidContentTypeDataModel invalidContentType) - { - return new SafeWrapper(null, invalidContentType.error); - } - - var canvasItem = new InfiniteCanvasItem(destinationFolder, destinationFolder); - var infiniteCanvasFileReceiver = new InfiniteCanvasFileReceiver(canvasItem); - var canvasPasteModel = CanvasHelpers.GetPasteModelFromContentType(pastedItemContentType, infiniteCanvasFileReceiver, new StatusCenterOperationReceiver()); - return await canvasPasteModel.PasteData(dataPackageView, UserSettingsService.AlwaysPasteFilesAsReference, cancellationToken); - }); - } - - UpdateTarget(autopasteTarget); - } - - // Get rules - if (!AutopasteSettingsService.SavedRules.IsEmpty()) - { - _itemAddedInternally = true; - AutopasteRules.AddRange(AutopasteSettingsService.SavedRules); - foreach (var item in AutopasteRules) - { - item.RuleActions = this; // Initialize Rule Actions when deserializing - if (!IsInfoBarOpen && item is FileSizeRuleViewModel && !AutopasteSettingsService.FileSizeRuleDoesNotApplyToFoldersWarningDismissed) - { - IsInfoBarOpen = true; - } - } - _itemAddedInternally = false; - } - } - - private void AddRuleToRuleset(BaseAutopasteRuleViewModel ruleViewModel) - { - _itemAddedInternally = true; - AutopasteRules.Add(ruleViewModel); - AutopasteSettingsService.GuaranteeAddToList(AutopasteSettingsService.SavedRules, ruleViewModel, nameof(AutopasteSettingsService.SavedRules)); - _itemAddedInternally = false; - } - - public void UpdateTarget(IAutopasteTarget? autopasteTarget) - { - this.AutopasteTarget = autopasteTarget; - OnPropertyChanged(nameof(AutopasteTargetName)); - - AutopasteSettingsService.AutopastePath = autopasteTarget?.TargetPath; - } - - public void SerializeRules() - { - AutopasteSettingsService.SavedRules = AutopasteRules.ToList(); - AutopasteSettingsService.FlushSettings(); - } - - public void RemoveRule(BaseAutopasteRuleViewModel ruleViewModel) - { - AutopasteRules.Remove(ruleViewModel); - AutopasteSettingsService.GuaranteeRemoveFromList(AutopasteSettingsService.SavedRules, ruleViewModel, nameof(AutopasteSettingsService.SavedRules)); - - if (IsInfoBarOpen && !AutopasteRules.Any((item) => item is FileSizeRuleViewModel)) - { - IsInfoBarOpen = false; - } - } - - #endregion - - #region Event Handlers - - private void AutopasteRules_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (_internalCollectionCount < AutopasteRules.Count && !_itemAddedInternally) - { - // Serialize rules when collection items have been reordered - SerializeRules(); - } - - _internalCollectionCount = AutopasteRules.Count; - } - - private async void Clipboard_ContentChanged(object sender, object e) - { - if (AutopasteTarget != null && !ApplicationService.IsWindowActivated && UserSettingsService.IsAutopasteEnabled) - { - SafeWrapper clipboardData = ClipboardHelpers.GetClipboardData(); - if (clipboardData) - { - SafeWrapper pasteResult = (null, SafeWrapperResult.UNKNOWN_FAIL); - - clipboardData.Result.Properties.PrintEnumerable(); - - if (clipboardData.Result.AvailableFormats.IsEmpty()) - { - return; - } - - if (_autopasteRoutineStarted && _autopasteDataQueue.Any(item => - (item.Properties.IsEmpty() && clipboardData.Result.Properties.IsEmpty()) - || item.Properties.SequenceEqual(clipboardData.Result.Properties))) - { - return; // Avoid duplicates where the event is called twice - } - - try - { - // Start and add the operation to queue - _autopasteRoutineStarted = true; - _autopasteDataQueue.Add(clipboardData); - - // Check filters - foreach (var item in AutopasteRules) - { - if (!await item.PassesRule(clipboardData)) - { - return; - } - } - - CancellationToken cancellationToken; - if (UserSettingsService.PushAutopasteNotification) - { - cancellationToken = NotificationService.PushAutopastePasteStartedNotification(); - } - else - { - cancellationToken = CancellationToken.None; - } - - pasteResult = await AutopasteTarget.PasteData(clipboardData, cancellationToken); - - var todaySection = await TimelineService.GetOrCreateTodaySection(); - var targetCollection = CollectionsWidgetViewModel.FindCollection(AutopasteSettingsService.AutopastePath); - if (targetCollection is not null) - await TimelineService.AddItemForSection(todaySection, targetCollection, pasteResult); - } - catch (Exception ex) - { - pasteResult = (null, SafeWrapperResult.FromException(ex)); - } - finally - { - // Remove the completed operation from queue - _autopasteDataQueue.Remove(clipboardData); - _autopasteRoutineStarted = !_autopasteDataQueue.IsEmpty(); - } - - if (pasteResult && UserSettingsService.PushAutopasteNotification) - { - NotificationService.PushAutopastePasteFinishedNotification(); - } - else if (!pasteResult && UserSettingsService.PushAutopasteFailedNotification) - { - // Show notification if failed - NotificationService.PushAutopastePasteFailedNotification(pasteResult); - } - } - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - Clipboard.ContentChanged -= Clipboard_ContentChanged; - if (AutopasteRules != null) - { - AutopasteRules.CollectionChanged -= AutopasteRules_CollectionChanged; - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/BaseAutopasteRuleViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/BaseAutopasteRuleViewModel.cs deleted file mode 100644 index 697e7904..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/BaseAutopasteRuleViewModel.cs +++ /dev/null @@ -1,52 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using Newtonsoft.Json; -using System.Threading.Tasks; -using System.Windows.Input; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.Models.Autopaste; - -namespace ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules -{ - public abstract class BaseAutopasteRuleViewModel : ObservableObject - { - [JsonIgnore] - public IRuleActions RuleActions { get; set; } - - [JsonIgnore] - protected string ruleName; - [JsonIgnore] - public string RuleName - { - get => ruleName; - set => SetProperty(ref ruleName, value); - } - - [JsonIgnore] - protected string ruleFontIconGlyph; - [JsonIgnore] - public string RuleFontIconGlyph - { - get => ruleFontIconGlyph; - set => SetProperty(ref ruleFontIconGlyph, value); - } - - [JsonIgnore] - public ICommand RemoveRuleCommand { get; private set; } - - public BaseAutopasteRuleViewModel(IRuleActions ruleActions) - : this() - { - this.RuleActions = ruleActions; - } - - [JsonConstructor] - private BaseAutopasteRuleViewModel() - { - this.RemoveRuleCommand = new RelayCommand(() => this.RuleActions.RemoveRule(this)); - } - - public abstract Task PassesRule(DataPackageView dataPackage); - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/FileSizeRuleViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/FileSizeRuleViewModel.cs deleted file mode 100644 index 6eacc3b8..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/FileSizeRuleViewModel.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using ByteSizeLib; - -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Models.Autopaste; - -namespace ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules -{ - public sealed class FileSizeRuleViewModel : BaseAutopasteRuleViewModel - { - private double _MaxFileSize; - public double MaxFileSize - { - get => _MaxFileSize; - set - { - if (double.IsNaN(value)) - { - value = 0.0d; - _MaxFileSize = value; - OnPropertyChanged(); - RuleActions?.SerializeRules(); - } - else if (SetProperty(ref _MaxFileSize, value)) - { - RuleActions?.SerializeRules(); - } - } - } - - private double _MinFileSize; - public double MinFileSize - { - get => _MinFileSize; - set - { - if (double.IsNaN(value)) - { - value = 0.0d; - _MinFileSize = value; - OnPropertyChanged(); - RuleActions?.SerializeRules(); - } - else if (SetProperty(ref _MinFileSize, value)) - { - RuleActions?.SerializeRules(); - } - } - } - - public FileSizeRuleViewModel(IRuleActions ruleActions) - : base(ruleActions) - { - ruleName = "File size"; - ruleFontIconGlyph = "\uE2B2"; - _MaxFileSize = 8.0d; - } - - public override async Task PassesRule(DataPackageView dataPackage) - { - if (dataPackage.Contains(StandardDataFormats.StorageItems)) - { - SafeWrapper> items = await dataPackage.SafeGetStorageItemsAsync(); - - if (!items) - { - return false; - } - - foreach (var item in items.Result) - { - if (item is IStorageFile storageFile) - { - long fileSize = await storageFile.GetFileSize(); - return fileSize >= ByteSize.FromMegaBytes(MinFileSize).Bytes && fileSize <= ByteSize.FromMegaBytes(MaxFileSize).Bytes; - } - else - { - return true; - } - } - } - else if (dataPackage.Contains(StandardDataFormats.Text)) - { - SafeWrapper result = await dataPackage.SafeGetTextAsync(); - - if (result && (result.Result.Length < ByteSize.FromMegaBytes(MinFileSize).Bytes || result.Result.Length > ByteSize.FromMegaBytes(MaxFileSize).Bytes)) - { - return false; - } - } - - return true; - } - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/TypeFilterRuleViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/TypeFilterRuleViewModel.cs deleted file mode 100644 index 351bd9c0..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Autopaste/Rules/TypeFilterRuleViewModel.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Newtonsoft.Json; - -using ClipboardCanvas.Models.Autopaste; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using System.Collections.Generic; -using Windows.Storage; -using System.Linq; - -namespace ClipboardCanvas.ViewModels.UserControls.Autopaste.Rules -{ - internal class TypeFilterRuleViewModel : BaseAutopasteRuleViewModel - { - [JsonIgnore] - private int _SelectedIndex; - public int SelectedIndex - { - get => _SelectedIndex; - set - { - if (SetProperty(ref _SelectedIndex, value)) - { - RuleActions?.SerializeRules(); - } - } - } - - public TypeFilterRuleViewModel(IRuleActions ruleActions) - : base(ruleActions) - { - ruleName = "Type filter"; - ruleFontIconGlyph = "\uE71C"; - } - - public override async Task PassesRule(DataPackageView dataPackage) - { - switch (_SelectedIndex) - { - case 0: // Image - { - if (dataPackage.Contains(StandardDataFormats.Bitmap)) - { - return false; - } - - break; - } - - case 1: // Text - { - if (dataPackage.Contains(StandardDataFormats.Text)) - { - SafeWrapper result = await dataPackage.SafeGetTextAsync(); - - if (result && !await WebHelpers.IsValidUrl(result)) - { - return false; - } - } - - break; - } - - case 2: // File - { - if (dataPackage.Contains(StandardDataFormats.StorageItems)) - { - SafeWrapper> result = await dataPackage.SafeGetStorageItemsAsync(); - - if (result && result.Result.Any((item) => item is IStorageFile)) - { - return false; - } - } - - break; - } - - case 3: // Url - { - if (dataPackage.Contains(StandardDataFormats.Text)) - { - SafeWrapper result = await dataPackage.SafeGetTextAsync(); - - if (result && await WebHelpers.IsValidUrl(result)) - { - return false; - } - } - - break; - } - - case 4: // Folder - { - if (dataPackage.Contains(StandardDataFormats.StorageItems)) - { - SafeWrapper> result = await dataPackage.SafeGetStorageItemsAsync(); - - if (result && result.Result.Any((item) => item is IStorageFolder)) - { - return false; - } - } - - break; - } - - default: - return false; - } - - return true; - } - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/BaseCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/BaseCanvasViewModel.cs deleted file mode 100644 index b8f67922..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/BaseCanvasViewModel.cs +++ /dev/null @@ -1,223 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using System.Threading; -using System.Collections.Generic; -using CommunityToolkit.Mvvm.Input; - -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.Models; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Services; -using CommunityToolkit.Mvvm.DependencyInjection; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public abstract class BaseCanvasViewModel : BaseReadOnlyCanvasViewModel, ICanvasPreviewModel, IDisposable - { - #region Members - - protected IPasteModel canvasPasteModel; - - #endregion - - #region Events - - public event EventHandler OnPasteInitiatedEvent; - - public event EventHandler OnFileCreatedEvent; - - public event EventHandler OnFileModifiedEvent; - - #endregion - - #region Constructor - - public BaseCanvasViewModel(ISafeWrapperExceptionReporter errorReporter, BaseContentTypeModel contentType, IBaseCanvasPreviewControlView view) - : base(errorReporter, contentType, view) - { - } - - #endregion - - #region Canvas Operations - - public virtual async Task TryPasteData(DataPackageView dataPackage, CancellationToken cancellationToken) - { - SafeWrapperResult result; - - this.cancellationToken = cancellationToken; - - RaiseOnPasteInitiatedEvent(this, new PasteInitiatedEventArgs(IsContentLoaded, dataPackage, ContentType, AssociatedCollection)); - - if (IsDisposed) - { - return new SafeWrapperResult(OperationErrorCode.InvalidOperation, new ObjectDisposedException(nameof(BaseCanvasViewModel)), "The canvas has been already disposed of."); - } - else if (IsContentLoaded) - { - result = new SafeWrapperResult(OperationErrorCode.AlreadyExists, new InvalidOperationException(), "Content has been already pasted."); - RaiseOnErrorOccurredEvent(this, new ErrorOccurredEventArgs(result, result.Message, ContentType)); - - return result; - } - - canvasPasteModel = SetCanvasPasteModel(); - - if (canvasPasteModel == null) - { - return new SafeWrapperResult(OperationErrorCode.AccessUnauthorized, null, "Couldn't paste content."); - } - - SafeWrapper pasteResult = await canvasPasteModel.PasteData(dataPackage, CanPasteAsReference(), cancellationToken); - this.canvasItem = pasteResult.Result; - - if (!AssertNoError(pasteResult)) - { - return pasteResult; - } - - isContentAsReference = canvasPasteModel.IsContentAsReference; - - // Set collectionItemViewModel because it wasn't set before - this.collectionItemViewModel = AssociatedCollection?.FindCollectionItem(canvasItem); - - // Notify paste succeeded - await OnPasteSucceeded(canvasItem); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - if (UserSettings.OpenNewCanvasOnPaste) - { - OpenNewCanvas(); - } - else - { - // We only need to fetch the data to view if we stay on that canvas - result = await TryFetchDataToView(); - if (!AssertNoError(result)) - { - return result; - } - - IsContentLoaded = true; - CanPasteReference = CheckCanPasteReference(); - - RefreshContextMenuItems(); - AssociatedCollection?.UpdateIndex(collectionItemViewModel); - RaiseOnContentLoadedEvent(this, new ContentLoadedEventArgs(ContentType, IsContentLoaded, canvasPasteModel.IsContentAsReference, CanPasteReference)); - } - - return SafeWrapperResult.SUCCESS; - } - - public virtual void OpenNewCanvas() - { - DiscardData(); - NavigationService.OpenNewCanvas(AssociatedCollection); - } - - public virtual async Task> GetSuggestedActions() - { - List actions = new List(); - - if (AssociatedItem == null) - { - return actions; - } - - // Open file - IStorageFile file = null; - if (isContentAsReference && await SourceFile != null) - { - file = await SourceFile; - } - else - { - if (AssociatedFile != null) - { - file = AssociatedFile; - } - } - - // Open file - var action_openFile = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - await AssociatedCollection.CurrentCollectionItemViewModel.OpenFile(); - }), "OpenFile".GetLocalized2(), "\uE8E5"); - - // Open directory - var action_openContainingFolder = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - await AssociatedCollection.CurrentCollectionItemViewModel.OpenContainingFolder(); - }), "OpenContainingFolder".GetLocalized2(), "\uE838"); - - // Show in collection - var action_showInCollection = new SuggestedActionsControlItemViewModel( - new RelayCommand(() => - { - var navigationService = Ioc.Default.GetService(); - navigationService.OpenCollectionPreviewPage(AssociatedCollection); - }), "ShowInCollection".GetLocalized2(), ""); - - actions.Add(action_openFile); - actions.Add(action_openContainingFolder); - - return actions; - } - - #endregion - - #region Protected Helpers - - protected virtual Task OnPasteSucceeded(CanvasItem pastedItem) - { - _ = pastedItem; - return Task.CompletedTask; - } - - protected virtual bool CanPasteAsReference() - { - return UserSettings.AlwaysPasteFilesAsReference; - } - - protected abstract IPasteModel SetCanvasPasteModel(); - - #endregion - - #region Event Raisers - - protected void RaiseOnPasteInitiatedEvent(object s, PasteInitiatedEventArgs e) => OnPasteInitiatedEvent?.Invoke(s, e); - - protected void RaiseOnFileCreatedEvent(object s, FileCreatedEventArgs e) => OnFileCreatedEvent?.Invoke(s, e); - - protected void RaiseOnFileModifiedEvent(object s, FileModifiedEventArgs e) => OnFileModifiedEvent?.Invoke(s, e); - - #endregion - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - this.canvasPasteModel?.Dispose(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/BaseReadOnlyCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/BaseReadOnlyCanvasViewModel.cs deleted file mode 100644 index 39177efb..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/BaseReadOnlyCanvasViewModel.cs +++ /dev/null @@ -1,471 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using CommunityToolkit.Mvvm.DependencyInjection; -using System.Collections.ObjectModel; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.Models; -using ClipboardCanvas.ReferenceItems; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.CanvasFileReceivers; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public abstract class BaseReadOnlyCanvasViewModel : ObservableObject, IReadOnlyCanvasPreviewModel, IDisposable - { - #region Protected Members - - protected readonly IBaseCanvasPreviewControlView view; - - protected readonly ISafeWrapperExceptionReporter errorReporter; - - protected CancellationToken cancellationToken; - - /// - /// Determines whether content is in reference mode - /// - protected bool isContentAsReference; - - protected CollectionItemViewModel collectionItemViewModel; - - protected CanvasItem canvasItem; - - #endregion - - #region Properties - - public static readonly SafeWrapperResult ReferencedFileNotFoundResult = new SafeWrapperResult(OperationErrorCode.NotFound, new FileNotFoundException(), "The file referenced was not found"); - - public static readonly SafeWrapperResult ItemIsNotAFileResult = new SafeWrapperResult(OperationErrorCode.InvalidArgument, new ArgumentException(), "The provided item is not a file."); - - protected IUserSettingsService UserSettings { get; } = Ioc.Default.GetService(); - - protected ICanvasSettingsService CanvasSettings { get; } = Ioc.Default.GetService(); - - protected INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - protected ITimelineService TimelineService { get; } = Ioc.Default.GetService(); - - protected IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - protected ICollectionModel AssociatedCollection => view?.CollectionModel; - - /// - protected StorageFile AssociatedFile => AssociatedItem as StorageFile; - - /// - protected Task SourceFile => Task.Run(async () => (await SourceItem) as StorageFile); - - /// - protected Task SourceFolder => Task.Run(async () => (await SourceItem) as StorageFolder); - - /// - /// The item that's associated with the canvas. For guaranteed true file, use instead. - /// - protected IStorageItem AssociatedItem => canvasItem?.AssociatedItem; - - /// - /// The source item. If not in reference mode, points to - /// - protected Task SourceItem => canvasItem?.SourceItem; - - protected bool IsDisposed { get; private set; } - - public BaseContentTypeModel ContentType { get; protected set; } - - public bool IsContentLoaded { get; protected set; } - - public bool CanPasteReference { get; protected set; } - - public ObservableCollection ContextMenuItems { get; protected set; } - - public ICanvasItemReceiverModel CanvasItemReceiver { get; set; } - - #endregion - - #region Events - - public event EventHandler OnContentStartedLoadingEvent; - - public event EventHandler OnContentLoadedEvent; - - public event EventHandler OnContentLoadFailedEvent; - - public event EventHandler OnFileDeletedEvent; - - public event EventHandler OnErrorOccurredEvent; - - public event EventHandler OnTipTextUpdateRequestedEvent; - - public event EventHandler OnProgressReportedEvent; - - #endregion - - #region Constructor - - public BaseReadOnlyCanvasViewModel(ISafeWrapperExceptionReporter errorReporter, BaseContentTypeModel contentType, IBaseCanvasPreviewControlView view) - { - this.errorReporter = errorReporter; - this.ContentType = contentType; - this.view = view; - - this.ContextMenuItems = new ObservableCollection(); - } - - #endregion - - #region Canvas Operations - - public virtual async Task TryLoadExistingData(CollectionItemViewModel itemData, CancellationToken cancellationToken) - { - this.collectionItemViewModel = itemData; - - return await TryLoadExistingData(itemData, itemData.ContentType, cancellationToken); - } - - public virtual async Task TryLoadExistingData(CanvasItem canvasItem, BaseContentTypeModel contentType, CancellationToken cancellationToken) - { - SafeWrapperResult result; - - this.cancellationToken = cancellationToken; - this.ContentType = contentType; - this.canvasItem = canvasItem; - - RaiseOnContentStartedLoadingEvent(this, new ContentStartedLoadingEventArgs(contentType)); - - if (!StorageHelpers.Existsh(AssociatedItem.Path)) - { - // We don't invoke OnErrorOccurredEvent here because we want to discard this canvas immediately and not show the error - return new SafeWrapperResult(OperationErrorCode.NotFound, new FileNotFoundException(), "Canvas not found."); - } - else if (collectionItemViewModel?.OperationContext.IsOperationStarted ?? false) // Check if it's being pasted - { - // Hook event to operation finished event - if (!collectionItemViewModel.OperationContext.IsEventAlreadyHooked) - { - collectionItemViewModel.OperationContext.OnOperationFinishedEvent += OperationContext_OnOperationFinishedEvent; - collectionItemViewModel.OperationContext.IsEventAlreadyHooked = true; - } - //this.collectionItemViewModel.OperationContext.OperationProgress = ReportProgress; - - RaiseOnTipTextUpdateRequestedEvent(this, new TipTextUpdateRequestedEventArgs("The file is being pasted, please wait.")); - return new SafeWrapperResult(OperationErrorCode.InProgress, "Pasting is still in progress"); - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - result = await SetContentMode(); - if (!AssertNoError(result)) - { - return result; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - result = await SetDataFromExistingItem(await SourceItem); - if (!AssertNoError(result)) - { - return result; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - result = await TryFetchDataToView(); - if (!AssertNoError(result)) - { - return result; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - IsContentLoaded = true; - CanPasteReference = CheckCanPasteReference(); - - RefreshContextMenuItems(); - RaiseOnContentLoadedEvent(this, new ContentLoadedEventArgs(contentType, IsContentLoaded, isContentAsReference, CanPasteReference)); - - return result; - } - - public virtual async Task TryDeleteData(bool hideConfirmation = false) - { - SafeWrapperResult result = await CanvasHelpers.DeleteCanvasFile(CanvasItemReceiver ?? AssociatedCollection, canvasItem, hideConfirmation); - - if (result != OperationErrorCode.Canceled && !AssertNoError(result)) - { - return result; - } - else if (result != OperationErrorCode.Canceled) - { - RaiseOnFileDeletedEvent(this, new FileDeletedEventArgs(AssociatedItem, AssociatedCollection)); - } - - return result; - } - - public virtual void DiscardData() - { - Dispose(); - IsDisposed = false; - } - - public virtual async Task SetDataToDataPackage(DataPackage data) - { - data.SetStorageItems((await SourceItem).ToListSingle()); - - return true; - } - - public virtual async Task CopyData() - { - DataPackage data = new DataPackage(); - bool result = await SetDataToDataPackage(data); - ClipboardHelpers.CopyDataPackage(data); - - return result; - } - - protected virtual bool CheckCanPasteReference() - { - return true; - } - - protected virtual void RefreshContextMenuItems() - { - ContextMenuItems.DisposeClear(); - - // Open item - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(async () => await StorageHelpers.OpenFile(await SourceItem)), - IconGlyph = "\uE8E5", - Text = "OpenFile".GetLocalized2() - }); - - // Separator - ContextMenuItems.Add(new MenuFlyoutSeparatorViewModel()); - - // Copy item - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(CopyData), - IconGlyph = "\uE8C8", - Text = "CopyFile".GetLocalized2() - }); - - // Open containing folder - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(async () => await StorageHelpers.OpenContainingFolder(await SourceItem)), - IconGlyph = "\uE838", - Text = "OpenContainingFolder".GetLocalized2() - }); - - // Open reference containing folder - if (isContentAsReference) - { - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(() => StorageHelpers.OpenContainingFolder(AssociatedItem)), - IconGlyph = "\uE838", - Text = "OpenReferenceContainingFolder".GetLocalized2() - }); - } - - // Delete item - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(() => TryDeleteData()), - IconGlyph = "\uE74D", - Text = isContentAsReference ? "DeleteReference".GetLocalized2() : "DeleteFile".GetLocalized2(), - }); - } - - public virtual async Task> PasteOverrideReference() - { - if (!isContentAsReference) - { - return new (null, OperationErrorCode.InvalidOperation, new InvalidOperationException(), "Cannot paste file that's not a reference"); - } - - SafeWrapper newCanvasItemResult = await CanvasHelpers.PasteOverrideReference(canvasItem, CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - - if (newCanvasItemResult) - { - this.canvasItem = newCanvasItemResult; - this.collectionItemViewModel = AssociatedCollection?.FindCollectionItem(newCanvasItemResult); - - isContentAsReference = false; - - if (newCanvasItemResult) - { - RefreshContextMenuItems(); - await OnReferencePasted(); - } - } - - return newCanvasItemResult; - } - - protected virtual Task OnReferencePasted() - { - return Task.CompletedTask; - } - - protected abstract Task SetDataFromExistingItem(IStorageItem item); - - protected abstract Task TryFetchDataToView(); - - #endregion - - #region Protected Helpers - - /// - /// Used in critical functions to check if sub-functions returned SUCCESS. - ///
- ///
- /// This function also calls underlying events to report potential error codes from . - ///
- /// - /// - /// - protected virtual bool AssertNoError(SafeWrapperResult result, TimeSpan errorMessageAutoHide) - { - if (result == null) - { - result = SafeWrapperResult.UNKNOWN_FAIL; - } - - if (!result) - { - RaiseOnErrorOccurredEvent(this, new ErrorOccurredEventArgs(result, result.Message, ContentType, errorMessageAutoHide)); - RaiseOnContentLoadFailedEvent(this, new ErrorOccurredEventArgs(result, result.Message, ContentType)); - return false; - } - - return true; - } - - /// - protected virtual bool AssertNoError(SafeWrapperResult result) - { - return AssertNoError(result, TimeSpan.Zero); - } - - /// - /// Wrapper for that raises - /// - protected virtual void ReportProgress(float value) - { - RaiseOnProgressReportedEvent(this, new ProgressReportedEventArgs(value, ContentType)); - } - - protected virtual async Task SetContentMode() - { - if (ReferenceFile.IsReferenceFile(AssociatedFile)) - { - // Reference file - isContentAsReference = true; - - // Check if not null - if (await SourceItem == null) - { - return ReferencedFileNotFoundResult; - } - else - { - return SafeWrapperResult.SUCCESS; - } - } - else - { - // Not a reference - isContentAsReference = false; - - return SafeWrapperResult.SUCCESS; - } - } - - #endregion - - #region Event Handlers - - private async void OperationContext_OnOperationFinishedEvent(object sender, OperationFinishedEventArgs e) - { - collectionItemViewModel.OperationContext.OnOperationFinishedEvent -= OperationContext_OnOperationFinishedEvent; - collectionItemViewModel.OperationContext.IsEventAlreadyHooked = false; - - // Load data again when it's finished, and check if we are still on the canvas to load - if (e.result && AssociatedCollection.IsOnOpenedCanvas(collectionItemViewModel)) - { - await TryLoadExistingData(collectionItemViewModel, cancellationToken); - } - } - - #endregion - - #region Event Raisers - - protected void RaiseOnContentStartedLoadingEvent(object s, ContentStartedLoadingEventArgs e) => OnContentStartedLoadingEvent?.Invoke(s, e); - - protected void RaiseOnContentLoadedEvent(object s, ContentLoadedEventArgs e) => OnContentLoadedEvent?.Invoke(s, e); - - protected void RaiseOnContentLoadFailedEvent(object s, ErrorOccurredEventArgs e) => OnContentLoadFailedEvent?.Invoke(s, e); - - protected void RaiseOnFileDeletedEvent(object s, FileDeletedEventArgs e) => OnFileDeletedEvent?.Invoke(s, e); - - protected void RaiseOnErrorOccurredEvent(object s, ErrorOccurredEventArgs e) => OnErrorOccurredEvent?.Invoke(s, e); - - protected void RaiseOnTipTextUpdateRequestedEvent(object s, TipTextUpdateRequestedEventArgs e) => OnTipTextUpdateRequestedEvent?.Invoke(s, e); - - protected void RaiseOnProgressReportedEvent(object s, ProgressReportedEventArgs e) => OnProgressReportedEvent?.Invoke(s, e); - - #endregion - - #region IDisposable - - public virtual void Dispose() - { - IsDisposed = true; - IsContentLoaded = false; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/FallbackCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/FallbackCanvasViewModel.cs deleted file mode 100644 index a1413fc0..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/FallbackCanvasViewModel.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.UI.Xaml.Media.Imaging; -using Windows.Storage.FileProperties; -using System.Threading.Tasks; -using Windows.Storage; -using System.IO; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public class FallbackCanvasViewModel : BaseCanvasViewModel - { - #region Members - - private StorageItemThumbnail _itemThumbnail; - - private bool _isFolder; - - #endregion - - #region Properties - - private FallbackPasteModel FallbackPasteModel => canvasPasteModel as FallbackPasteModel; - - private string _FileName; - public string FileName - { - get => FallbackPasteModel?.FileName ?? _FileName; - } - - private string _FilePath; - public string FilePath - { - get => FallbackPasteModel?.FilePath ?? _FilePath; - } - - private DateTime _DateCreated; - public DateTime DateCreated - { - get => FallbackPasteModel?.DateCreated ?? _DateCreated; - } - - private DateTime _DateModified; - public DateTime DateModified - { - get => FallbackPasteModel?.DateModified ?? _DateModified; - } - - private BitmapImage _FileIcon; - public BitmapImage FileIcon - { - get => FallbackPasteModel?.FileIcon ?? _FileIcon; - } - - #endregion - - #region Constructor - - public FallbackCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - // Read file properties - if (item is StorageFile file) - { - _itemThumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem); - } - else if (item is StorageFolder folder) - { - _isFolder = true; - _itemThumbnail = await folder.GetThumbnailAsync(ThumbnailMode.SingleItem); - } - - this._FileName = item.Name; - this._FilePath = item.Path; - this._DateCreated = item.DateCreated.DateTime; - - var properties = await item.GetBasicPropertiesAsync(); - this._DateModified = properties.DateModified.DateTime; - - _FileIcon = new BitmapImage(); - await FileIcon.SetSourceAsync(_itemThumbnail); - - return SafeWrapperResult.SUCCESS; - } - - protected override async Task TryFetchDataToView() - { - OnPropertyChanged(nameof(FileName)); - OnPropertyChanged(nameof(FilePath)); - OnPropertyChanged(nameof(DateCreated)); - OnPropertyChanged(nameof(DateModified)); - OnPropertyChanged(nameof(FileIcon)); - - return await Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override IPasteModel SetCanvasPasteModel() - { - return new FallbackPasteModel(CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - } - - protected override bool CheckCanPasteReference() - { - return !_isFolder; - } - - protected override async Task OnReferencePasted() - { - await base.OnReferencePasted(); - - string newPath = await CanvasHelpers.SafeGetCanvasItemPath(canvasItem); - - this._FilePath = newPath; - this._FileName = Path.GetFileName(newPath); - - this.FallbackPasteModel?.UpdatePathProperty(newPath); - - OnPropertyChanged(nameof(FileName)); - OnPropertyChanged(nameof(FilePath)); - } - - #endregion - - #region Public Helpers - - public async Task> ProvideDragData() - { - return (await SourceItem).ToListSingle(); - } - - #endregion - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - _itemThumbnail?.Dispose(); - - _itemThumbnail = null; - _FileIcon = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/ImageCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/ImageCanvasViewModel.cs deleted file mode 100644 index ded3df89..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/ImageCanvasViewModel.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.Streams; -using System.Collections.Generic; -using Windows.Graphics.Imaging; -using Microsoft.UI.Xaml.Media.Imaging; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.Models; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers.Filesystem; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public sealed class ImageCanvasViewModel : BaseCanvasViewModel, IDragDataProviderModel - { - #region Members - - private SoftwareBitmap _softwareBitmap; - - private BitmapImage _gifBitmapImage; - - #endregion - - #region Properties - - private ImagePasteModel ImagePasteModel => canvasPasteModel as ImagePasteModel; - - public static List Extensions => new List() { - ".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff", ".ico", ".svg", ".webp" - }; - - private BitmapImage _ContentImage; - public BitmapImage ContentImage - { - get => _ContentImage; - set => SetProperty(ref _ContentImage, value); - } - - #endregion - - #region Constructor - - public ImageCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper openedStream = await SafeWrapperRoutines.SafeWrapAsync( - () => file.OpenAsync(FileAccessMode.Read).AsTask()); - - if (!openedStream) - { - return openedStream; - } - - SafeWrapperResult result = await SafeWrapperRoutines.SafeWrapAsync(async () => - { - if (FileHelpers.IsPathEqualExtension(item.Path, ".gif")) - { - _gifBitmapImage = new BitmapImage(); - await _gifBitmapImage.SetSourceAsync(openedStream.Result); - } - else - { - BitmapDecoder bitmapDecoder = await BitmapDecoder.CreateAsync(openedStream.Result); - _softwareBitmap = await bitmapDecoder.GetSoftwareBitmapAsync(); - } - }); - - openedStream.Result.Dispose(); - - return result; - } - - protected override async Task TryFetchDataToView() - { - return await SafeWrapperRoutines.SafeWrapAsync(async () => - { - if (_gifBitmapImage != null || ImagePasteModel?.GifBitmapImage != null) - { - ContentImage = ImagePasteModel?.GifBitmapImage ?? _gifBitmapImage; - return; - } - - byte[] buffer; - - if (ImagePasteModel != null && ImagePasteModel?.SoftwareBitmap != null) // Data is pasted, use ImagePasteModel.SoftwareBitmap - { - buffer = await ImagingHelpers.GetBytesFromSoftwareBitmap(ImagePasteModel.SoftwareBitmap, BitmapEncoder.PngEncoderId); - } - else // Data is read from file, use local _softwareBitmap - { - buffer = await ImagingHelpers.GetBytesFromSoftwareBitmap(_softwareBitmap, BitmapEncoder.PngEncoderId); - } - - ContentImage = await ImagingHelpers.ToBitmapAsync(buffer); - Array.Clear(buffer, 0, buffer.Length); - }); - } - - protected override IPasteModel SetCanvasPasteModel() - { - return new ImagePasteModel(CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - } - - public override async Task SetDataToDataPackage(DataPackage data) - { - data.SetStorageItems((await SourceItem).ToListSingle()); - - var imageRandomAccessStreamReference = RandomAccessStreamReference.CreateFromFile(await SourceFile); - data.SetBitmap(imageRandomAccessStreamReference); - - return true; - } - - #endregion - - #region Public Helpers - - public async Task SetDragData(DataPackage data) - { - await SetDataToDataPackage(data); - } - - #endregion - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - _softwareBitmap?.Dispose(); - - _softwareBitmap = null; - _gifBitmapImage = null; - ContentImage = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/InfiniteCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/InfiniteCanvasViewModel.cs deleted file mode 100644 index 9df785c1..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/InfiniteCanvasViewModel.cs +++ /dev/null @@ -1,691 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using System.IO; -using Newtonsoft.Json; -using CommunityToolkit.Mvvm.Input; -using ClipboardCanvas.GlobalizationExtensions; -using System.Linq; -using System.Collections.Generic; -using Windows.Storage.Streams; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Graphics.Display; -using Windows.Graphics.Imaging; -using CommunityToolkit.WinUI; - -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.EventArguments.InfiniteCanvasEventArgs; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.ViewModels.UserControls.CanvasPreview; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Models.Autopaste; -using ClipboardCanvas.Services; -using ClipboardCanvas.UnsafeNative; -using CommunityToolkit.Mvvm.DependencyInjection; -using Vanara.PInvoke; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public class InfiniteCanvasViewModel : BaseCanvasViewModel - { - #region Private Members - - private bool _isPasting; - - private CanvasItem? _lastPastedItem; - - private FilesystemChangeWatcher2 _filesystemChangeWatcher; - - private bool _isFilesystemWatcherReady; - - private ICanvasItemReceiverModel _infiniteCanvasFileReceiver; - - #endregion - - #region Properties - - private InfiniteCanvasItem InfiniteCanvasItem => canvasItem as InfiniteCanvasItem; - - private IInteractableCanvasControlModel InteractableCanvasControlModel => ControlView?.InteractableCanvasModel; - - private IInfiniteCanvasControlView _ControlView; - public IInfiniteCanvasControlView ControlView - { - get => _ControlView; - set - { - if (_ControlView != null) - { - _ControlView.InteractableCanvasModel.OnInfiniteCanvasSaveRequestedEvent -= InteractableCanvasModel_OnInfiniteCanvasSaveRequestedEvent; - } - - _ControlView = value; - - if (_ControlView != null) - { - _ControlView.InteractableCanvasModel.OnInfiniteCanvasSaveRequestedEvent += InteractableCanvasModel_OnInfiniteCanvasSaveRequestedEvent; - } - } - } - - public IAutopasteService AutopasteService { get; } = Ioc.Default.GetRequiredService(); - - #endregion - - #region Constructor - - public InfiniteCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base (StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - public override async Task TryPasteData(DataPackageView dataPackage, CancellationToken cancellationToken) - { - _lastPastedItem = null; - _isPasting = true; - this.cancellationToken = cancellationToken; - SafeWrapperResult fetchDataToViewResult = SafeWrapperResult.SUCCESS; - - try - { - RaiseOnPasteInitiatedEvent(this, - new PasteInitiatedEventArgs(false, null, ContentType, AssociatedCollection)); - - // First, set Infinite Canvas folder - SafeWrapperResult initializeInfiniteCanvasFolderResult = await InitializeInfiniteCanvasFolder(); - if (!AssertNoError(initializeInfiniteCanvasFolderResult)) // Default AssertNoError - { - return initializeInfiniteCanvasFolderResult; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Get content type from data package - BaseContentTypeModel pastedItemContentType = - await BaseContentTypeModel.GetContentTypeFromDataPackage(dataPackage); - - if (pastedItemContentType is InvalidContentTypeDataModel invalidContentType) - { - if (invalidContentType.error == (OperationErrorCode.InvalidOperation | OperationErrorCode.NotAFile)) - { - // This error code means user tried pasting a folder with Reference Files setting *disabled* - AssertNoErrorInfiniteCanvas(invalidContentType.error); // Only for notification - } - else - { - return invalidContentType.error; - } - } - else - { - // Get correct IPasteModel from contentType - IPasteModel canvasPasteModel = CanvasHelpers.GetPasteModelFromContentType(pastedItemContentType, - _infiniteCanvasFileReceiver, new StatusCenterOperationReceiver()); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - if (canvasPasteModel == null) - { - return BaseContentTypeModel.CannotDisplayContentForTypeResult; - } - - // Paste data - SafeWrapper pastedItem = await canvasPasteModel.PasteData(dataPackage, - UserSettings.AlwaysPasteFilesAsReference, cancellationToken); - _lastPastedItem = pastedItem.Result; - - // We don't need IPasteModel anymore, so dispose it - canvasPasteModel.Dispose(); - - if (!pastedItem) - { - return pastedItem; - } - - // Add new object to Infinite Canvas - var interactableCanvasControlItem = await InteractableCanvasControlModel.AddItem( - AssociatedCollection, pastedItemContentType, pastedItem, _infiniteCanvasFileReceiver, - cancellationToken); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Wait for control to load - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - - // Update item position based on datapackage - InteractableCanvasControlModel.UpdateItemPositionFromDataPackage(dataPackage, - interactableCanvasControlItem); - - // Save data after pasting - SafeWrapperResult saveDataResult = await SaveConfigurationModel(); - - // Notify paste succeeded - await OnPasteSucceeded(pastedItem); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - AssertNoErrorInfiniteCanvas(saveDataResult); // Only for notification - - // Fetch data to view - fetchDataToViewResult = await interactableCanvasControlItem.LoadContent(); - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Start filesystem change tracker - await StartFilesystemChangeWatcher((await InfiniteCanvasItem.SourceItem) as StorageFolder); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - RefreshContextMenuItems(); - - RaiseOnContentLoadedEvent(this, - new ContentLoadedEventArgs(pastedItemContentType, false, false, CanPasteReference)); - - return fetchDataToViewResult; - } - finally - { - _isPasting = false; - } - } - - public override async Task TryLoadExistingData(CanvasItem canvasItem, BaseContentTypeModel contentType, CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - this.canvasItem = new InfiniteCanvasItem(canvasItem.AssociatedItem, await canvasItem.SourceItem); - this.ContentType = contentType; - - if (IsDisposed) - { - return null; - } - - RaiseOnContentStartedLoadingEvent(this, new ContentStartedLoadingEventArgs(contentType)); - - // First, initialize Infinite Canvas folder - SafeWrapperResult initializeInfiniteCanvasFolderResult = await InitializeInfiniteCanvasFolder(); - if (!AssertNoError(initializeInfiniteCanvasFolderResult)) // Default AssertNoError - { - return initializeInfiniteCanvasFolderResult; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Get all items in Infinite Canvas folder - IEnumerable items = await Task.Run(async () => await ((await canvasItem.SourceItem) as StorageFolder).GetItemsAsync()); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - List loadContentTasks = new List(); - List interactableCanvasList = new List(); - - foreach (var item in items) - { - if (FileHelpers.IsPathEqualExtension(item.Path, Constants.FileSystem.INFINITE_CANVAS_CONFIGURATION_FILE_EXTENSION) - || Path.GetFileName(item.Path) == Constants.FileSystem.INFINITE_CANVAS_PREVIEW_IMAGE_FILENAME) - { - continue; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Initialize parameters - BaseContentTypeModel itemContentType = await BaseContentTypeModel.GetContentType(item, null); - CanvasItem itemCanvasItem = new CanvasItem(item); - - if (IsDisposed || InteractableCanvasControlModel == null) - { - return null; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Add to canvas - var interactableCanvasItem = await InteractableCanvasControlModel?.AddItem(AssociatedCollection, itemContentType, itemCanvasItem, _infiniteCanvasFileReceiver, cancellationToken); - interactableCanvasList.Add(interactableCanvasItem); - } - - // Read Infinite Canvas configuration file - SafeWrapper readFile = await FilesystemOperations.ReadFileText(InfiniteCanvasItem.ConfigurationFile); - if (!AssertNoErrorInfiniteCanvas(readFile)) - { - return readFile; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Set configuration model - var canvasConfigurationModel = JsonConvert.DeserializeObject(readFile); - InteractableCanvasControlModel.SetConfigurationModel(canvasConfigurationModel); - - // Load item previews - foreach (var item in interactableCanvasList) - { - loadContentTasks.Add(item.LoadContent(true)); - } - await Task.WhenAll(loadContentTasks); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Start filesystem change tracker - await StartFilesystemChangeWatcher((await InfiniteCanvasItem.SourceItem) as StorageFolder); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - // Always regenerate canvas preview on load to update it - await InteractableCanvasControlModel.RegenerateCanvasPreview(); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - RefreshContextMenuItems(); - - RaiseOnContentLoadedEvent(this, new ContentLoadedEventArgs(contentType, IsContentLoaded, false, CanPasteReference)); - - return SafeWrapperResult.SUCCESS; - } - - private async Task SaveConfigurationModel() - { - InfiniteCanvasConfigurationModel canvasConfigurationModel = InteractableCanvasControlModel.ConstructConfigurationModel(); - - string serializedConfig = JsonConvert.SerializeObject(canvasConfigurationModel, Formatting.Indented); - SafeWrapperResult writeConfigResult = await FilesystemOperations.WriteFileText(InfiniteCanvasItem.ConfigurationFile, serializedConfig); - - return writeConfigResult; - } - - protected override Task SetDataFromExistingItem(IStorageItem item) - { - return Task.FromResult(SafeWrapperResult.CANCEL); - } - - protected override Task TryFetchDataToView() - { - return Task.FromResult(SafeWrapperResult.CANCEL); - } - - public override async Task> GetSuggestedActions() - { - List actions = new List(); - - if (AssociatedItem == null) - { - return actions; - } - - // Paste from clipboard - var action_paste = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - SafeWrapper dataPackage = ClipboardHelpers.GetClipboardData(); - - await TryPasteData(dataPackage, CanvasPreviewControlViewModel.CanvasPasteCancellationTokenSource.Token); - }), "PasteFromClipboard".GetLocalized2(), "\uE77F"); - - // Open Infinite Canvas folder - var action_openInfiniteCanvasFolder = new SuggestedActionsControlItemViewModel( - new AsyncRelayCommand(async () => - { - await AssociatedCollection.CurrentCollectionItemViewModel.OpenFile(); - }), "OpenInfiniteCanvasFolder".GetLocalized2(), "\uE838"); - - actions.Add(action_paste); - actions.Add(action_openInfiniteCanvasFolder); - - return actions; - } - - protected override IPasteModel SetCanvasPasteModel() - { - return null; - } - - protected override void RefreshContextMenuItems() - { - ContextMenuItems.Clear(); - - // Set as Autopaste target - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(SetAsAutopasteTarget), - IconGlyph = "\uE77F", - Text = "SetAsAutopasteTarget".GetLocalized2() - }); - - // Reset position - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(InteractableCanvasControlModel.ResetAllItemPositions), - IconGlyph = "\uE72C", - Text = "ResetItemPositions".GetLocalized2() - }); - - // Delete Infinite Canvas - ContextMenuItems.Add(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(() => TryDeleteData()), - IconGlyph = "\uE74D", - Text = isContentAsReference ? "DeleteReference".GetLocalized2() : "DeleteInfiniteCanvas".GetLocalized2() - }); - } - - #endregion - - #region Event Handlers - - private async void InteractableCanvasModel_OnInfiniteCanvasSaveRequestedEvent(object sender, InfiniteCanvasSaveRequestedEventArgs e) - { - // Save configuration - SafeWrapperResult saveDataResult = await SaveConfigurationModel(); - AssertNoErrorInfiniteCanvas(saveDataResult); // Only for notification - - // Save canvas image preview - SafeWrapperResult imagePreviewSaveResult = await SafeWrapperRoutines.SafeWrapAsync(async () => - { - using (IRandomAccessStream fileStream = await InfiniteCanvasItem.CanvasPreviewImageFile.OpenAsync(FileAccessMode.ReadWrite)) - { - byte[] pixelArray = e.canvasImageBuffer.ToArray(); - - IntPtr hwnd = ApplicationService.GetHwnd(MainWindow.Instance); - HMONITOR hmonitor = User32.MonitorFromWindow(hwnd, User32.MonitorFlags.MONITOR_DEFAULTTONULL); - SHCore.GetDpiForMonitor(hmonitor, SHCore.MONITOR_DPI_TYPE.MDT_RAW_DPI, out uint rawDpiX, out uint rawDpiY); - - BitmapEncoder bitmapEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream); - bitmapEncoder.SetPixelData(BitmapPixelFormat.Bgra8, // RGB with alpha - BitmapAlphaMode.Premultiplied, - (uint)e.pixelWidth, - (uint)e.pixelHeight, - rawDpiX, - rawDpiY, - pixelArray); - - await bitmapEncoder.FlushAsync(); - } - }); - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", - Justification = "")] - private async void FilesystemChangeWatcher_OnChangeRegisteredEvent(object sender, ChangeRegisteredEventArgs2 e) - { - try - { - await MainWindow.Instance.DispatcherQueue.EnqueueAsync(async () => - { - if (e.FullPath.EndsWith(".TMP") || e.FullPath.EndsWith("~tmp")) - return; - - // Reflect changes - if (FileHelpers.IsPathEqualExtension(e.FullPath, - Constants.FileSystem.INFINITE_CANVAS_CONFIGURATION_FILE_EXTENSION) - || Path.GetFileName(e.FullPath) == - Constants.FileSystem.INFINITE_CANVAS_PREVIEW_IMAGE_FILENAME) - { - return; - } - - string itemParentFolder = Path.GetDirectoryName(e.FullPath); - string watchedParentFolder = (await InfiniteCanvasItem.SourceItem).Path; - if (itemParentFolder != watchedParentFolder) - { - return; - } - - IStorageItem changedItem = await StorageHelpers.ToStorageItem(e.FullPath); - - switch (e.ChangeType) - { - case WatcherChangeTypes.Created: - { - if (changedItem == null || _isPasting || InteractableCanvasControlModel.FindItem(changedItem.Path) is not null) - { - return; - } - - BaseContentTypeModel contentType = - await BaseContentTypeModel.GetContentType(changedItem, null); - if (contentType != null) - { - CanvasItem canvasItem = new CanvasItem(changedItem); - - var interactableCanvasControlItem = - await InteractableCanvasControlModel.AddItem(AssociatedCollection, contentType, - canvasItem, _infiniteCanvasFileReceiver, cancellationToken); - if (interactableCanvasControlItem != null) - { - await interactableCanvasControlItem.LoadContent(true); - } - } - - break; - } - - case WatcherChangeTypes.Deleted: - { - InteractableCanvasControlModel.RemoveItem(InteractableCanvasControlModel.FindItem(e.FullPath)); - break; - } - - case WatcherChangeTypes.Renamed: - { - if (changedItem != null) - { - string oldName = Path.GetFileName(e.OldPath); - string newName = Path.GetFileName(e.FullPath); - - string oldParentPath = Path.GetDirectoryName(e.OldPath); - string newParentPath = Path.GetDirectoryName(e.FullPath); - - if ((oldName != newName) && (oldParentPath == newParentPath)) - { - // Renamed - var interactableCanvasControlItem = - InteractableCanvasControlModel.FindItem(e.OldPath); - - if (interactableCanvasControlItem != null) - { - interactableCanvasControlItem.CanvasItem.DangerousUpdateItem(changedItem); - await interactableCanvasControlItem.InitializeDisplayName(); - - // Since it was renamed, configuration model needs to be updated too! - await SaveConfigurationModel(); - } - } - } - - break; - } - - case WatcherChangeTypes.Changed: - { - var interactableCanvasControlItem = InteractableCanvasControlModel.FindItem(e.FullPath); - if (interactableCanvasControlItem != null) - { - await interactableCanvasControlItem.LoadContent(); - await InteractableCanvasControlModel.RegenerateCanvasPreview(); - } - - break; - } - } - }); - } - catch (Exception ex) - { - // Wrong thread exception bug? - } - } - - #endregion - - #region Private Helpers - - private async Task SetAsAutopasteTarget() - { - var autopasteTargetBridge = new AutopasteTargetWrapper("OOBEInfiniteCanvasTitle".GetLocalized2() + " - " + AssociatedCollection.DisplayName, (await SourceItem).Path, - async (dataPackage, cancellationToken) => - { - var result = await TryPasteData(dataPackage, cancellationToken); - return new SafeWrapper(_lastPastedItem, result.Details); - }); - AutopasteService.UpdateAutopasteTarget(autopasteTargetBridge); - } - - private bool AssertNoErrorInfiniteCanvas(SafeWrapperResult result) - { - return AssertNoError(result, TimeSpan.FromMilliseconds(Constants.UI.CanvasContent.INFINITE_CANVAS_ERROR_SHOW_TIME)); - } - - private async Task StartFilesystemChangeWatcher(StorageFolder infiniteCanvasFolder) - { - if (!_isFilesystemWatcherReady) - { - _isFilesystemWatcherReady = true; - - this._filesystemChangeWatcher = new FilesystemChangeWatcher2(infiniteCanvasFolder.Path); - this._filesystemChangeWatcher.OnChangeRegisteredEvent += FilesystemChangeWatcher_OnChangeRegisteredEvent; - } - } - - private async Task InitializeInfiniteCanvasFolder() - { - if (InfiniteCanvasItem != null) - { - SafeWrapperResult result = await InfiniteCanvasItem.InitializeCanvasFolder(); - - if (!result) - { - return result; - } - - result = await SetContentMode(); - - if (!result) - { - return result; - } - } - else - { - string folderName = DateTime.Now.ToString(Constants.FileSystem.CANVAS_FILE_FILENAME_DATE_FORMAT); - folderName = $"{folderName}{Constants.FileSystem.INFINITE_CANVAS_EXTENSION}"; - - SafeWrapper canvasFolderResult = await AssociatedCollection.CreateNewCanvasFolder(folderName); - - if (!canvasFolderResult) - { - return canvasFolderResult; - } - canvasItem = new InfiniteCanvasItem(canvasFolderResult.Result.AssociatedItem, await canvasFolderResult.Result.SourceItem); - collectionItemViewModel = AssociatedCollection.FindCollectionItem(canvasItem); - - // Initialize Infinite Canvas - SafeWrapperResult canvasInitializationResult = await InfiniteCanvasItem.InitializeCanvasFolder(); - - if (!canvasInitializationResult) - { - return canvasInitializationResult; - } - } - - // Initialize infinite canvas file receiver - _infiniteCanvasFileReceiver = new InfiniteCanvasFileReceiver(canvasItem); - - return SafeWrapperResult.SUCCESS; - } - - #endregion - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - if (_isFilesystemWatcherReady && _filesystemChangeWatcher != null) - { - _filesystemChangeWatcher.OnChangeRegisteredEvent -= FilesystemChangeWatcher_OnChangeRegisteredEvent; - _filesystemChangeWatcher.Dispose(); - } - - this.InteractableCanvasControlModel?.Dispose(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/MarkdownCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/MarkdownCanvasViewModel.cs deleted file mode 100644 index e80127d2..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/MarkdownCanvasViewModel.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.Contexts.Operations; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public class MarkdownCanvasViewModel : BaseCanvasViewModel - { - #region Public Properties - - private MarkdownPasteModel MarkdownPasteModel => canvasPasteModel as MarkdownPasteModel; - - public static List Extensions => new List() { - ".md", ".markdown", - }; - - private string _MarkdownText; - public string MarkdownText - { - get => MarkdownPasteModel?.MarkdownText ?? _MarkdownText; - } - - #endregion - - #region Constructor - - public MarkdownCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - this._MarkdownText = text; - - return text; - } - - protected override async Task TryFetchDataToView() - { - OnPropertyChanged(nameof(MarkdownText)); - - return await Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override IPasteModel SetCanvasPasteModel() - { - return new MarkdownPasteModel(CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - } - - public override Task SetDataToDataPackage(DataPackage data) - { - data.SetText(MarkdownText); - - return Task.FromResult(true); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/MediaCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/MediaCanvasViewModel.cs deleted file mode 100644 index 98cb0223..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/MediaCanvasViewModel.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.Media.Core; -using System.Threading; -using Windows.Storage; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Contexts.Operations; -using System.IO; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public class MediaCanvasViewModel : BaseCanvasViewModel - { - private bool _webViewNeedsUpdate; - - private bool _webViewLoaded; - - #region Properties - - private MediaContentType MediaContentType => ContentType as MediaContentType; - - private MediaPasteModel MediaPasteModel => canvasPasteModel as MediaPasteModel; - - private TimeSpan Position - { - get => ControlView.Position; - set => ControlView.Position = value; - } - - private bool IsLoopingEnabled - { - get => ControlView.IsLoopingEnabled; - set => ControlView.IsLoopingEnabled = value; - } - - private double Volume - { - get => ControlView.Volume; - set => ControlView.Volume = value; - } - - public static List Extensions = new List() { - // Video - ".mp4", ".webm", ".ogg", ".mov", ".qt", ".mp4", ".m4v", ".mp4v", ".3g2", ".3gp2", ".3gp", ".3gpp", ".mkv", - // Audio - ".mp3", ".m4a", ".wav", ".wma", ".aac", ".adt", ".adts", ".cda", - }; - - public static List AudioExtensions = new List() - { - // Audio - ".mp3", ".m4a", ".wav", ".wma", ".aac", ".adt", ".adts", ".cda", - }; - - private MediaSource _ContentMedia; - public MediaSource ContentMedia - { - get => _ContentMedia; - set => SetProperty(ref _ContentMedia, value); - } - - private bool _ContentMediaLoad; - public bool ContentMediaLoad - { - get => _ContentMediaLoad; - set => SetProperty(ref _ContentMediaLoad, value); - } - - private bool _ContentWebViewLoad; - public bool ContentWebViewLoad - { - get => _ContentWebViewLoad; - set => SetProperty(ref _ContentWebViewLoad, value); - } - - public IMediaCanvasControlView ControlView { get; set; } - - #endregion - - #region Constructor - - public MediaCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - public override async Task TryLoadExistingData(CanvasItem canvasItem, BaseContentTypeModel contentType, CancellationToken cancellationToken) - { - SafeWrapperResult result = await base.TryLoadExistingData(canvasItem, contentType, cancellationToken); - - if (result) - { - UpdateMediaControl(); - } - - return result; - } - - protected override Task SetDataFromExistingItem(IStorageItem item) - { - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override async Task TryFetchDataToView() - { - ContentWebViewLoad = true; - ContentMediaLoad = true; - //ContentMedia = MediaSource.CreateFromStorageFile(await SourceFile); - - if (!_webViewLoaded) - { - _webViewNeedsUpdate = true; - } - else - { - await UpdateWebViewContent(true); - } - - return SafeWrapperResult.SUCCESS; - } - - protected override async Task OnReferencePasted() - { - await base.OnReferencePasted(); - - // Change the source - _ContentMedia = MediaSource.CreateFromStorageFile(await SourceFile); - } - - protected override IPasteModel SetCanvasPasteModel() - { - return new MediaPasteModel(CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - } - - #endregion - - #region Public Helpers - - public async Task NotifyWebViewLoaded() - { - _webViewLoaded = true; - - await UpdateWebViewContent(); - } - - private async Task UpdateWebViewContent(bool force = false) - { - if (_webViewLoaded && (_webViewNeedsUpdate || force)) - { - string ext = Path.GetExtension((await SourceFile).Path).ToLower(); - if (AudioExtensions.Contains(ext)) - { - await ControlView.LoadFromAudio(await SourceFile); - } - else - { - await ControlView.LoadFromMedia(await SourceFile); - } - } - } - - public void UpdateMediaControl() - { - if (ControlView != null && MediaContentType != null) - { - this.Position = MediaContentType.savedPosition; - this.IsLoopingEnabled = CanvasSettings.MediaCanvas_IsLoopingEnabled; - this.Volume = CanvasSettings.MediaCanvas_UniversalVolume; - } - } - - #endregion - - #region IDisposable - - public override void Dispose() - { - if (ControlView != null && ContentMediaLoad) - { - if (collectionItemViewModel?.ContentType is MediaContentType mediaContentType) - { - mediaContentType.savedPosition = Position; - } - - CanvasSettings.MediaCanvas_IsLoopingEnabled = IsLoopingEnabled; - CanvasSettings.MediaCanvas_UniversalVolume = Volume; - } - - base.Dispose(); - - ContentMedia?.Dispose(); - ControlView?.Dispose(); - ContentMediaLoad = false; - ContentMedia = null; - ContentWebViewLoad = false; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/TextCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/TextCanvasViewModel.cs deleted file mode 100644 index 228ce773..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/TextCanvasViewModel.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; -using CommunityToolkit.Mvvm.Input; -using System.Collections.Generic; -using Windows.ApplicationModel.DataTransfer; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.Contexts.Operations; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public class TextCanvasViewModel : BaseCanvasViewModel - { - #region Public Properties - - private TextPasteModel TextPasteModel => canvasPasteModel as TextPasteModel; - - private string _Text; - public string Text - { - get => TextPasteModel?.Text ?? _Text; - } - - public static List Extensions => new List() { - ".txt" - }; - - public ITextCanvasControlView ControlView { get; set; } - - #endregion - - #region Constructor - - public TextCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - this._Text = text; - - return text; - } - - protected override Task TryFetchDataToView() - { - OnPropertyChanged(nameof(Text)); - - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override IPasteModel SetCanvasPasteModel() - { - return new TextPasteModel(CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - } - - protected override void RefreshContextMenuItems() - { - base.RefreshContextMenuItems(); - - // The order is reversed - - // Separator - ContextMenuItems.AddFront(new MenuFlyoutSeparatorViewModel()); - - // Select all - ContextMenuItems.AddFront(new MenuFlyoutItemViewModel() - { - Command = new RelayCommand(() => - { - ControlView?.TextSelectAll(); - RefreshContextMenuItems(); - }), - IconGlyph = "\uE8B3", - Text = "SelectAll".GetLocalized2(), - IsShown = () => (ControlView?.SelectedTextLength ?? 0) < Text.Length - }); - - // Copy selected text - ContextMenuItems.AddFront(new MenuFlyoutItemViewModel() - { - Command = new RelayCommand(() => ControlView?.CopySelectedText()), - IconGlyph = "\uE8C8", - Text = "CopySelectedText".GetLocalized2(), - IsShown = () => ControlView?.IsTextSelected ?? false - }); - } - - public override async Task SetDataToDataPackage(DataPackage data) - { - data.SetStorageItems((await SourceFile).ToListSingle()); - data.SetText(Text); - - return true; - } - - #endregion - - #region Helpers - - public static async Task CanLoadAsText(StorageFile file) - { - // Check if exceeds maximum fileSize or is zero - long fileSize = await file.GetFileSize(); - if (fileSize > Constants.UI.CanvasContent.FALLBACK_TEXTLOAD_MAX_FILESIZE || fileSize == 0L) - { - return false; - } - - try - { - // Check if file is binary - string text = await FilesystemOperations.ReadFileText(file); - if (text?.Contains("\0\0\0\0") ?? true) - { - return false; - } - - return true; - } - catch (Exception ex) - { - Console.WriteLine(ex); - return false; - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/WebViewCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/WebViewCanvasViewModel.cs deleted file mode 100644 index 77e088a1..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasDisplay/WebViewCanvasViewModel.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.Enums; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.CanavsPasteModels; -using ClipboardCanvas.Contexts.Operations; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasDisplay -{ - public class WebViewCanvasViewModel : BaseCanvasViewModel - { - #region Members - - private bool _webViewNeedsUpdate; - - private bool _webViewIsLoaded; - - #endregion - - #region Properties - - private WebViewPasteModel WebViewPasteModel => canvasPasteModel as WebViewPasteModel; - - private WebViewContentType WebViewContentType => ContentType as WebViewContentType; - - public WebViewCanvasMode Mode => WebViewContentType.mode; - - public static List Extensions => new List() { - ".html", ".htm", Constants.FileSystem.WEBSITE_LINK_FILE_EXTENSION, - }; - - private bool _ContentWebViewLoad; - public bool ContentWebViewLoad - { - get => _ContentWebViewLoad; - set => SetProperty(ref _ContentWebViewLoad, value); - } - - private string _HtmlText; - public string TextHtml - { - get => WebViewPasteModel?.HtmlText ?? _HtmlText; - } - - private string _Source; - public string Source - { - get => WebViewPasteModel?.Source ?? _Source; - } - - public IWebViewCanvasControlView ControlView { get; set; } - - #endregion - - #region Constructor - - public WebViewCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - if (Mode == WebViewCanvasMode.ReadWebsite) - { - _Source = text; - } - else - { - _HtmlText = text; - } - - return text; - } - - protected override async Task TryFetchDataToView() - { - ContentWebViewLoad = true; - - if (!_webViewIsLoaded) - { - _webViewNeedsUpdate = true; - } - else - { - if (Mode == WebViewCanvasMode.ReadWebsite) - { - ControlView.NavigateToSource(Source); - } - else - { - ControlView.NavigateToHtml(TextHtml); - } - } - - return await Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override IPasteModel SetCanvasPasteModel() - { - return new WebViewPasteModel(Mode, CanvasItemReceiver ?? AssociatedCollection, new StatusCenterOperationReceiver()); - } - - #endregion - - #region Public Helpers - - public void NotifyWebViewLoaded() - { - _webViewIsLoaded = true; - - if (_webViewNeedsUpdate) - { - _webViewNeedsUpdate = false; - - if (Mode == WebViewCanvasMode.ReadWebsite) - { - ControlView.NavigateToSource(Source); - } - else - { - ControlView.NavigateToHtml(TextHtml); - } - } - } - - #endregion - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - this.ControlView?.Dispose(); - - this.ControlView = null; - this.ContentWebViewLoad = false; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/BaseCanvasPreviewControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/BaseCanvasPreviewControlViewModel.cs deleted file mode 100644 index 3bbd00d7..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/BaseCanvasPreviewControlViewModel.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasPreview -{ - public abstract class BaseCanvasPreviewControlViewModel : BaseReadOnlyCanvasPreviewControlViewModel, ICanvasPreviewModel, IDisposable - { - #region Public Properties - - public Func GetRequestedCanvasTypeFunc; - - #endregion - - #region Events - - public event EventHandler OnPasteInitiatedEvent; - - public event EventHandler OnFileCreatedEvent; - - public event EventHandler OnFileModifiedEvent; - - #endregion - - #region Constructor - - public BaseCanvasPreviewControlViewModel(IBaseCanvasPreviewControlView view) - : base(view) - { - } - - #endregion - - #region ICanvasPreviewModel - - public async Task TryPasteData(DataPackageView dataPackage, CancellationToken cancellationToken) - { - BaseContentTypeModel contentType; - - InfiniteCanvasViewModel infiniteCanvasViewModel = CanvasViewModel as InfiniteCanvasViewModel; - if (GetRequestedCanvasTypeFunc() == CanvasType.InfiniteCanvas || infiniteCanvasViewModel != null) - { - contentType = infiniteCanvasViewModel?.ContentType ?? new InfiniteCanvasContentType(); - } - else - { - contentType = await BaseContentTypeModel.GetContentTypeFromDataPackage(dataPackage); - } - - SafeWrapperResult result = await InitializeViewModelAndPaste(dataPackage, contentType, cancellationToken); - - if (!result) - { - RaiseOnErrorOccurredEvent(this, new ErrorOccurredEventArgs(result, result.Message, contentType)); - } - - return result; - } - - public void OpenNewCanvas() - { - CanvasViewModel?.OpenNewCanvas(); - } - - public async Task> GetSuggestedActions() - { - if (CanvasViewModel == null) - { - return null; - } - - return await CanvasViewModel.GetSuggestedActions(); - } - - #endregion - - #region Protected Helpers - - /// - /// Decide and initialize View Model from data package - /// - /// - /// - protected virtual async Task InitializeViewModelAndPaste(DataPackageView dataPackage, BaseContentTypeModel contentType, CancellationToken cancellationToken) - { - // Decide content type and initialize view model - - // Discard any left over data if we're already pasting to canvas that is filled - if (contentType is not InfiniteCanvasContentType) - { - DiscardData(); - } - - if (contentType is InvalidContentTypeDataModel invalidContentType) - { - return invalidContentType.error; - } - - if (InitializeViewModelFromContentType(contentType)) - { - RaiseOnProgressReportedEvent(this, new ProgressReportedEventArgs(0.0f, contentType)); - SafeWrapperResult result = await CanvasViewModel.TryPasteData(dataPackage, cancellationToken); - RaiseOnProgressReportedEvent(this, new ProgressReportedEventArgs(100.0f, contentType)); - - return result; - } - else - { - return new SafeWrapperResult(OperationErrorCode.AccessUnauthorized, null, "Cannot paste data."); - } - } - - #endregion - - #region Event Handlers - - private void CanvasViewModel_OnPasteInitiatedEvent(object sender, PasteInitiatedEventArgs e) - { - RaiseOnPasteInitiatedEvent(sender, e); - } - - private void CanvasViewModel_OnFileCreatedEvent(object sender, FileCreatedEventArgs e) - { - OnFileCreatedEvent(sender, e); - } - - private void CanvasViewModel_OnFileModifiedEvent(object sender, FileModifiedEventArgs e) - { - RaiseOnFileModifiedEvent(sender, e); - } - - #endregion - - #region Event Raisers - - protected void RaiseOnPasteInitiatedEvent(object s, PasteInitiatedEventArgs e) => OnPasteInitiatedEvent?.Invoke(s, e); - - protected void RaiseOnFileCreatedEvent(object s, FileCreatedEventArgs e) => OnFileCreatedEvent?.Invoke(s, e); - - protected void RaiseOnFileModifiedEvent(object s, FileModifiedEventArgs e) => OnFileModifiedEvent?.Invoke(s, e); - - #endregion - - #region Override - - protected override void HookCanvasViewModelEvents() - { - base.HookCanvasViewModelEvents(); - - if (CanvasViewModel != null) - { - CanvasViewModel.OnPasteInitiatedEvent += CanvasViewModel_OnPasteInitiatedEvent; - CanvasViewModel.OnFileCreatedEvent += CanvasViewModel_OnFileCreatedEvent; - CanvasViewModel.OnFileModifiedEvent += CanvasViewModel_OnFileModifiedEvent; - } - } - - protected override void UnhookCanvasViewModelEvents() - { - base.UnhookCanvasViewModelEvents(); - - if (CanvasViewModel != null) - { - CanvasViewModel.OnPasteInitiatedEvent -= CanvasViewModel_OnPasteInitiatedEvent; - CanvasViewModel.OnFileCreatedEvent -= CanvasViewModel_OnFileCreatedEvent; - CanvasViewModel.OnFileModifiedEvent -= CanvasViewModel_OnFileModifiedEvent; - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/BaseReadOnlyCanvasPreviewControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/BaseReadOnlyCanvasPreviewControlViewModel.cs deleted file mode 100644 index b6ed5d3d..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/BaseReadOnlyCanvasPreviewControlViewModel.cs +++ /dev/null @@ -1,349 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using System; -using System.Threading; -using System.Collections.ObjectModel; -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.CanvasFileReceivers; -using Windows.ApplicationModel.DataTransfer; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasPreview -{ - public abstract class BaseReadOnlyCanvasPreviewControlViewModel : ObservableObject, - IReadOnlyCanvasPreviewModel, - IDisposable - where TBaseViewModel : BaseReadOnlyCanvasViewModel - { - #region Protected Members - - protected ICollectionModel CollectionModel => view?.CollectionModel; - - protected CollectionItemViewModel collectionItemViewModel; - - protected readonly IBaseCanvasPreviewControlView view; - - protected IStorageItem AssociatedItem => collectionItemViewModel.AssociatedItem; - - protected readonly SafeWrapperResult CanvasNullResult = new SafeWrapperResult(OperationErrorCode.InvalidArgument, new NullReferenceException(), "Invalid Canvas."); - - #endregion - - #region Public Properties - - private TBaseViewModel _CanvasViewModel; - public TBaseViewModel CanvasViewModel - { - get => _CanvasViewModel; - set => SetProperty(ref _CanvasViewModel, value); - } - - public bool IsContentLoaded => CanvasViewModel?.IsContentLoaded ?? false; - - public ICanvasItemReceiverModel CanvasItemReceiver - { - get => CanvasViewModel?.CanvasItemReceiver; - set => CanvasViewModel.CanvasItemReceiver = value; - } - - public ObservableCollection ContextMenuItems => CanvasViewModel?.ContextMenuItems; - - #endregion - - #region Static Members - - public static CancellationTokenSource CanvasPasteCancellationTokenSource = new CancellationTokenSource(); - - #endregion - - #region Events - - public event EventHandler OnContentStartedLoadingEvent; - - public event EventHandler OnContentLoadedEvent; - - public event EventHandler OnContentLoadFailedEvent; - - public event EventHandler OnFileDeletedEvent; - - public event EventHandler OnErrorOccurredEvent; - - public event EventHandler OnTipTextUpdateRequestedEvent; - - public event EventHandler OnProgressReportedEvent; - - #endregion - - #region Constructor - - public BaseReadOnlyCanvasPreviewControlViewModel(IBaseCanvasPreviewControlView view) - { - this.view = view; - } - - #endregion - - #region IReadOnlyCanvasPreviewModel - - public virtual async Task TryLoadExistingData(CollectionItemViewModel collectionItem, CancellationToken cancellationToken) - { - this.collectionItemViewModel = collectionItem; - - SafeWrapper result = await InitializeViewModelFromCollectionItem(collectionItem, collectionItem.ContentType); - collectionItem.ContentType = result.Result; - - if (result && CanvasViewModel != null) - { - return await CanvasViewModel.TryLoadExistingData(collectionItem, cancellationToken); - } - else - { - OnErrorOccurredEvent?.Invoke(this, new ErrorOccurredEventArgs(result, result.Message, result.Result)); - return result; - } - } - - public virtual async Task TryLoadExistingData(CanvasItem canvasFile, BaseContentTypeModel contentType, CancellationToken cancellationToken) - { - contentType = await BaseContentTypeModel.GetContentType(canvasFile, contentType); - - SafeWrapperResult result = await InitializeViewModelFromCollectionItem(canvasFile, contentType); - - if (result && CanvasViewModel != null) - { - return await CanvasViewModel.TryLoadExistingData(canvasFile, contentType, cancellationToken); - } - else - { - OnErrorOccurredEvent?.Invoke(this, new ErrorOccurredEventArgs(result, result.Message, contentType)); - return result; - } - } - - public virtual async Task TryDeleteData(bool hideConfirmation = false) - { - if (CanvasViewModel == null) - { - // The canvas is null, delete the reference file manually - SafeWrapperResult result = await CanvasHelpers.DeleteCanvasFile(CanvasItemReceiver ?? CollectionModel, collectionItemViewModel, hideConfirmation); - - if (result != OperationErrorCode.Canceled && !result) - { - OnErrorOccurredEvent?.Invoke(this, new ErrorOccurredEventArgs(result, result?.Message, CanvasViewModel.ContentType)); - return result; - } - else if (result != OperationErrorCode.Canceled) - { - OnFileDeletedEvent?.Invoke(this, new FileDeletedEventArgs(AssociatedItem, CollectionModel)); - } - - return result; - } - else - { - return await CanvasViewModel.TryDeleteData(hideConfirmation); - } - } - - public virtual void DiscardData() - { - CanvasViewModel?.DiscardData(); - } - - public virtual async Task SetDataToDataPackage(DataPackage data) - { - if (CanvasViewModel == null) - { - return false; - } - - return await CanvasViewModel.SetDataToDataPackage(data); - } - - public virtual async Task CopyData() - { - if (CanvasViewModel == null) - { - return false; - } - - return await CanvasViewModel.CopyData(); - } - - public virtual async Task> PasteOverrideReference() - { - if (CanvasViewModel == null) - { - return (null, CanvasNullResult); - } - - return await CanvasViewModel.PasteOverrideReference(); - } - - #endregion - - #region Protected Helpers - - protected virtual async Task> InitializeViewModelFromCollectionItem(CanvasItem canvasFile, BaseContentTypeModel contentType) - { - // Clear leftover data - DiscardData(); - - // TODO: Add support for adding previews from extensions - - // Decide content type - contentType = await BaseContentTypeModel.GetContentType(canvasFile, contentType); - - // Check if contentType is InvalidContentTypeDataModel - if (contentType is InvalidContentTypeDataModel invalidContentType) - { - return (contentType, invalidContentType.error); - } - - return (contentType, InitializeViewModelFromContentType(contentType) ? SafeWrapperResult.SUCCESS : new SafeWrapperResult(OperationErrorCode.InvalidOperation, new InvalidOperationException(), "Couldn't display content for this file")); - } - - protected abstract bool InitializeViewModelFromContentType(BaseContentTypeModel contentType); - - protected bool InitializeViewModelForType(BaseContentTypeModel contentType, Func initializer) - where TContentType : BaseContentTypeModel - where TViewModel : TBaseViewModel - { - if (contentType is TContentType) - { - return InitializeViewModel(initializer); - } - - return false; - } - - protected bool InitializeViewModel(Func initializer) - where TViewModel : TBaseViewModel - { - if (CanvasViewModel is TViewModel) // Reuse View Model - { - return true; - } - else // Initialize new View Model - { - UnhookCanvasViewModelEvents(); - CanvasViewModel = initializer(); - HookCanvasViewModelEvents(); - - return true; - } - } - - #endregion - - #region Event Handlers - - private void CanvasViewModel_OnContentStartedLoadingEvent(object sender, ContentStartedLoadingEventArgs e) - { - RaiseOnContentStartedLoadingEvent(sender, e); - } - - private void CanvasViewModel_OnContentLoadedEvent(object sender, ContentLoadedEventArgs e) - { - RaiseOnContentLoadedEvent(sender, e); - } - - private void CanvasViewModel_OnContentLoadFailedEvent(object sender, ErrorOccurredEventArgs e) - { - RaiseOnContentLoadFailedEvent(sender, e); - } - - private void CanvasViewModel_OnFileDeletedEvent(object sender, FileDeletedEventArgs e) - { - RaiseOnFileDeletedEvent(sender, e); - } - - private void CanvasViewModel_OnErrorOccurredEvent(object sender, ErrorOccurredEventArgs e) - { - RaiseOnErrorOccurredEvent(sender, e); - } - - private void CanvasViewModel_OnTipTextUpdateRequestedEvent(object sender, TipTextUpdateRequestedEventArgs e) - { - RaiseOnTipTextUpdateRequestedEvent(sender, e); - } - - private void CanvasViewModel_OnProgressReportedEvent(object sender, ProgressReportedEventArgs e) - { - RaiseOnProgressReportedEvent(sender, e); - } - - #endregion - - #region Event Raisers - - protected void RaiseOnContentStartedLoadingEvent(object s, ContentStartedLoadingEventArgs e) => OnContentStartedLoadingEvent?.Invoke(s, e); - - protected void RaiseOnContentLoadedEvent(object s, ContentLoadedEventArgs e) => OnContentLoadedEvent?.Invoke(s, e); - - protected void RaiseOnContentLoadFailedEvent(object s, ErrorOccurredEventArgs e) => OnContentLoadFailedEvent?.Invoke(s, e); - - protected void RaiseOnFileDeletedEvent(object s, FileDeletedEventArgs e) => OnFileDeletedEvent?.Invoke(s, e); - - protected void RaiseOnErrorOccurredEvent(object s, ErrorOccurredEventArgs e) => OnErrorOccurredEvent?.Invoke(s, e); - - protected void RaiseOnTipTextUpdateRequestedEvent(object s, TipTextUpdateRequestedEventArgs e) => OnTipTextUpdateRequestedEvent?.Invoke(s, e); - - protected void RaiseOnProgressReportedEvent(object s, ProgressReportedEventArgs e) => OnProgressReportedEvent?.Invoke(s, e); - - #endregion - - #region Event Hooks - - protected virtual void HookCanvasViewModelEvents() - { - if (CanvasViewModel != null) - { - CanvasViewModel.OnContentStartedLoadingEvent += CanvasViewModel_OnContentStartedLoadingEvent; - CanvasViewModel.OnContentLoadedEvent += CanvasViewModel_OnContentLoadedEvent; - CanvasViewModel.OnContentLoadFailedEvent += CanvasViewModel_OnContentLoadFailedEvent; - CanvasViewModel.OnFileDeletedEvent += CanvasViewModel_OnFileDeletedEvent; - CanvasViewModel.OnErrorOccurredEvent += CanvasViewModel_OnErrorOccurredEvent; - CanvasViewModel.OnTipTextUpdateRequestedEvent += CanvasViewModel_OnTipTextUpdateRequestedEvent; - CanvasViewModel.OnProgressReportedEvent += CanvasViewModel_OnProgressReportedEvent; - } - } - - protected virtual void UnhookCanvasViewModelEvents() - { - if (CanvasViewModel != null) - { - CanvasViewModel.OnContentStartedLoadingEvent -= CanvasViewModel_OnContentStartedLoadingEvent; - CanvasViewModel.OnContentLoadedEvent -= CanvasViewModel_OnContentLoadedEvent; - CanvasViewModel.OnContentLoadFailedEvent -= CanvasViewModel_OnContentLoadFailedEvent; - CanvasViewModel.OnFileDeletedEvent -= CanvasViewModel_OnFileDeletedEvent; - CanvasViewModel.OnErrorOccurredEvent -= CanvasViewModel_OnErrorOccurredEvent; - CanvasViewModel.OnTipTextUpdateRequestedEvent -= CanvasViewModel_OnTipTextUpdateRequestedEvent; - CanvasViewModel.OnProgressReportedEvent -= CanvasViewModel_OnProgressReportedEvent; - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - UnhookCanvasViewModelEvents(); - CanvasViewModel?.Dispose(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/CanvasPreviewControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/CanvasPreviewControlViewModel.cs deleted file mode 100644 index 345d1fb0..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/CanvasPreviewControlViewModel.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using System.Threading; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasPreview -{ - public class CanvasPreviewControlViewModel : BaseCanvasPreviewControlViewModel, IDisposable - { - #region Constructor - - public CanvasPreviewControlViewModel(IBaseCanvasPreviewControlView view) - : base(view) - { - } - - #endregion - - #region Private Helpers - - protected override bool InitializeViewModelFromContentType(BaseContentTypeModel contentType) - { - // Try for infinite canvas - if (InitializeViewModelForType(contentType, () => new InfiniteCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for image - if (InitializeViewModelForType(contentType, () => new ImageCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for text - if (InitializeViewModelForType(contentType, () => new TextCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for media - if (InitializeViewModelForType(contentType, () => new MediaCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for WebView - if (InitializeViewModelForType(contentType, () => new WebViewCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for markdown - if (InitializeViewModelForType(contentType, () => new MarkdownCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for url preview // TODO: Make it url canvas view model - if (InitializeViewModelForType(contentType, () => new TextCanvasViewModel(view, contentType))) - { - return true; - } - - // Try fallback - if (InitializeViewModelForType(contentType, () => new FallbackCanvasViewModel(view, contentType))) - { - return true; - } - - return false; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/SimpleCanvasPreviewControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/SimpleCanvasPreviewControlViewModel.cs deleted file mode 100644 index 34b4d77f..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/CanvasPreview/SimpleCanvasPreviewControlViewModel.cs +++ /dev/null @@ -1,90 +0,0 @@ -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay; -using CommunityToolkit.Mvvm.ComponentModel; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; - -namespace ClipboardCanvas.ViewModels.UserControls.CanvasPreview -{ - public class SimpleCanvasPreviewControlViewModel : BaseReadOnlyCanvasPreviewControlViewModel - { - #region Constructor - - public SimpleCanvasPreviewControlViewModel(IBaseCanvasPreviewControlView view) - : base(view) - { - } - - #endregion - - #region Override - - protected override bool InitializeViewModelFromContentType(BaseContentTypeModel contentType) - { - // Try for infinite canvas - if (InitializeViewModelForType(contentType, () => new ThumbnailSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for image - if (InitializeViewModelForType(contentType, () => new ThumbnailSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for text - if (InitializeViewModelForType(contentType, () => new TextSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for media - if (InitializeViewModelForType(contentType, () => new ThumbnailSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for WebView - if (InitializeViewModelForType(contentType, () => new ThumbnailSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for markdown // TODO: Add simple markdown - if (InitializeViewModelForType(contentType, () => new TextSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try for url preview - if (InitializeViewModelForType(contentType, () => new UrlSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - // Try fallback - if (InitializeViewModelForType(contentType, () => new ThumbnailSimpleCanvasViewModel(view, contentType))) - { - return true; - } - - return false; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Collections/BaseCollectionViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Collections/BaseCollectionViewModel.cs deleted file mode 100644 index 28a6d5b2..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Collections/BaseCollectionViewModel.cs +++ /dev/null @@ -1,947 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; -using System.Windows.Input; -using System.Collections.ObjectModel; -using CommunityToolkit.Mvvm.Input; -using Microsoft.UI.Xaml.Media.Imaging; -using Windows.Storage.Streams; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using Windows.ApplicationModel.DataTransfer; -using Microsoft.UI.Xaml; - -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.EventArguments.Collections; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.Exceptions; -using ClipboardCanvas.Contexts; -using ClipboardCanvas.Services; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; -using ClipboardCanvas.Models.Autopaste; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.CanavsPasteModels; -using Microsoft.UI.Dispatching; -using Windows.System; -using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue; -using CommunityToolkit.WinUI; - -namespace ClipboardCanvas.ViewModels.UserControls.Collections -{ - public abstract class BaseCollectionViewModel : ObservableObject, ICollectionModel, IAutopasteTarget, IDisposable - { - #region Protected Members - - protected readonly SafeWrapperResult CollectionFolderNotFound = new SafeWrapperResult(OperationErrorCode.NotFound, new DirectoryNotFoundException(), "CollectionFolderNotFound".GetLocalized2()); - - protected readonly SafeWrapperResult RestrictedAccessUnauthorized = StaticExceptionReporters.DefaultSafeWrapperExceptionReporter.GetStatusResult(new UnauthorizedAccessException()); - - protected StorageFolder collectionFolder; - - protected CanvasNavigationDirection canvasNavigationDirection; - - protected int currentIndex; - - protected StorageFile iconFile; - - protected bool isFilesystemWatcherReady; - - protected FilesystemChangeWatcher2 filesystemChangeWatcher; - - protected IDialogService DialogService { get; } = Ioc.Default.GetService(); - - protected IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService(); - - protected IAutopasteService AutopasteService { get; } = Ioc.Default.GetService(); - - protected IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - #endregion - - #region Public Properties - - public ObservableCollection CollectionItems { get; protected set; } - - public ICollectionModel CollectionModel => this; - - public SearchContext SearchContext { get; set; } - - public CanvasType AssociatedCanvasType { get; set; } - - public bool IsCollectionAvailable { get; protected set; } - - public virtual bool IsOnNewCanvas => currentIndex == CollectionItems.Count; - - public CollectionItemViewModel CurrentCollectionItemViewModel => CollectionItems.Count == currentIndex ? null : CollectionItems.ElementAtOrDefault(currentIndex); - - public string CollectionPath { get; protected set; } - - public virtual string DisplayName => Path.GetFileName(CollectionPath); - - public string TargetPath => CollectionPath; - - public bool IsCollectionInitialized { get; protected set; } - - protected bool isCanvasInitializing; - public bool IsCollectionInitializing - { - get => isCanvasInitializing; - protected set => SetProperty(ref isCanvasInitializing, value); - } - - protected bool isSelected; - public bool IsSelected - { - get => isSelected; - set => SetProperty(ref isSelected, value); - } - - protected string editBoxText; - public string EditBoxText - { - get => editBoxText; - set => SetProperty(ref editBoxText, value); - } - - protected bool isEditingName; - public bool IsEditingName - { - get => isEditingName; - protected set => SetProperty(ref isEditingName, value); - } - - protected bool editBoxFocus; - public bool EditBoxFocus - { - get => editBoxFocus; - protected set => SetProperty(ref editBoxFocus, value); - } - - protected SafeWrapperResult collectionErrorInfo; - public SafeWrapperResult CollectionErrorInfo - { - get => collectionErrorInfo; - protected set => SetProperty(ref collectionErrorInfo, value); - } - - protected bool errorIconVisibility; - public bool ErrorIconVisibility - { - get => errorIconVisibility; - protected set => SetProperty(ref errorIconVisibility, value); - } - - protected bool usesCustomIcon; - public bool UsesCustomIcon - { - get => usesCustomIcon; - protected set => SetProperty(ref usesCustomIcon, value); - } - - protected bool canBeSetAsAutopasteTarget; - public bool CanBeSetAsAutopasteTarget - { - get => canBeSetAsAutopasteTarget; - protected set => SetProperty(ref canBeSetAsAutopasteTarget, value); - } - - protected BitmapImage customIcon; - public BitmapImage CustomIcon - { - get => customIcon; - protected set => SetProperty(ref customIcon, value); - } - - #endregion - - #region Events - - public event EventHandler OnCollectionOpenRequestedEvent; - - public event EventHandler OnOpenNewCanvasRequestedEvent; - - public event EventHandler OnCanvasLoadFailedEvent; - - public event EventHandler OnGoToHomepageRequestedEvent; - - public event EventHandler OnCollectionErrorRaisedEvent; - - public event EventHandler OnCollectionItemsInitializationStartedEvent; - - public event EventHandler OnCollectionItemsInitializationFinishedEvent; - - public event EventHandler OnTipTextUpdateRequestedEvent; - - public event EventHandler OnCollectionItemAddedEvent; - - public event EventHandler OnCollectionItemRemovedEvent; - - public event EventHandler OnCollectionItemRenamedEvent; - - public event EventHandler OnCollectionItemContentsChangedEvent; - - #endregion - - #region Commands - - public ICommand OpenCollectionCommand { get; protected set; } - - public ICommand OpenCollectionLocationCommand { get; protected set; } - - public ICommand SetAsAutopasteTargetCommand { get; private set; } - - public ICommand ChangeCollectionIconCommand { get; protected set; } - - public ICommand RemoveCollectionIconCommand { get; protected set; } - - public ICommand ReloadCollectionCommand { get; protected set; } - - public ICommand StartRenameCollectionCommand { get; protected set; } - - public ICommand RenameBoxKeyDownCommand { get; protected set; } - - public ICommand RenameBoxLostFocusCommand { get; protected set; } - - public ICommand RemoveCollectionCommand { get; protected set; } - - #endregion - - #region Constructor - - public BaseCollectionViewModel(StorageFolder collectionFolder) - : this(collectionFolder, null) - { - } - - public BaseCollectionViewModel(string collectionPath) - : this(null, collectionPath) - { - } - - public BaseCollectionViewModel(StorageFolder collectionFolder, string collectionPath) - { - this.collectionFolder = collectionFolder; - if (!string.IsNullOrEmpty(collectionPath)) - { - this.CollectionPath = collectionPath; - } - else - { - this.CollectionPath = collectionFolder?.Path; - } - - this.CollectionItems = new ObservableCollection(); - this.AssociatedCanvasType = CanvasHelpers.GetDefaultCanvasType(); - - // Create commands - OpenCollectionCommand = new RelayCommand(OpenCollection); - OpenCollectionLocationCommand = new AsyncRelayCommand(OpenCollectionLocation); - SetAsAutopasteTargetCommand = new RelayCommand(SetAsAutopasteTarget); - ChangeCollectionIconCommand = new AsyncRelayCommand(ChangeCollectionIcon); - RemoveCollectionIconCommand = new AsyncRelayCommand(RemoveCollectionIcon); - ReloadCollectionCommand = new AsyncRelayCommand(ReloadCollection); - } - - #endregion - - #region Command Implementation - - private void OpenCollection() - { - OnCollectionOpenRequestedEvent?.Invoke(this, new CollectionOpenRequestedEventArgs(this)); - } - - private async Task OpenCollectionLocation() - { - if (!IsCollectionAvailable) - { - return; - } - - await Launcher.LaunchFolderAsync(collectionFolder); - } - - private void SetAsAutopasteTarget() - { - AutopasteService.UpdateAutopasteTarget(this); - } - - private async Task ChangeCollectionIcon() - { - string errorMessage = "CouldNotSetCollectionIcon".GetLocalized2(); - - StorageFile pickedIcon = await DialogService.PickSingleFile(new List() { ".png", ".jpg", ".jpeg"/*, ".gif", ".svg"*/ }); - if (pickedIcon != null) - { - // If already has an icon... - if (UsesCustomIcon && this.iconFile != null) - { - SafeWrapperResult result = await FilesystemOperations.DeleteItem(this.iconFile); - - if (!result) - { - PushErrorNotification("CouldNotDeleteCollectionIcon".GetLocalized2(), result); - } - } - - SafeWrapper iconsFolder = await StorageHelpers.GetCollectionIconsFolder(); - if (!iconsFolder) - { - PushErrorNotification(errorMessage, iconsFolder); - return; - } - - SafeWrapper iconFile = await FilesystemOperations.CreateFile(iconsFolder, pickedIcon.Name); - if (!iconFile) - { - PushErrorNotification(errorMessage, iconFile); - return; - } - this.iconFile = iconFile.Result; - - SafeWrapperResult copyResult = await FilesystemOperations.CopyFileAsync(pickedIcon, this.iconFile, null); // TODO: In the future, add StatusCenter - StatusCenter.CreateNewOperation().OperationContext; - if (!copyResult) - { - PushErrorNotification(errorMessage, copyResult); - return; - } - - SafeWrapperResult setIconResult = await InitializeIconIfSet(this.iconFile); - if (!setIconResult) - { - PushErrorNotification(errorMessage, setIconResult); - return; - } - - // Serialize again because icon was updated - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - } - } - - public async Task RemoveCollectionIcon() - { - if (UsesCustomIcon && iconFile != null) - { - SafeWrapperResult result = await FilesystemOperations.DeleteItem(iconFile); - - if (!result) - { - if (result != OperationErrorCode.NotFound) // Only if it wasn't NotFound -- if it was, continue as usual - { - PushErrorNotification("CouldNotRemoveCollectionIcon".GetLocalized2(), result); - return; - } - } - - iconFile = null; - CustomIcon = null; - UsesCustomIcon = false; - - // Serialize again because icon was updated - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - } - } - - private async Task ReloadCollection() - { - await InitializeCollectionFolder(); - await InitializeCollectionItems(); - } - - #endregion - - #region ICollectionModel - - public async Task> CreateNewCanvasFolder(string folderName = null) - { - if (string.IsNullOrEmpty(folderName)) - { - folderName = DateTime.Now.ToString(Constants.FileSystem.CANVAS_FILE_FILENAME_DATE_FORMAT); - } - - SafeWrapper folder = await FilesystemOperations.CreateFolder(collectionFolder, folderName); - - CollectionItemViewModel collectionItem = null; - if (folder) - { - collectionItem = new CollectionItemViewModel(folder.Result); - AddCollectionItem(collectionItem); - } - - return (collectionItem, folder.Details); - } - - public async Task> CreateNewCanvasItem(string fileName) - { - var result = await CreateNewCollectionItem(fileName); - - return (result.Result, result.Details); - } - - public async Task> CreateNewCanvasItemFromExtension(string extension) - { - var result = await CreateNewCollectionItemFromExtension(extension); - - return (result.Result, result.Details); - } - - public async Task DeleteItem(IStorageItem itemToDelete, bool permanently) - { - return await DeleteCollectionItem(FindCollectionItem(itemToDelete), permanently); - } - - public async Task> CreateNewCollectionItemFromExtension(string extension) - { - string fileName = DateTime.Now.ToString(Constants.FileSystem.CANVAS_FILE_FILENAME_DATE_FORMAT); - fileName = $"{fileName}{extension}"; - - return await CreateNewCollectionItem(fileName); - } - - public async Task> CreateNewCollectionItem(string fileName) - { - if (collectionFolder == null) - { - return new SafeWrapper(null, CollectionFolderNotFound); - } - - SafeWrapper file = await FilesystemOperations.CreateFile(collectionFolder, fileName); - - CollectionItemViewModel collectionItem = null; - if (file) - { - collectionItem = new CollectionItemViewModel(file.Result); - AddCollectionItem(collectionItem); - } - - return (collectionItem, file.Details); - } - - public async Task DeleteCollectionItem(CollectionItemViewModel itemToDelete, bool permanently = true) - { - SafeWrapperResult result = await FilesystemOperations.DeleteItem(itemToDelete?.AssociatedItem, permanently); - - if (result) - { - RemoveCollectionItem(itemToDelete); - } - - return result; - } - - public CollectionItemViewModel FindCollectionItem(CanvasItem canvasItem) - { - return FindCollectionItem(canvasItem.AssociatedItem); - } - - public CollectionItemViewModel FindCollectionItem(IStorageItem storageItem) - { - return FindCollectionItem(storageItem.Path); - } - - public CollectionItemViewModel FindCollectionItem(string path) - { - return CollectionItems.FirstOrDefault((item) => item?.AssociatedItem.Path == path); - } - - public virtual void NavigateFirst(ICanvasPreviewModel pasteCanvasModel) - { - SetIndexOnNewCanvas(); - canvasNavigationDirection = CanvasNavigationDirection.Forward; - - OnOpenNewCanvasRequestedEvent?.Invoke(this, new OpenNewCanvasRequestedEventArgs()); - } - - public virtual async Task NavigateNext(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken) - { - currentIndex++; - canvasNavigationDirection = CanvasNavigationDirection.Forward; - - if (currentIndex == CollectionItems.Count) - { - // Open new canvas if _currentIndex exceeds the _items size - OnOpenNewCanvasRequestedEvent?.Invoke(this, new OpenNewCanvasRequestedEventArgs()); - } - else - { - // Otherwise, load existing data from file - await LoadCanvasFromCollection(pasteCanvasModel, cancellationToken); - } - } - - public virtual async Task NavigateLast(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken) - { - currentIndex = 0; - canvasNavigationDirection = CanvasNavigationDirection.Backward; - - await LoadCanvasFromCollection(pasteCanvasModel, cancellationToken); - } - - public virtual async Task NavigateBack(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken) - { - currentIndex--; - canvasNavigationDirection = CanvasNavigationDirection.Backward; - - await LoadCanvasFromCollection(pasteCanvasModel, cancellationToken); - } - - public virtual void AddCollectionItem(CollectionItemViewModel collectionItemViewModel, bool fromInit = false) - { - if (!fromInit) - { - OnCollectionItemAddedEvent?.Invoke(this, new CollectionItemAddedEventArgs(this, collectionItemViewModel)); - } - CollectionItems.Add(collectionItemViewModel); - } - - public virtual void RemoveCollectionItem(CollectionItemViewModel collectionItemViewModel) - { - if (collectionItemViewModel != null) - { - OnCollectionItemRemovedEvent?.Invoke(this, new CollectionItemRemovedEventArgs(this, collectionItemViewModel)); - CollectionItems.Remove(collectionItemViewModel); - } - } - - public virtual bool HasNext() - { - return currentIndex < CollectionItems.Count; - } - - public virtual bool HasBack() - { - return currentIndex > 0; - } - - public virtual void SetIndexOnNewCanvas() - { - currentIndex = CollectionItems.Count; - } - - public virtual void UpdateIndex(CollectionItemViewModel collectionItemViewModel) - { - int newIndex = -1; - - if (collectionItemViewModel != null) - { - newIndex = CollectionItems.IndexOf(collectionItemViewModel); - } - - if (newIndex == -1) - { - SetIndexOnNewCanvas(); - } - else - { - currentIndex = newIndex; - } - } - - public bool IsOnOpenedCanvas(CollectionItemViewModel collectionItemViewModel) - { - int indexOfRequestedItemViewModel = CollectionItems.IndexOf(collectionItemViewModel); - - return indexOfRequestedItemViewModel == currentIndex; - } - - public abstract bool CheckCollectionAvailability(); - - public virtual CollectionConfigurationModel ConstructConfigurationModel() - { - return new CollectionConfigurationModel(CollectionPath, UsesCustomIcon, iconFile?.Name); - } - - public virtual async Task LoadCanvasFromCollection(ICanvasPreviewModel pasteCanvasModel, CancellationToken cancellationToken, CollectionItemViewModel collectionItemViewModel = null) - { - // You can only load existing data - if (CollectionItems.IsEmpty() || (canvasNavigationDirection == CanvasNavigationDirection.Forward && (IsOnNewCanvas && collectionItemViewModel == null))) - { - OnOpenNewCanvasRequestedEvent?.Invoke(this, new OpenNewCanvasRequestedEventArgs()); - return SafeWrapperResult.SUCCESS; - } - else - { - currentIndex = Extensions.CollectionExtensions.IndexFitBounds(CollectionItems.Count, currentIndex); - - if (collectionItemViewModel == null) - { - collectionItemViewModel = CollectionItems[currentIndex]; - } - else - { - int providedCollectionItemModelIndex = CollectionItems.IndexOf(collectionItemViewModel); - currentIndex = providedCollectionItemModelIndex; - } - - SafeWrapperResult result = await pasteCanvasModel.TryLoadExistingData(collectionItemViewModel, cancellationToken); - - if (result == OperationErrorCode.NotFound && result.Exception is not ReferencedFileNotFoundException) // A canvas is missing, meaning we need to reload all other items - { - if (!StorageHelpers.Existsh(CollectionPath)) - { - SetCollectionError(CollectionFolderNotFound); - - // TODO: Pass error code here in the future - OnGoToHomepageRequestedEvent?.Invoke(this, new GoToHomepageRequestedEventArgs()); - return result; - } - - // We must reload items because some were missing - OnTipTextUpdateRequestedEvent?.Invoke(this, new TipTextUpdateRequestedEventArgs("CollectionItemsMissing".GetLocalized2(), TimeSpan.FromMilliseconds(Constants.UI.CanvasContent.COLLECTION_RELOADING_TIP_DELAY))); - await InitializeCollectionItems(); - - if (canvasNavigationDirection == CanvasNavigationDirection.Forward) - { - if (!HasNext()) - { - // Doesn't have next, so we're on new canvas - open new canvas - OnOpenNewCanvasRequestedEvent?.Invoke(this, new OpenNewCanvasRequestedEventArgs()); - } - else - { - currentIndex++; - } - } - else - { - if (HasBack()) - { - currentIndex--; - } - } - - if (CollectionItems.IsEmpty()) - { - OnOpenNewCanvasRequestedEvent?.Invoke(this, new OpenNewCanvasRequestedEventArgs()); - return SafeWrapperResult.SUCCESS; - } - else - { - int providedCollectionItemModelIndex = CollectionItems.IndexOf(collectionItemViewModel); - if (providedCollectionItemModelIndex != -1) - { - currentIndex = providedCollectionItemModelIndex; - } - - if (currentIndex < CollectionItems.Count) - { - collectionItemViewModel = CollectionItems[currentIndex]; - - // Load canvas again - result = await pasteCanvasModel.TryLoadExistingData(collectionItemViewModel, cancellationToken); - } - } - } - else if (result == OperationErrorCode.InProgress) - { - // Content is still being pasted... - // TODO: Hook event to collectionItemViewModel.OperationContext.OnOperationFinishedEvent - } - else if (result == OperationErrorCode.InvalidOperation) - { - // View Model wasn't found - // Cannot display content for this file. - e.g. canvas display doesn't exists for this file - } - - if (!result) - { - OnCanvasLoadFailedEvent?.Invoke(this, new CanvasLoadFailedEventArgs(result)); - } - - return result; - } - } - - public virtual Task SetupFilesystemWatcher() - { - if (!isFilesystemWatcherReady) - { - isFilesystemWatcherReady = true; - - this.filesystemChangeWatcher = new(collectionFolder.Path); - this.filesystemChangeWatcher.OnChangeRegisteredEvent += FilesystemChangeWatcher_OnChangeRegisteredEvent; - } - - return Task.CompletedTask; - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", - Justification = "")] - private async void FilesystemChangeWatcher_OnChangeRegisteredEvent(object sender, ChangeRegisteredEventArgs2 e) - { - // Issue: items are pasted added to collection twice - return; - try - { - await MainWindow.Instance.DispatcherQueue.EnqueueAsync(async () => - { - if (e.FullPath.EndsWith(".TMP") || e.FullPath.EndsWith("~tmp")) - return; - - // Reflect changes in collection - string itemParentFolder = Path.GetDirectoryName(e.FullPath); - string watchedParentFolder = collectionFolder.Path; - if (itemParentFolder != watchedParentFolder) - return; - - IStorageItem changedItem = await StorageHelpers.ToStorageItem(e.FullPath); - - switch (e.ChangeType) - { - case WatcherChangeTypes.Created: - { - // Add new collection item - if (changedItem != null && !CollectionItems.Any((i) => e.FullPath == i.AssociatedItem.Path)) - { - var collectionItem = new CollectionItemViewModel(changedItem); - AddCollectionItem(collectionItem); - } - - break; - } - - case WatcherChangeTypes.Deleted: - { - // Remove the collection item - var collectionItem = FindCollectionItem(e.FullPath); - RemoveCollectionItem(collectionItem); - break; - } - - case WatcherChangeTypes.Renamed: - { - if (changedItem != null) - { - string oldName = Path.GetFileName(e.OldPath); - string newName = Path.GetFileName(e.FullPath); - - string oldParentPath = Path.GetDirectoryName(e.OldPath); - string newParentPath = Path.GetDirectoryName(e.FullPath); - - if ((oldName != newName) && (oldParentPath == newParentPath)) - { - // Renamed - var collectionItem = FindCollectionItem(e.OldPath); - if (collectionItem is null) - break; - - collectionItem.DangerousUpdateItem(changedItem); - OnCollectionItemRenamedEvent?.Invoke(this, - new CollectionItemRenamedEventArgs(this, collectionItem, - e.OldPath)); - } - } - - break; - } - - case WatcherChangeTypes.Changed: - { - var collectionItem = FindCollectionItem(changedItem?.Path); - if (collectionItem != null) - { - OnCollectionItemContentsChangedEvent?.Invoke(this, - new CollectionItemContentsChangedEventArgs(this, collectionItem)); - } - - break; - } - } - }); - } - catch (Exception ex) - { - // Wrong thread exception bug? - } - } - - public virtual async Task InitializeCollectionItems() - { - if (collectionFolder != null) - { - IsCollectionInitializing = true; - OnCollectionItemsInitializationStartedEvent?.Invoke(this, new CollectionItemsInitializationStartedEventArgs(this)); - - IEnumerable items = await Task.Run(async () => await collectionFolder.GetItemsAsync()); - - await SetupFilesystemWatcher(); - - CollectionItems.Clear(); - if (!items.IsEmpty()) - { - // Sort items from oldest (last canvas) to newest (first canvas) - items = items.OrderBy((x) => x.DateCreated.DateTime); - - // Save indexes for later - int savedIndex = currentIndex; - int savedItemsCount = CollectionItems.Count; - - foreach (var item in items) - { - AddCollectionItem(new CollectionItemViewModel(item), true); - } - - // TODO: save index somewhere to file? - // Calculate new index - int newItemsCount = CollectionItems.Count; - int newIndex = Math.Max(savedIndex, savedIndex - (savedItemsCount - newItemsCount)); - - this.currentIndex = Extensions.CollectionExtensions.IndexFitBounds(this.CollectionItems.Count + 1, newIndex); // Increase the Items.Count by one to account for new canvas being always Items.Count - } - - IsCollectionInitializing = false; - IsCollectionInitialized = true; - OnCollectionItemsInitializationFinishedEvent?.Invoke(this, new CollectionItemsInitializationFinishedEventArgs(this)); - - return true; - } - - IsCollectionInitialized = false; - return false; - } - - public async Task InitializeCollectionFolder() - { - if (!CheckCollectionAvailability()) - { - return false; - } - else - { - SafeWrapper result = await StorageHelpers.ToStorageItemWithError(CollectionPath); - collectionFolder = result; - - if (!result) - { - SetCollectionError(result); - - return false; - } - else - { - return true; - } - } - } - - public async Task InitializeIconIfSet(CollectionConfigurationModel collectionConfiguration) - { - if (collectionConfiguration == null || !collectionConfiguration.usesCustomIcon) - { - return SafeWrapperResult.SUCCESS; - } - - SafeWrapper iconsFolder = await StorageHelpers.GetCollectionIconsFolder(); - if (!iconsFolder) - { - return iconsFolder; - } - - SafeWrapper iconFile = await StorageHelpers.ToStorageItemWithError(Path.Combine(iconsFolder.Result.Path, collectionConfiguration.iconFileName)); - - if (!iconFile) - { - return iconFile; - } - - return await InitializeIconIfSet(iconFile); - } - - public async Task InitializeIconIfSet(StorageFile iconFile) - { - UsesCustomIcon = true; - this.iconFile = iconFile; - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - - return await SafeWrapperRoutines.SafeWrapAsync(async () => - { - using (IRandomAccessStream fileStream = await iconFile.OpenReadAsync()) - { - CustomIcon = await ImagingHelpers.ToBitmapAsync(fileStream); - } - }); - } - - #endregion - - #region IAutopasteTarget - - public async Task> PasteData(DataPackageView dataPackage, CancellationToken cancellationToken) - { - BaseContentTypeModel pastedItemContentType = await BaseContentTypeModel.GetContentTypeFromDataPackage(dataPackage); - - if (pastedItemContentType is InvalidContentTypeDataModel invalidContentType) - { - return (null, invalidContentType.error); - } - - // Get correct IPasteModel from contentType - using IPasteModel canvasPasteModel = CanvasHelpers.GetPasteModelFromContentType(pastedItemContentType, this, new StatusCenterOperationReceiver()); - SafeWrapper canvasItemResult = await canvasPasteModel.PasteData(dataPackage, UserSettingsService.AlwaysPasteFilesAsReference, cancellationToken); - if (canvasItemResult && currentIndex == CollectionItems.Count - 1) // Was on new canvas, item was pasted and is now one behind - set to new canvas - { - SetIndexOnNewCanvas(); - } - - return canvasItemResult; - } - - #endregion - - #region Protected Helpers - - protected virtual void SetCollectionError(SafeWrapperResult safeWrapperResult) - { - if (!safeWrapperResult) - { - CollectionErrorInfo = safeWrapperResult; - ErrorIconVisibility = true; - IsCollectionAvailable = false; - } - else - { - ErrorIconVisibility = false; - IsCollectionAvailable = true; - } - - OnCollectionErrorRaisedEvent?.Invoke(this, new CollectionErrorRaisedEventArgs(safeWrapperResult)); - } - - protected virtual void PushErrorNotification(string errorMessage, SafeWrapperResult result) - { - IInAppNotification notification = DialogService.GetNotification(); - notification.ViewModel.NotificationText = string.Format("CollectionErrorNotificationDescription".GetLocalized2(), errorMessage, result.ErrorCode); - notification.ViewModel.ShownButtons = InAppNotificationButtonType.OkButton; - - notification.Show(Constants.UI.Notifications.NOTIFICATION_DEFAULT_SHOW_TIME); - } - - #endregion - - #region IDisposable - - public virtual void Dispose() - { - if (isFilesystemWatcherReady) - { - filesystemChangeWatcher.OnChangeRegisteredEvent -= FilesystemChangeWatcher_OnChangeRegisteredEvent; - filesystemChangeWatcher.Dispose(); - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Collections/CollectionItemViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Collections/CollectionItemViewModel.cs deleted file mode 100644 index 02973546..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Collections/CollectionItemViewModel.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Windows.Storage; -using System.Threading.Tasks; - -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Contexts.Operations; - -namespace ClipboardCanvas.ViewModels.UserControls.Collections -{ - public class CollectionItemViewModel : CanvasItem - { - public BaseContentTypeModel ContentType { get; set; } - - public OperationContext OperationContext { get; set; } - - public BaseAdditionalData AdditionalData { get; set; } - - public CollectionItemViewModel(IStorageItem item) - : this(item, null) - { - } - - public CollectionItemViewModel(IStorageItem item, BaseContentTypeModel contentType) - : base(item) - { - this.ContentType = contentType; - this.OperationContext = new OperationContext(); - } - - public async Task OpenFile() - { - await StorageHelpers.OpenFile(await SourceItem); - } - - public async Task OpenContainingFolder() - { - await OpenContainingFolder(true); - } - - public async Task OpenContainingFolder(bool checkForReference) - { - if (checkForReference) - { - await StorageHelpers.OpenContainingFolder(await SourceItem); - } - else - { - await StorageHelpers.OpenContainingFolder(AssociatedItem); - } - } - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Collections/CollectionsWidgetViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Collections/CollectionsWidgetViewModel.cs deleted file mode 100644 index b31b310a..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Collections/CollectionsWidgetViewModel.cs +++ /dev/null @@ -1,593 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Input; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; -using Microsoft.UI.Xaml; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.EventArguments.Collections; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Interfaces.Collections; -using ClipboardCanvas.Services; -using ClipboardCanvas.Models; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; - -#nullable enable - -namespace ClipboardCanvas.ViewModels.UserControls.Collections -{ - public class CollectionsWidgetViewModel : ObservableObject, IDisposable - { - #region Private Members - - private static bool s_itemAddedInternally; - - private static int s_internalCollectionsCount; - - #endregion - - #region Properties - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - public static ObservableCollection Collections { get; private set; } = new ObservableCollection(); - - private static BaseCollectionViewModel _CurrentCollection; - public static BaseCollectionViewModel CurrentCollection - { - get => _CurrentCollection; - set - { - if (value != _CurrentCollection) - { - _CurrentCollection = value; - - if (_CurrentCollection != null) - { - // Set selection property - foreach (var item in Collections) - { - item.IsSelected = false; - } - _CurrentCollection.IsSelected = true; - - SettingsSerializationHelpers.UpdateLastSelectedCollectionSetting(_CurrentCollection); - - OnCollectionSelectionChangedEvent?.Invoke(null, new CollectionSelectionChangedEventArgs(value)); - } - } - } - } - - public BaseCollectionViewModel SelectedItem - { - get => CurrentCollection; - set => CurrentCollection = value; - } - - #endregion - - #region Events - - public static event EventHandler OnCollectionOpenRequestedEvent; - - public static event EventHandler OnCollectionSelectionChangedEvent; - - public static event EventHandler OnCollectionRemovedEvent; - - public static event EventHandler OnCollectionAddedEvent; - - // Collection events - - public static event EventHandler OnCollectionItemsInitializationStartedEvent; - - public static event EventHandler OnCollectionItemsInitializationFinishedEvent; - - public static event EventHandler OnOpenNewCanvasRequestedEvent; - - public static event EventHandler OnGoToHomepageRequestedEvent; - - public static event EventHandler OnCollectionErrorRaisedEvent; - - public static event EventHandler OnCanvasLoadFailedEvent; - - public static event EventHandler OnTipTextUpdateRequestedEvent; - - public static event EventHandler OnCollectionItemAddedEvent; - - public static event EventHandler OnCollectionItemRemovedEvent; - - public static event EventHandler OnCollectionItemRenamedEvent; - - public static event EventHandler OnCollectionItemContentsChangedEvent; - - #endregion - - #region Commands - - public ICommand DragOverCommand { get; private set; } - - public ICommand DropCommand { get; private set; } - - #endregion - - #region Constructor - - public CollectionsWidgetViewModel() - { - HookEvents(); - - // Create commands - DragOverCommand = new AsyncRelayCommand(DragOver); - DropCommand = new AsyncRelayCommand(Drop); - } - - #endregion - - #region Command Implementation - - private async Task DragOver(DragEventArgs e) - { - DragOperationDeferral deferral = null; - - try - { - deferral = e.GetDeferral(); - - if (e.DataView.Contains(StandardDataFormats.StorageItems)) - { - SafeWrapper> items = await SafeWrapperRoutines.SafeWrapAsync(async () => - await e.DataView.GetStorageItemsAsync()); - - if (items) - { - if (!items.Result.Any((item) => item is not IStorageFolder)) - { - e.AcceptedOperation = DataPackageOperation.Move; - return; - } - } - } - - e.AcceptedOperation = DataPackageOperation.None; - } - finally - { - e.Handled = true; - deferral?.Complete(); - } - } - - private async Task Drop(DragEventArgs e) - { - DragOperationDeferral deferral = null; - - try - { - deferral = e.GetDeferral(); - - if (ApplicationService.IsInRestrictedAccessMode) - { - IDialogService dialogService = Ioc.Default.GetService(); - - IInAppNotification notification = dialogService.GetNotification(); - notification.ViewModel.NotificationText = "Cannot add collections in Restricted Access mode."; - notification.ViewModel.ShownButtons = Enums.InAppNotificationButtonType.OkButton; - notification.Show(Constants.UI.Notifications.NOTIFICATION_DEFAULT_SHOW_TIME); - - return; - } - - SafeWrapper> items = await SafeWrapperRoutines.SafeWrapAsync(async () => - await e.DataView.GetStorageItemsAsync()); - - if (!items) - { - return; - } - - foreach (var item in items.Result) - { - // We retrieve the folder again this time using ToStorageItem<>() because items received cannot be modified - i.e. Renamed etc. - StorageFolder folder = await StorageHelpers.ToStorageItem(item.Path); - - if (folder != null) - { - StandardCollectionViewModel standardCollectionViewModel = new StandardCollectionViewModel(folder); - await AddCollection(standardCollectionViewModel, null, true); - } - } - - // We need to update saved collections because we suppressed that in AddCollection() - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - } - finally - { - e.Handled = true; - deferral?.Complete(); - } - } - - #endregion - - #region Event Handlers - - private static void Collections_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - if (!s_itemAddedInternally && s_internalCollectionsCount < Collections.Count) - { - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - } - - s_internalCollectionsCount = Collections.Count; - } - - private static async void CollectionRemovable_OnRemoveCollectionRequestedEvent(object sender, RemoveCollectionRequestedEventArgs e) - { - await RemoveCollection(e.baseCollectionViewModel); - } - - private static void CollectionNameEditable_OnCheckRenameCollectionRequestedEvent(object sender, CheckRenameCollectionRequestedEventArgs e) - { - if ( - e.baseCollectionViewModel is ICollectionNameEditable - && !string.IsNullOrWhiteSpace(e.newName) - && !Collections.Any((item) => item.DisplayName == e.newName) - && !e.baseCollectionViewModel.DisplayName.SequenceEqual(e.newName) - ) - { - e.canRename = true; - } - else - { - e.canRename = false; - } - } - - private static void BaseCollectionViewModel_OnCollectionItemContentsChangedEvent(object sender, CollectionItemContentsChangedEventArgs e) - { - OnCollectionItemContentsChangedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionItemRenamedEvent(object sender, CollectionItemRenamedEventArgs e) - { - OnCollectionItemRenamedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionItemRemovedEvent(object sender, CollectionItemRemovedEventArgs e) - { - OnCollectionItemRemovedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionItemAddedEvent(object sender, CollectionItemAddedEventArgs e) - { - OnCollectionItemAddedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnTipTextUpdateRequestedEvent(object sender, TipTextUpdateRequestedEventArgs e) - { - OnTipTextUpdateRequestedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionItemsInitializationFinishedEvent(object sender, CollectionItemsInitializationFinishedEventArgs e) - { - OnCollectionItemsInitializationFinishedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionItemsInitializationStartedEvent(object sender, CollectionItemsInitializationStartedEventArgs e) - { - OnCollectionItemsInitializationStartedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionErrorRaisedEvent(object sender, CollectionErrorRaisedEventArgs e) - { - OnCollectionErrorRaisedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnGoToHomepageRequestedEvent(object sender, GoToHomepageRequestedEventArgs e) - { - OnGoToHomepageRequestedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCanvasLoadFailedEvent(object sender, CanvasLoadFailedEventArgs e) - { - OnCanvasLoadFailedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnOpenNewCanvasRequestedEvent(object sender, OpenNewCanvasRequestedEventArgs e) - { - OnOpenNewCanvasRequestedEvent?.Invoke(sender, e); - } - - private static void BaseCollectionViewModel_OnCollectionOpenRequestedEvent(object sender, CollectionOpenRequestedEventArgs e) - { - OnCollectionOpenRequestedEvent?.Invoke(sender, e); - } - - #endregion - - #region Public Helpers - - public void OpenItem(BaseCollectionViewModel collectionViewModel) - { - OnCollectionOpenRequestedEvent?.Invoke(this, new CollectionOpenRequestedEventArgs(collectionViewModel)); - } - - public static async Task ReloadAllCollections() - { - var collectionsSettings = Ioc.Default.GetService(); - - var collectionConfigurations = collectionsSettings?.SavedCollections; - - // Add default collection - StorageFolder defaultCollectionFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Default Collection", CreationCollisionOption.OpenIfExists); - - if (defaultCollectionFolder == null) - { - Debugger.Break(); // That shouldn't even happen! - throw new UnauthorizedAccessException("The default folder collection couldn't be retrieved!"); - } - - bool defaultCollectionAdded = false; - - collectionConfigurations ??= new(); - if (collectionsSettings != null) - { - collectionsSettings.SavedCollections = collectionConfigurations; - - foreach (var item in collectionConfigurations) - { - BaseCollectionViewModel baseCollection; - - if (!defaultCollectionAdded && - item.collectionPath == Constants.Collections.DEFAULT_COLLECTION_TOKEN) - { - defaultCollectionAdded = true; - baseCollection = new DefaultCollectionViewModel(defaultCollectionFolder); - } - else - { - baseCollection = new StandardCollectionViewModel(item.collectionPath); - } - - await AddCollection(baseCollection, item, true); - } - } - - if (!defaultCollectionAdded) - { - // Add default collection if it hasn't been added (it wasn't found in collections_settings) - await AddCollection(new DefaultCollectionViewModel(defaultCollectionFolder), null, true); - } - - // We need to update saved collections because we suppressed that in AddCollection() - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - - FallbackSetSelectedCollection(); - - OnCollectionItemsInitializationFinishedEvent?.Invoke(null, new CollectionItemsInitializationFinishedEventArgs(CurrentCollection)); - } - - public static void FallbackSetSelectedCollection() - { - string lastSelectedCollection = string.Empty; - try - { - var collectionsSettings = Ioc.Default.GetRequiredService(); - - lastSelectedCollection = collectionsSettings.LastSelectedCollection; - - if (string.IsNullOrWhiteSpace(lastSelectedCollection)) - { - // The last selected collection setting is not set - lastSelectedCollection = Constants.Collections.DEFAULT_COLLECTION_TOKEN; - collectionsSettings.LastSelectedCollection = lastSelectedCollection; - } - } - catch (Exception ex) - { - LoggingHelpers.SafeLogExceptionToFile(ex); - } - - if (lastSelectedCollection == Constants.Collections.DEFAULT_COLLECTION_TOKEN) - { - // Set current collection to default collection - CurrentCollection = Collections.First((item) => item is DefaultCollectionViewModel); - } - else - { - // Find the collection with the matching lastSelectedCollection setting - var baseCollectionViewModel = Collections.SingleOrDefault((item) => item.CollectionPath == lastSelectedCollection); - - if (baseCollectionViewModel != null) - { - CurrentCollection = baseCollectionViewModel; - } - else - { - // Fallback to default collection - CurrentCollection = Collections.First((item) => item is DefaultCollectionViewModel); - } - } - } - - public static BaseCollectionViewModel FindCollection(CollectionConfigurationModel collectionConfigurationModel) - { - return Collections.FirstOrDefault((item) => item.ConstructConfigurationModel().collectionPath == collectionConfigurationModel.collectionPath); - } - - public static BaseCollectionViewModel? FindCollection(string collectionPath) - { - return Collections.FirstOrDefault((item) => item.CollectionPath == collectionPath); - } - - public static async Task AddCollection(BaseCollectionViewModel baseCollectionViewModel, CollectionConfigurationModel configurationModel, bool suppressSettingsUpdate = false) - { - // If collections already contain a collection with the same path - if (Collections.Any((item) => item.CollectionPath == baseCollectionViewModel.CollectionPath)) - { - return false; - } - - // Hook events - baseCollectionViewModel.OnCollectionOpenRequestedEvent += BaseCollectionViewModel_OnCollectionOpenRequestedEvent; - baseCollectionViewModel.OnOpenNewCanvasRequestedEvent += BaseCollectionViewModel_OnOpenNewCanvasRequestedEvent; - baseCollectionViewModel.OnCanvasLoadFailedEvent += BaseCollectionViewModel_OnCanvasLoadFailedEvent; - baseCollectionViewModel.OnGoToHomepageRequestedEvent += BaseCollectionViewModel_OnGoToHomepageRequestedEvent; - baseCollectionViewModel.OnCollectionErrorRaisedEvent += BaseCollectionViewModel_OnCollectionErrorRaisedEvent; - baseCollectionViewModel.OnCollectionItemsInitializationStartedEvent += BaseCollectionViewModel_OnCollectionItemsInitializationStartedEvent; - baseCollectionViewModel.OnCollectionItemsInitializationFinishedEvent += BaseCollectionViewModel_OnCollectionItemsInitializationFinishedEvent; - baseCollectionViewModel.OnTipTextUpdateRequestedEvent += BaseCollectionViewModel_OnTipTextUpdateRequestedEvent; - baseCollectionViewModel.OnCollectionItemAddedEvent += BaseCollectionViewModel_OnCollectionItemAddedEvent; - baseCollectionViewModel.OnCollectionItemRemovedEvent += BaseCollectionViewModel_OnCollectionItemRemovedEvent; - baseCollectionViewModel.OnCollectionItemRenamedEvent += BaseCollectionViewModel_OnCollectionItemRenamedEvent; - baseCollectionViewModel.OnCollectionItemContentsChangedEvent += BaseCollectionViewModel_OnCollectionItemContentsChangedEvent; - - // Hook extension interfaces events - if (baseCollectionViewModel is ICollectionNameEditable collectionNameEditable) - { - collectionNameEditable.OnCheckRenameCollectionRequestedEvent += CollectionNameEditable_OnCheckRenameCollectionRequestedEvent; - } - if (baseCollectionViewModel is ICollectionRemovable collectionRemovable) - { - collectionRemovable.OnRemoveCollectionRequestedEvent += CollectionRemovable_OnRemoveCollectionRequestedEvent; - } - - await baseCollectionViewModel.InitializeCollectionFolder(); - await baseCollectionViewModel.InitializeIconIfSet(configurationModel); - - - s_itemAddedInternally = true; - Collections.Add(baseCollectionViewModel); - s_itemAddedInternally = false; - - OnCollectionAddedEvent?.Invoke(null, new CollectionAddedEventArgs(baseCollectionViewModel)); - - if (!suppressSettingsUpdate) - { - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - } - - return true; - } - - public static async Task RemoveCollection(BaseCollectionViewModel baseCollectionViewModel) - { - if (baseCollectionViewModel is DefaultCollectionViewModel) - { - return; - } - - IAutopasteService autopasteService = Ioc.Default.GetService(); - if (autopasteService.IsAutopasteTarget(baseCollectionViewModel)) - { - // Also reset that collection as a Autopaste target if it was removed - autopasteService.UpdateAutopasteTarget(null); - } - - // Unhook events - baseCollectionViewModel.OnCollectionOpenRequestedEvent -= BaseCollectionViewModel_OnCollectionOpenRequestedEvent; - baseCollectionViewModel.OnOpenNewCanvasRequestedEvent -= BaseCollectionViewModel_OnOpenNewCanvasRequestedEvent; - baseCollectionViewModel.OnCanvasLoadFailedEvent -= BaseCollectionViewModel_OnCanvasLoadFailedEvent; - baseCollectionViewModel.OnGoToHomepageRequestedEvent -= BaseCollectionViewModel_OnGoToHomepageRequestedEvent; - baseCollectionViewModel.OnCollectionErrorRaisedEvent -= BaseCollectionViewModel_OnCollectionErrorRaisedEvent; - baseCollectionViewModel.OnCollectionItemsInitializationStartedEvent -= BaseCollectionViewModel_OnCollectionItemsInitializationStartedEvent; - baseCollectionViewModel.OnCollectionItemsInitializationFinishedEvent -= BaseCollectionViewModel_OnCollectionItemsInitializationFinishedEvent; - baseCollectionViewModel.OnTipTextUpdateRequestedEvent -= BaseCollectionViewModel_OnTipTextUpdateRequestedEvent; - baseCollectionViewModel.OnCollectionItemAddedEvent -= BaseCollectionViewModel_OnCollectionItemAddedEvent; - baseCollectionViewModel.OnCollectionItemRemovedEvent -= BaseCollectionViewModel_OnCollectionItemRemovedEvent; - baseCollectionViewModel.OnCollectionItemRenamedEvent -= BaseCollectionViewModel_OnCollectionItemRenamedEvent; - baseCollectionViewModel.OnCollectionItemContentsChangedEvent -= BaseCollectionViewModel_OnCollectionItemContentsChangedEvent; - - // Unhook extension interfaces events - if (baseCollectionViewModel is ICollectionNameEditable collectionNameEditable) - { - collectionNameEditable.OnCheckRenameCollectionRequestedEvent -= CollectionNameEditable_OnCheckRenameCollectionRequestedEvent; - } - if (baseCollectionViewModel is ICollectionRemovable collectionRemovable) - { - collectionRemovable.OnRemoveCollectionRequestedEvent -= CollectionRemovable_OnRemoveCollectionRequestedEvent; - } - - Collections.Remove(baseCollectionViewModel); - - // Also remove the icon if there was any - await baseCollectionViewModel.RemoveCollectionIcon(); - - baseCollectionViewModel.Dispose(); - - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - FallbackSetSelectedCollection(); - SettingsSerializationHelpers.UpdateLastSelectedCollectionSetting(CurrentCollection); - - OnCollectionRemovedEvent?.Invoke(null, new CollectionRemovedEventArgs(baseCollectionViewModel)); - } - - public static async Task AddCollectionViaUi() - { - IDialogService dialogService = Ioc.Default.GetService(); - IApplicationService applicationService = Ioc.Default.GetService(); - - if (applicationService.IsInRestrictedAccessMode) - { - IInAppNotification notification = dialogService.GetNotification(); - notification.ViewModel.NotificationText = "Cannot add collections in Restricted Access mode."; - notification.ViewModel.ShownButtons = Enums.InAppNotificationButtonType.OkButton; - notification.Show(Constants.UI.Notifications.NOTIFICATION_DEFAULT_SHOW_TIME); - - return false; - } - - StorageFolder folder = await dialogService.PickSingleFolder(); - - // We retrieve the folder again this time using ToStorageItem<>() because items picked by the FilePicker - // or FolderPicker cannot be modified - i.e. Renamed etc. - folder = await StorageHelpers.ToStorageItem(folder?.Path); - - if (folder == null) - { - return false; // User didn't pick any folder or couldn't retrieve the folder after it's been picked - } - - StandardCollectionViewModel standardCollectionViewModel = new StandardCollectionViewModel(folder); - - return await AddCollection(standardCollectionViewModel, null); - } - - #endregion - - #region Event Hooks - - private void HookEvents() - { - UnhookEvents(); - Collections.CollectionChanged += Collections_CollectionChanged; - } - - private void UnhookEvents() - { - Collections.CollectionChanged -= Collections_CollectionChanged; - } - - #endregion - - #region IDisposable - - public void Dispose() - { - UnhookEvents(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Collections/DefaultCollectionViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Collections/DefaultCollectionViewModel.cs deleted file mode 100644 index cfd118d7..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Collections/DefaultCollectionViewModel.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Windows.Storage; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.ViewModels.UserControls.Collections -{ - public class DefaultCollectionViewModel : BaseCollectionViewModel - { - #region Properties - - public override string DisplayName => "DefaultCollection".GetLocalized2(); - - #endregion - - #region Constructor - - public DefaultCollectionViewModel(StorageFolder collectionFolder) - : base(collectionFolder) - { - canBeSetAsAutopasteTarget = true; - } - - #endregion - - #region Override - - public override bool CheckCollectionAvailability() - { - SetCollectionError(SafeWrapperResult.SUCCESS); - return true; - } - - public override CollectionConfigurationModel ConstructConfigurationModel() - { - return new CollectionConfigurationModel(Constants.Collections.DEFAULT_COLLECTION_TOKEN, UsesCustomIcon, iconFile?.Name); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/Collections/StandardCollectionViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/Collections/StandardCollectionViewModel.cs deleted file mode 100644 index 60240722..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/Collections/StandardCollectionViewModel.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using CommunityToolkit.Mvvm.Input; -using System.Threading.Tasks; -using Microsoft.UI.Xaml.Input; -using Windows.System; -using Microsoft.UI.Xaml; -using Windows.Storage; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.EventArguments.Collections; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Interfaces.Collections; - -namespace ClipboardCanvas.ViewModels.UserControls.Collections -{ - public class StandardCollectionViewModel : BaseCollectionViewModel, ICollectionNameEditable, ICollectionRemovable - { - #region Events - - public event EventHandler OnCheckRenameCollectionRequestedEvent; - - public event EventHandler OnRemoveCollectionRequestedEvent; - - #endregion - - #region Constructor - - public StandardCollectionViewModel(StorageFolder collectionFolder) - : this(collectionFolder, null) - { - } - - public StandardCollectionViewModel(string collectionPath) - : this(null, collectionPath) - { - } - - public StandardCollectionViewModel(StorageFolder collectionFolder, string collectionPath) - : base(collectionFolder, collectionPath) - { - canBeSetAsAutopasteTarget = true; - - // Create commands - StartRenameCollectionCommand = new RelayCommand(StartRename); - RenameBoxKeyDownCommand = new AsyncRelayCommand(RenameBoxKeyDown); - RenameBoxLostFocusCommand = new AsyncRelayCommand(RenameBoxLostFocus); - RemoveCollectionCommand = new RelayCommand(RemoveCollection); - } - - #endregion - - #region Command Implementation - - private async Task RenameBoxKeyDown(KeyRoutedEventArgs e) - { - e.Handled = true; - switch (e.Key) - { - case VirtualKey.Enter: - { - await ConfirmRename(); - - break; - } - - case VirtualKey.Escape: - { - CancelRename(); - - break; - } - } - } - - private async Task RenameBoxLostFocus(RoutedEventArgs e) - { - if (!IsEditingName) // Don't fire when textbox is being hidden - { - return; - } - - await ConfirmRename(); - } - - #endregion - - #region Override - - public override bool CheckCollectionAvailability() - { - if (ApplicationService.IsInRestrictedAccessMode) - { - SetCollectionError(RestrictedAccessUnauthorized); - return false; - } - else if (!StorageHelpers.Existsh(CollectionPath)) - { - SetCollectionError(CollectionFolderNotFound); - return false; - } - - SetCollectionError(SafeWrapperResult.SUCCESS); - return true; - } - - #endregion - - #region ICollectionNameEditable - - public void CancelRename() - { - // Cancel - IsEditingName = false; - } - - public async Task ConfirmRename() - { - string newName = EditBoxText; - isEditingName = false; - - CheckRenameCollectionRequestedEventArgs args = new CheckRenameCollectionRequestedEventArgs(this, newName); - OnCheckRenameCollectionRequestedEvent?.Invoke(this, args); - - if (args.canRename) - { - SafeWrapperResult result = await FilesystemOperations.RenameItem(collectionFolder, newName, NameCollisionOption.FailIfExists); - - if (result) - { - CollectionPath = collectionFolder.Path; - - OnPropertyChanged(nameof(DisplayName)); - OnPropertyChanged(nameof(IsEditingName)); - - // Also update settings - SettingsSerializationHelpers.UpdateSavedCollectionsSetting(); - SettingsSerializationHelpers.UpdateLastSelectedCollectionSetting(this); - - return true; - } - else - { - // Post a notification informing that rename had failed - PushErrorNotification("CouldNotRenameCollection".GetLocalized2(), result); - } - } - - OnPropertyChanged(nameof(IsEditingName)); - return false; - } - - public void StartRename() - { - if (IsCollectionAvailable) - { - EditBoxText = DisplayName; - IsEditingName = true; - - // Focus EditBox - EditBoxFocus = true; - EditBoxFocus = false; - } - } - - #endregion - - #region ICollectionRemovable - - public void RemoveCollection() - { - OnRemoveCollectionRequestedEvent?.Invoke(this, new RemoveCollectionRequestedEventArgs(this)); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/DisplayControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/DisplayControlViewModel.cs deleted file mode 100644 index bf91fbad..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/DisplayControlViewModel.cs +++ /dev/null @@ -1,944 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Threading; -using Windows.UI.ViewManagement; -using Windows.Storage; -using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.Mvvm.ComponentModel; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.EventArguments.CanvasControl; -using ClipboardCanvas.EventArguments.Collections; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.ReferenceItems; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.EventArguments.CollectionPreview; -using ClipboardCanvas.Services; -using ClipboardCanvas.DisplayFrameEventArgs; -using ClipboardCanvas.ViewModels.Widgets.Timeline; - -#nullable enable - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class DisplayControlViewModel : ObservableObject, IDisposable - { - #region Members - - private readonly IDisplayControlView _view; - - private ICollectionModel _currentCollectionModel; - - private CancellationTokenSource _canvasLoadCancellationTokenSource; - - private IWindowTitleBarControlModel WindowTitleBarControlModel => _view?.WindowTitleBarControlModel; - - private IIntroductionScreenPanelModel IntroductionScreenPanelModel => _view?.IntroductionScreenPanelModel; - - private INavigationToolBarControlModel NavigationToolBarControlModel => _view?.NavigationToolBarControlModel; - - /// - /// Stores Canvas Preview control - ///

- /// Note: This might be null depending on the current view - ///
- private IPasteCanvasPageModel PasteCanvasPageModel => _view?.PasteCanvasPageModel; - - /// - /// Stores Collection Preview model - ///

- /// Note: This might be null depending on the current view - ///
- private ICollectionPreviewPageModel CollectionPreviewPageModel => _view?.CollectionPreviewPageModel; - - private DisplayPageType CurrentPage => NavigationService.CurrentPage; - - private DisplayPageType LastPage => NavigationService.LastPage; - - private bool IntroductionPanelLoad - { - get => _view.IntroductionPanelLoad; - set => _view.IntroductionPanelLoad = value; - } - - #endregion - - #region Properties - - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - private IApplicationSettingsService ApplicationSettingsService { get; } = Ioc.Default.GetService(); - - private IAutopasteService AutopasteService { get; } = Ioc.Default.GetService(); - - private ITimelineService TimelineService { get; } = Ioc.Default.GetService(); - - #endregion - - #region Constructor - - public DisplayControlViewModel(IDisplayControlView view) - { - this._view = view; - this._canvasLoadCancellationTokenSource = new CancellationTokenSource(); - } - - #endregion - - #region Event Handlers - - #region NavigationService Events - - private void NavigationService_OnNavigationStartedEvent(object sender, NavigationStartedEventArgs e) - { - // Page switch requested so we need to unhook events - if (e.collection != null) - { - _currentCollectionModel = e.collection; - } - - // Unhook all views events - UnhookCanvasControlEvents(); - UnhookCollectionPreviewEvents(); - - // Dispose canvas - PasteCanvasPageModel?.Dispose(); - } - - private async void NavigationService_OnNavigationFinishedEvent(object sender, NavigationFinishedEventArgs e) - { - NavigationToolBarControlModel?.NotifyCurrentPageChanged(CurrentPage); - - // Hook up correct events - if (CurrentPage == DisplayPageType.CanvasPage) - { - HookCanvasControlEvents(); - } - else if (CurrentPage == DisplayPageType.CollectionPreviewPage) - { - HookCollectionPreviewEvents(); - } - - // Hide underline - WindowTitleBarControlModel.ShowTitleUnderline = false; - - // Update title bar text - UpdateTitleBar(); - - SafeWrapperResult canvasLoadResult = null; - - // We might navigate from home to a canvas that's already filled, so initialize the content - if ((e.collection?.IsCollectionInitialized ?? false) - && (!e.collection?.IsCollectionInitializing ?? false) - && (!e.collection?.IsOnNewCanvas ?? false) - && e.collectionItemToLoad != null) - { - _canvasLoadCancellationTokenSource.Cancel(); - _canvasLoadCancellationTokenSource.Dispose(); - _canvasLoadCancellationTokenSource = new CancellationTokenSource(); - - canvasLoadResult = await e.collection.LoadCanvasFromCollection(PasteCanvasPageModel.PasteCanvasModel, _canvasLoadCancellationTokenSource.Token, e.collectionItemToLoad); - } - - // Update navigation buttons - await UpdateNavigationOnPageNavigation(e.collection); - - // Update Suggested Actions - await SetSuggestedActions(e.collection, canvasLoadResult); - } - - #endregion - - #region WindowTitleBarControlModel - - private async void WindowTitleBarControlModel_OnSwitchApplicationViewRequestedEvent(object sender, EventArgs e) - { - if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default) - { - if (await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay)) - { - UpdateViewForCompactOverlayMode(); - } - } - else - { - if (await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default)) - { - UpdateViewForDefaultMode(); - } - } - } - - #endregion - - #region NavigationControlModel - - private async void NavigationControlModel_OnNavigateLastRequestedEvent(object sender, EventArgs e) - { - if (CurrentPage == DisplayPageType.CanvasPage && _currentCollectionModel.HasBack()) - { - _canvasLoadCancellationTokenSource.Cancel(); - _canvasLoadCancellationTokenSource.Dispose(); - _canvasLoadCancellationTokenSource = new CancellationTokenSource(); - - await _currentCollectionModel.NavigateLast(PasteCanvasPageModel.PasteCanvasModel, _canvasLoadCancellationTokenSource.Token); - } - } - - private async void NavigationControlModel_OnNavigateBackRequestedEvent(object sender, EventArgs e) - { - if (CurrentPage == DisplayPageType.CanvasPage && _currentCollectionModel.HasBack()) - { - _canvasLoadCancellationTokenSource.Cancel(); - _canvasLoadCancellationTokenSource.Dispose(); - _canvasLoadCancellationTokenSource = new CancellationTokenSource(); - - await _currentCollectionModel.NavigateBack(PasteCanvasPageModel.PasteCanvasModel, _canvasLoadCancellationTokenSource.Token); - } - } - - private void NavigationControlModel_OnNavigateFirstRequestedEvent(object sender, EventArgs e) - { - if (CurrentPage == DisplayPageType.CanvasPage && _currentCollectionModel.HasNext()) - { - _canvasLoadCancellationTokenSource.Cancel(); - _canvasLoadCancellationTokenSource.Dispose(); - _canvasLoadCancellationTokenSource = new CancellationTokenSource(); - - _currentCollectionModel.NavigateFirst(PasteCanvasPageModel.PasteCanvasModel); - } - } - - private async void NavigationControlModel_OnNavigateForwardRequestedEvent(object sender, EventArgs e) - { - if (CurrentPage == DisplayPageType.CanvasPage && _currentCollectionModel.HasNext()) - { - _canvasLoadCancellationTokenSource.Cancel(); - _canvasLoadCancellationTokenSource.Dispose(); - _canvasLoadCancellationTokenSource = new CancellationTokenSource(); - - await _currentCollectionModel.NavigateNext(PasteCanvasPageModel.PasteCanvasModel, _canvasLoadCancellationTokenSource.Token); - } - } - - private void NavigationControlModel_OnGoToHomepageRequestedEvent(object sender, EventArgs e) - { - _canvasLoadCancellationTokenSource.Cancel(); - _canvasLoadCancellationTokenSource.Dispose(); - _canvasLoadCancellationTokenSource = new CancellationTokenSource(); - - NavigationService.OpenHomepage(); - } - - private void NavigationControlModel_OnGoToCanvasRequestedEvent(object sender, EventArgs e) - { - NavigationService.OpenCanvasPage(_currentCollectionModel); - } - - private void NavigationControlModel_OnCollectionPreviewNavigateBackRequestedEvent(object sender, EventArgs e) - { - // Go back to page before Collection Preview page - OpenPage(LastPage); - } - - private void NavigationControlModel_OnCollectionPreviewGoToCanvasRequestedEvent(object sender, EventArgs e) - { - if (CollectionPreviewPageModel.SelectedItem == null) - { - // No item is selected, open new canvas - NavigationService.OpenNewCanvas(_currentCollectionModel); - } - else - { - // An item is selected, open that canvas - NavigationService.OpenCanvasPage(_currentCollectionModel, CollectionPreviewPageModel.SelectedItem.CollectionItemViewModel); - } - } - - #endregion - - #region CollectionsControlViewModel - - private async void CollectionsWidgetViewModel_OnCollectionItemContentsChangedEvent(object sender, CollectionItemContentsChangedEventArgs e) - { - if (NavigationService.CurrentPage == DisplayPageType.Homepage) - { - var (section, sectionItem) = TimelineService.FindTimelineSectionItem(e.itemChanged); - if (sectionItem != null) - { - await sectionItem.InitializeSectionItemContent(); - } - } - } - - private async void CollectionsWidgetViewModel_OnCollectionItemRenamedEvent(object sender, CollectionItemRenamedEventArgs e) - { - var (section, sectionItem) = TimelineService.FindTimelineSectionItem(e.itemChanged); - if (sectionItem != null) - { - await sectionItem.UpdateFileName(); - } - } - - private void CollectionsWidgetViewModel_OnCollectionItemRemovedEvent(object sender, CollectionItemRemovedEventArgs e) - { - var (section, sectionItem) = TimelineService.FindTimelineSectionItem(e.itemChanged); - section?.RemoveItem(sectionItem); - } - - private async void CollectionsWidgetViewModel_OnCollectionItemAddedEvent(object sender, CollectionItemAddedEventArgs e) - { - // Autopaste will handle the timeline - if (!NavigationToolBarControlModel.AutopasteControlModel.EnableAutopaste) - { - var todaySection = await TimelineService.GetOrCreateTodaySection(); - await TimelineService.AddItemForSection(todaySection, e.baseCollectionViewModel, e.itemChanged); - } - } - - private void CollectionsControlViewModel_OnTipTextUpdateRequestedEvent(object sender, TipTextUpdateRequestedEventArgs e) - { - PasteCanvasPageModel.SetTipText(e.infoText, e.tipShowDelay); - } - - private async void CollectionsControlViewModel_OnCanvasLoadFailedEvent(object sender, CanvasLoadFailedEventArgs e) - { - UpdateCanvasPageNavigation(); - - await SetSuggestedActions(_currentCollectionModel, e.error); - } - - private void CollectionsControlViewModel_OnCollectionErrorRaisedEvent(object sender, CollectionErrorRaisedEventArgs e) - { - if (e.safeWrapperResult) - { - NavigationToolBarControlModel.NavigationControlModel.GoToCanvasEnabled = true; - } - else - { - NavigationToolBarControlModel.NavigationControlModel.GoToCanvasEnabled = false; - } - } - - private void CollectionsControlViewModel_OnGoToHomepageRequestedEvent(object sender, GoToHomepageRequestedEventArgs e) - { - NavigationService.OpenHomepage(); - } - - private void CollectionsControlViewModel_OnOpenNewCanvasRequestedEvent(object sender, OpenNewCanvasRequestedEventArgs e) - { - NavigationService.OpenNewCanvas(_currentCollectionModel); - } - - private void CollectionsControlViewModel_OnCollectionItemsInitializationFinishedEvent(object sender, CollectionItemsInitializationFinishedEventArgs e) - { - // Re-enable navigation after items have loaded - NavigationToolBarControlModel.NavigationControlModel.NavigateBackLoading = false; - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardLoading = false; - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading = false; - } - - private void CollectionsControlViewModel_OnCollectionItemsInitializationStartedEvent(object sender, CollectionItemsInitializationStartedEventArgs e) - { - // Show navigation loading - NavigationToolBarControlModel.NavigationControlModel.NavigateBackLoading = true; - - if (CollectionPreviewPageModel?.SelectedItem != null) - { - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading = true; - } - - if (!_currentCollectionModel.IsOnNewCanvas) - { - // Also show loading for forward button if not on new canvas - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardLoading = true; - } - } - - private void CollectionsControlViewModel_OnCollectionAddedEvent(object sender, CollectionAddedEventArgs e) - { - } - - private void CollectionsControlViewModel_OnCollectionRemovedEvent(object sender, CollectionRemovedEventArgs e) - { - } - - private void CollectionsControlViewModel_OnCollectionSelectionChangedEvent(object sender, CollectionSelectionChangedEventArgs e) - { - _currentCollectionModel = e.baseCollectionViewModel; - - if (_currentCollectionModel.IsCollectionAvailable) - { - NavigationToolBarControlModel.NavigationControlModel.GoToCanvasEnabled = true; - } - else - { - NavigationToolBarControlModel.NavigationControlModel.GoToCanvasEnabled = false; - } - } - - private void CollectionsControlViewModel_OnCollectionOpenRequestedEvent(object sender, CollectionOpenRequestedEventArgs e) - { - NavigationService.OpenCollectionPreviewPage(e.baseCollectionViewModel); - } - - #endregion - - #region PasteCanvasModel - - private void PasteCanvasModel_OnErrorOccurredEvent(object sender, ErrorOccurredEventArgs e) - { - UpdateCanvasPageNavigation(); - } - - private async void PasteCanvasModel_OnFileDeletedEvent(object sender, FileDeletedEventArgs e) - { - await e.collectionModel.LoadCanvasFromCollection(PasteCanvasPageModel.PasteCanvasModel, _canvasLoadCancellationTokenSource.Token); - } - - private async void PasteCanvasModel_OnPasteInitiatedEvent(object sender, PasteInitiatedEventArgs e) - { - if (e.pasteInNewCanvas) - { - // Already has content, meaning we need to switch to the next page - NavigationService.OpenNewCanvas(e.collectionModel); - - // Forward the paste operation - SafeWrapperResult result = await PasteCanvasPageModel.PasteCanvasModel.TryPasteData(e.forwardedDataPackage, _canvasLoadCancellationTokenSource.Token); - } - } - - private void PasteCanvasModel_OnContentStartedLoadingEvent(object sender, ContentStartedLoadingEventArgs e) - { - NavigationToolBarControlModel.SuggestedActionsControlModel.ShowNoActionsLabelSuppressed = true; - UpdateCanvasPageNavigation(); - - if (e.contentType is not InfiniteCanvasContentType - && CurrentPage == DisplayPageType.CanvasPage - && (e.contentType is TextContentType - || e.contentType is MarkdownContentType)) - { - WindowTitleBarControlModel.ShowTitleUnderline = true; - } - else - { - WindowTitleBarControlModel.ShowTitleUnderline = false; - } - } - - private async void PasteCanvasModel_OnContentLoadedEvent(object sender, ContentLoadedEventArgs e) - { - await SetSuggestedActions(_currentCollectionModel); - NavigationToolBarControlModel.SuggestedActionsControlModel.ShowNoActionsLabelSuppressed = false; - - UpdateCanvasPageNavigation(); - - if (e.contentType is not InfiniteCanvasContentType - && CurrentPage == DisplayPageType.CanvasPage - && (e.contentType is TextContentType - || e.contentType is MarkdownContentType)) - { - WindowTitleBarControlModel.ShowTitleUnderline = true; - } - else - { - WindowTitleBarControlModel.ShowTitleUnderline = false; - } - } - - #endregion - - #region CollectionPreviewPageViewModel - - private void CollectionPreviewPageModel_OnCanvasPreviewSelectedItemChangedEvent(object sender, CanvasPreviewSelectedItemChangedEventArgs e) - { - // We must update the canvas button loading when selection is changed - if (e.selectedItem != null && e.selectedItem.CollectionModel.IsCollectionInitializing) - { - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading = true; - } - else - { - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading = false; - } - - if (e.selectedItem == null) - { - _currentCollectionModel.SetIndexOnNewCanvas(); - } - else - { - e.selectedItem.CollectionModel.UpdateIndex(e.selectedItem.CollectionItemViewModel); - } - - CheckCollectionPreviewPageNavigation(); - } - - private async void CollectionPreviewPageModel_OnCanvasPreviewPasteRequestedEvent(object sender, CanvasPreviewPasteRequestedEventArgs e) - { - e.collectionModel.SetIndexOnNewCanvas(); - NavigationService.OpenCanvasPage(e.collectionModel); - await Task.Delay(800); - - await PasteCanvasPageModel.PasteCanvasModel.TryPasteData(e.forwardedDataPackage, _canvasLoadCancellationTokenSource.Token); - } - - #endregion - - #endregion - - #region Public Helpers - - public async Task InitializeAfterLoad() - { - // Check to show OOBE - if (!this.ApplicationSettingsService.IsUserIntroduced) - { - IntroductionPanelLoad = true; - } - - // Important first-checks - await InitialApplicationChecksHelpers.HandleFileSystemPermissionDialog(WindowTitleBarControlModel); - await InitialApplicationChecksHelpers.CheckVersionAndShowDialog(); - - // Event hooks - HookCollectionsEvents(); - HookNavigationServiceEvents(); - HookTitleBarEvents(); - HookToolbarEvents(); - - // Update navigation buttons - NavigationToolBarControlModel.NavigationControlModel.NavigateBackEnabled = false; - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardEnabled = false; - - // Collections, Timeline and Autopaste - await CollectionsWidgetViewModel.ReloadAllCollections(); - await TimelineWidgetViewModel.ReloadAllSections(); - await AutopasteService.InitializeAutopaste(); - - // Navigate - NavigationService.OpenCanvasPage(_currentCollectionModel); - NavigationToolBarControlModel.NotifyCurrentPageChanged(CurrentPage); - - // Update navigaion buttons and Titlebar - UpdateTitleBar(); - UpdateCanvasPageNavigation(); - } - - public bool CheckCollectionAvailabilityBeforePageNavigation() - { - _currentCollectionModel?.CheckCollectionAvailability(); - - if (_currentCollectionModel == null || !_currentCollectionModel.IsCollectionAvailable) - { - // Something went wrong, cannot use collection - stay on homepage - NavigationService.OpenHomepage(); - - return false; - } - - return true; - } - - #endregion - - #region Private Helpers - - private void UpdateViewForCompactOverlayMode() - { - } - - private void UpdateViewForDefaultMode() - { - } - - private async Task UpdateNavigationOnPageNavigation(ICollectionModel collectionModel) - { - // Handle event where user opens canvas - and show loading rings if needed - if (collectionModel?.IsCollectionInitializing ?? false) - { - // Show navigation loading - NavigationToolBarControlModel.NavigationControlModel.NavigateBackLoading = true; - if (!collectionModel?.IsOnNewCanvas ?? false) - { - // Also show loading for forward button if not on new canvas - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardLoading = true; - } - - // If in Collection Preview and selected item is not null, meaning a canvas is selected - if (CollectionPreviewPageModel?.SelectedItem != null) - { - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading = true; - CheckCollectionPreviewPageNavigation(); - } - - UpdateCanvasPageNavigation(); - } - // Handle event when the collection is not initialized - else if (!collectionModel?.IsCollectionInitialized ?? false) - { - // Performance optimization: instead of initializing all collections at once, - // initialize the one that's being opened - await collectionModel.InitializeCollectionItems(); - CheckCollectionPreviewPageNavigation(); - UpdateCanvasPageNavigation(); - } - // Handle event where the loading rings were shown and the collection is no longer initializing - hide them - else - { - if (!collectionModel?.IsCollectionInitializing ?? false) - { - // Re-enable navigation after items have loaded - NavigationToolBarControlModel.NavigationControlModel.NavigateBackLoading = false; - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardLoading = false; - - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading = false; - UpdateCanvasPageNavigation(); - CheckCollectionPreviewPageNavigation(); - } - } - } - - - private void UpdateCanvasPageNavigation() - { - if (CurrentPage != DisplayPageType.CanvasPage || NavigationToolBarControlModel?.NavigationControlModel == null) - { - return; - } - - if (_currentCollectionModel != null) - { - if (NavigationToolBarControlModel.NavigationControlModel.NavigateBackLoading) - { - NavigationToolBarControlModel.NavigationControlModel.NavigateBackEnabled = false; - } - else - { - NavigationToolBarControlModel.NavigationControlModel.NavigateBackEnabled = _currentCollectionModel.HasBack(); - } - - if (NavigationToolBarControlModel.NavigationControlModel.NavigateForwardLoading) - { - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardEnabled = false; - } - else - { - NavigationToolBarControlModel.NavigationControlModel.NavigateForwardEnabled = _currentCollectionModel.HasNext(); - } - } - } - - private bool OpenPage(DisplayPageType pageType) - { - switch (pageType) - { - case DisplayPageType.Homepage: - { - return NavigationService.OpenHomepage(); - } - - case DisplayPageType.CanvasPage: - { - return NavigationService.OpenCanvasPage(_currentCollectionModel); - } - - case DisplayPageType.CollectionPreviewPage: - { - return NavigationService.OpenCollectionPreviewPage(_currentCollectionModel); - } - - default: - return false; - } - } - - private void CheckCollectionPreviewPageNavigation() - { - if (CurrentPage != DisplayPageType.CollectionPreviewPage) - { - return; - } - - if (NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasLoading) - { - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasEnabled = false; - } - else - { - NavigationToolBarControlModel.NavigationControlModel.CollectionPreviewGoToCanvasEnabled = true; - } - } - - private async Task SetSuggestedActions(ICollectionModel collectionModel, SafeWrapperResult fromError = null) - { - if (NavigationToolBarControlModel == null) - { - return; - } - - if (fromError != null) - { - if (collectionModel?.CurrentCollectionItemViewModel != null && collectionModel?.CurrentCollectionItemViewModel.AssociatedItem is StorageFile file && ReferenceFile.IsReferenceFile(file)) - { - if (fromError == OperationErrorCode.InvalidOperation) // Reference File is corrupted - { - NavigationToolBarControlModel.SuggestedActionsControlModel.SetActions(SuggestedActionsHelpers.GetActionsForInvalidReference(PasteCanvasPageModel.PasteCanvasModel)); - } - else if (fromError == OperationErrorCode.NotFound) // Reference not found - { - NavigationToolBarControlModel.SuggestedActionsControlModel.SetActions(SuggestedActionsHelpers.GetActionsForInvalidReference(PasteCanvasPageModel.PasteCanvasModel)); - } - } - } - else - { - bool checkAgain = false; - do - { - switch (CurrentPage) - { - case DisplayPageType.Homepage: - { - NavigationToolBarControlModel.SuggestedActionsControlModel.SetActions(SuggestedActionsHelpers.GetActionsForHomepage()); - - checkAgain = false; - - break; - } - - case DisplayPageType.CanvasPage: - { - // Add suggested actions - if (PasteCanvasPageModel != null && (!collectionModel?.IsOnNewCanvas ?? false || PasteCanvasPageModel.PasteCanvasModel.IsContentLoaded)) - { - var actions = await PasteCanvasPageModel.PasteCanvasModel.GetSuggestedActions(); - NavigationToolBarControlModel.SuggestedActionsControlModel.SetActions(actions); - - // Check again, the state might have changed - if (collectionModel?.IsOnNewCanvas ?? false) - { - // The state changed - checkAgain = true; - break; - } - - checkAgain = false; - } - else - { - NavigationToolBarControlModel.SuggestedActionsControlModel.SetActions(SuggestedActionsHelpers.GetActionsForEmptyCanvasPage(PasteCanvasPageModel.PasteCanvasModel)); - } - - break; - } - - case DisplayPageType.CollectionPreviewPage: - { - NavigationToolBarControlModel.SuggestedActionsControlModel.SetActions(SuggestedActionsHelpers.GetActionsForCollectionPreviewPage()); - - checkAgain = false; - - break; - } - } - } - while (checkAgain); - } - } - - private void UpdateTitleBar() - { - switch (CurrentPage) - { - case DisplayPageType.Homepage: - WindowTitleBarControlModel?.SetTitleBarForCollectionsView(); - break; - - case DisplayPageType.CanvasPage: - WindowTitleBarControlModel?.SetTitleBarForCanvasView(_currentCollectionModel.DisplayName); - break; - - case DisplayPageType.CollectionPreviewPage: - WindowTitleBarControlModel?.SetTitleBarForCollectionPreview(_currentCollectionModel.DisplayName); - break; - - default: - WindowTitleBarControlModel?.SetTitleBarForDefaultView(); - break; - } - } - - #endregion - - #region Event Hooks - - private void UnhookNavigationServiceEvents() - { - if (NavigationService != null) - { - NavigationService.OnNavigationStartedEvent -= NavigationService_OnNavigationStartedEvent; - NavigationService.OnNavigationFinishedEvent -= NavigationService_OnNavigationFinishedEvent; - } - } - - private void HookNavigationServiceEvents() - { - UnhookNavigationServiceEvents(); - if (NavigationService != null) - { - NavigationService.OnNavigationStartedEvent += NavigationService_OnNavigationStartedEvent; - NavigationService.OnNavigationFinishedEvent += NavigationService_OnNavigationFinishedEvent; - } - } - - private void UnhookTitleBarEvents() - { - if (this.WindowTitleBarControlModel != null) - { - this.WindowTitleBarControlModel.OnSwitchApplicationViewRequestedEvent -= WindowTitleBarControlModel_OnSwitchApplicationViewRequestedEvent; - } - } - - private void HookTitleBarEvents() - { - UnhookTitleBarEvents(); - if (this.WindowTitleBarControlModel != null) - { - this.WindowTitleBarControlModel.OnSwitchApplicationViewRequestedEvent += WindowTitleBarControlModel_OnSwitchApplicationViewRequestedEvent; - } - } - - private void HookToolbarEvents() - { - UnhookToolbarEvents(); - if (this.NavigationToolBarControlModel != null && this.NavigationToolBarControlModel.NavigationControlModel != null) - { - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateLastRequestedEvent += NavigationControlModel_OnNavigateLastRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateBackRequestedEvent += NavigationControlModel_OnNavigateBackRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateFirstRequestedEvent += NavigationControlModel_OnNavigateFirstRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateForwardRequestedEvent += NavigationControlModel_OnNavigateForwardRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnGoToHomepageRequestedEvent += NavigationControlModel_OnGoToHomepageRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnGoToCanvasRequestedEvent += NavigationControlModel_OnGoToCanvasRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnCollectionPreviewNavigateBackRequestedEvent += NavigationControlModel_OnCollectionPreviewNavigateBackRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnCollectionPreviewGoToCanvasRequestedEvent += NavigationControlModel_OnCollectionPreviewGoToCanvasRequestedEvent; - } - } - - private void UnhookToolbarEvents() - { - if (this.NavigationToolBarControlModel != null && this.NavigationToolBarControlModel.NavigationControlModel != null) - { - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateLastRequestedEvent -= NavigationControlModel_OnNavigateLastRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateBackRequestedEvent -= NavigationControlModel_OnNavigateBackRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateForwardRequestedEvent -= NavigationControlModel_OnNavigateForwardRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnNavigateFirstRequestedEvent -= NavigationControlModel_OnNavigateFirstRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnGoToHomepageRequestedEvent -= NavigationControlModel_OnGoToHomepageRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnGoToCanvasRequestedEvent -= NavigationControlModel_OnGoToCanvasRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnCollectionPreviewNavigateBackRequestedEvent -= NavigationControlModel_OnCollectionPreviewNavigateBackRequestedEvent; - this.NavigationToolBarControlModel.NavigationControlModel.OnCollectionPreviewGoToCanvasRequestedEvent -= NavigationControlModel_OnCollectionPreviewGoToCanvasRequestedEvent; - } - } - - private void HookCollectionsEvents() - { - UnhookCollectionsEvents(); - CollectionsWidgetViewModel.OnCollectionOpenRequestedEvent += CollectionsControlViewModel_OnCollectionOpenRequestedEvent; - CollectionsWidgetViewModel.OnCollectionSelectionChangedEvent += CollectionsControlViewModel_OnCollectionSelectionChangedEvent; - CollectionsWidgetViewModel.OnCollectionRemovedEvent += CollectionsControlViewModel_OnCollectionRemovedEvent; - CollectionsWidgetViewModel.OnCollectionAddedEvent += CollectionsControlViewModel_OnCollectionAddedEvent; - CollectionsWidgetViewModel.OnCollectionItemsInitializationStartedEvent += CollectionsControlViewModel_OnCollectionItemsInitializationStartedEvent; - CollectionsWidgetViewModel.OnCollectionItemsInitializationFinishedEvent += CollectionsControlViewModel_OnCollectionItemsInitializationFinishedEvent; - CollectionsWidgetViewModel.OnOpenNewCanvasRequestedEvent += CollectionsControlViewModel_OnOpenNewCanvasRequestedEvent; - CollectionsWidgetViewModel.OnGoToHomepageRequestedEvent += CollectionsControlViewModel_OnGoToHomepageRequestedEvent; - CollectionsWidgetViewModel.OnCollectionErrorRaisedEvent += CollectionsControlViewModel_OnCollectionErrorRaisedEvent; - CollectionsWidgetViewModel.OnCanvasLoadFailedEvent += CollectionsControlViewModel_OnCanvasLoadFailedEvent; - CollectionsWidgetViewModel.OnTipTextUpdateRequestedEvent += CollectionsControlViewModel_OnTipTextUpdateRequestedEvent; - CollectionsWidgetViewModel.OnCollectionItemAddedEvent += CollectionsWidgetViewModel_OnCollectionItemAddedEvent; - CollectionsWidgetViewModel.OnCollectionItemRemovedEvent += CollectionsWidgetViewModel_OnCollectionItemRemovedEvent; - CollectionsWidgetViewModel.OnCollectionItemRenamedEvent += CollectionsWidgetViewModel_OnCollectionItemRenamedEvent; - CollectionsWidgetViewModel.OnCollectionItemContentsChangedEvent += CollectionsWidgetViewModel_OnCollectionItemContentsChangedEvent; - } - - private void UnhookCollectionsEvents() - { - CollectionsWidgetViewModel.OnCollectionOpenRequestedEvent -= CollectionsControlViewModel_OnCollectionOpenRequestedEvent; - CollectionsWidgetViewModel.OnCollectionSelectionChangedEvent -= CollectionsControlViewModel_OnCollectionSelectionChangedEvent; - CollectionsWidgetViewModel.OnCollectionRemovedEvent -= CollectionsControlViewModel_OnCollectionRemovedEvent; - CollectionsWidgetViewModel.OnCollectionAddedEvent -= CollectionsControlViewModel_OnCollectionAddedEvent; - CollectionsWidgetViewModel.OnCollectionItemsInitializationStartedEvent -= CollectionsControlViewModel_OnCollectionItemsInitializationStartedEvent; - CollectionsWidgetViewModel.OnCollectionItemsInitializationFinishedEvent -= CollectionsControlViewModel_OnCollectionItemsInitializationFinishedEvent; - CollectionsWidgetViewModel.OnOpenNewCanvasRequestedEvent -= CollectionsControlViewModel_OnOpenNewCanvasRequestedEvent; - CollectionsWidgetViewModel.OnGoToHomepageRequestedEvent -= CollectionsControlViewModel_OnGoToHomepageRequestedEvent; - CollectionsWidgetViewModel.OnCollectionErrorRaisedEvent -= CollectionsControlViewModel_OnCollectionErrorRaisedEvent; - CollectionsWidgetViewModel.OnCanvasLoadFailedEvent -= CollectionsControlViewModel_OnCanvasLoadFailedEvent; - CollectionsWidgetViewModel.OnTipTextUpdateRequestedEvent -= CollectionsControlViewModel_OnTipTextUpdateRequestedEvent; - CollectionsWidgetViewModel.OnCollectionItemAddedEvent -= CollectionsWidgetViewModel_OnCollectionItemAddedEvent; - CollectionsWidgetViewModel.OnCollectionItemRemovedEvent -= CollectionsWidgetViewModel_OnCollectionItemRemovedEvent; - CollectionsWidgetViewModel.OnCollectionItemRenamedEvent -= CollectionsWidgetViewModel_OnCollectionItemRenamedEvent; - CollectionsWidgetViewModel.OnCollectionItemContentsChangedEvent -= CollectionsWidgetViewModel_OnCollectionItemContentsChangedEvent; - } - - private void HookCanvasControlEvents() - { - UnhookCanvasControlEvents(); - if (PasteCanvasPageModel != null) - { - this.PasteCanvasPageModel.PasteCanvasModel.OnContentLoadedEvent += PasteCanvasModel_OnContentLoadedEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnContentStartedLoadingEvent += PasteCanvasModel_OnContentStartedLoadingEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnPasteInitiatedEvent += PasteCanvasModel_OnPasteInitiatedEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnFileDeletedEvent += PasteCanvasModel_OnFileDeletedEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnErrorOccurredEvent += PasteCanvasModel_OnErrorOccurredEvent; - } - } - - private void UnhookCanvasControlEvents() - { - if (PasteCanvasPageModel != null) - { - this.PasteCanvasPageModel.PasteCanvasModel.OnContentLoadedEvent -= PasteCanvasModel_OnContentLoadedEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnContentStartedLoadingEvent -= PasteCanvasModel_OnContentStartedLoadingEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnPasteInitiatedEvent -= PasteCanvasModel_OnPasteInitiatedEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnFileDeletedEvent -= PasteCanvasModel_OnFileDeletedEvent; - this.PasteCanvasPageModel.PasteCanvasModel.OnErrorOccurredEvent -= PasteCanvasModel_OnErrorOccurredEvent; - } - } - - private void HookCollectionPreviewEvents() - { - UnhookCollectionPreviewEvents(); - if (CollectionPreviewPageModel != null) - { - this.CollectionPreviewPageModel.OnCanvasPreviewSelectedItemChangedEvent += CollectionPreviewPageModel_OnCanvasPreviewSelectedItemChangedEvent; - this.CollectionPreviewPageModel.OnCanvasPreviewPasteRequestedEvent += CollectionPreviewPageModel_OnCanvasPreviewPasteRequestedEvent; - } - } - - private void UnhookCollectionPreviewEvents() - { - if (CollectionPreviewPageModel != null) - { - this.CollectionPreviewPageModel.OnCanvasPreviewSelectedItemChangedEvent -= CollectionPreviewPageModel_OnCanvasPreviewSelectedItemChangedEvent; - this.CollectionPreviewPageModel.OnCanvasPreviewPasteRequestedEvent -= CollectionPreviewPageModel_OnCanvasPreviewPasteRequestedEvent; - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - UnhookTitleBarEvents(); - UnhookToolbarEvents(); - UnhookCollectionsEvents(); - UnhookCanvasControlEvents(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/InAppNotifications/IInAppNotification.cs b/ClipboardCanvas/ViewModels/UserControls/InAppNotifications/IInAppNotification.cs deleted file mode 100644 index 1ecc86ac..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/InAppNotifications/IInAppNotification.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using ClipboardCanvas.EventArguments; - -namespace ClipboardCanvas.ViewModels.UserControls.InAppNotifications -{ - public interface IInAppNotification - { - InAppNotificationControlViewModel ViewModel { get; set; } - - event EventHandler OnInAppNotificationDismissedEvent; - - void Show(int milliseconds = 0); - - void Dismiss(); - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/InAppNotifications/InAppNotificationControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/InAppNotifications/InAppNotificationControlViewModel.cs deleted file mode 100644 index ffa13fa9..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/InAppNotifications/InAppNotificationControlViewModel.cs +++ /dev/null @@ -1,244 +0,0 @@ -using System; -using System.Windows.Input; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System.Threading.Tasks; -using Microsoft.UI.Xaml; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments; - -namespace ClipboardCanvas.ViewModels.UserControls.InAppNotifications -{ - public class InAppNotificationControlViewModel : ObservableObject, IDisposable - { - #region Private Members - - private readonly DispatcherTimer _timer; - - private int _passedMilliseconds; - - private int _showMilliseconds; - - #endregion - - #region Public Properties - - public InAppNotificationButtonType NotificationResult { get; private set; } - - private InAppNotificationButtonType _ShownButtons; - public InAppNotificationButtonType ShownButtons - { - get => _ShownButtons; - set - { - if (_ShownButtons != value) - { - _ShownButtons = value; - CheckShownButtons(); - } - } - } - - private bool _ShowNotification; - public bool ShowNotification - { - get => _ShowNotification; - private set => SetProperty(ref _ShowNotification, value); - } - - private string _NotificationText; - public string NotificationText - { - get => _NotificationText; - set => SetProperty(ref _NotificationText, value); - } - - private bool _OkButtonLoad; - public bool OkButtonLoad - { - get => _OkButtonLoad; - private set => SetProperty(ref _OkButtonLoad, value); - } - - private bool _YesButtonLoad; - public bool YesButtonLoad - { - get => _YesButtonLoad; - private set => SetProperty(ref _YesButtonLoad, value); - } - - private bool _NoButtonLoad; - public bool NoButtonLoad - { - get => _NoButtonLoad; - private set => SetProperty(ref _NoButtonLoad, value); - } - - private bool _NotificationShowTimerProgressBarLoad; - public bool NotificationShowTimerProgressBarLoad - { - get => _NotificationShowTimerProgressBarLoad; - set => SetProperty(ref _NotificationShowTimerProgressBarLoad, value); - } - - private double _NotificationShowTimerProgressBarValue; - public double NotificationShowTimerProgressBarValue - { - get => _NotificationShowTimerProgressBarValue; - set => SetProperty(ref _NotificationShowTimerProgressBarValue, value); - } - - #endregion - - #region Events - - public event EventHandler OnInAppNotificationDismissedEvent; - - #endregion - - #region Commands - - public ICommand OkButtonClickCommand { get; private set; } - - public ICommand YesButtonClickCommand { get; private set; } - - public ICommand NoButtonClickCommand { get; private set; } - - #endregion - - #region Constructor - - public InAppNotificationControlViewModel(InAppNotificationButtonType shownButtons) - { - this.ShownButtons = shownButtons; - this._timer = new DispatcherTimer(); - this._timer.Interval = TimeSpan.FromMilliseconds(Constants.UI.Notifications.NOTIFICATION_PROGRESSBAR_REFRESH_INTERVAL); - this._timer.Tick += Timer_Tick; - - CheckShownButtons(); - - // Create commands - OkButtonClickCommand = new RelayCommand(OkButtonClick); - YesButtonClickCommand = new RelayCommand(YesButtonClick); - NoButtonClickCommand = new RelayCommand(NoButtonClick); - } - - #endregion - - #region Command Implementation - - private void NoButtonClick() - { - NotificationResult = InAppNotificationButtonType.NoButton; - Dismiss(); - OnInAppNotificationDismissedEvent?.Invoke(this, new InAppNotificationDismissedEventArgs(NotificationResult)); - } - - private void YesButtonClick() - { - NotificationResult = InAppNotificationButtonType.YesButton; - Dismiss(); - OnInAppNotificationDismissedEvent?.Invoke(this, new InAppNotificationDismissedEventArgs(NotificationResult)); - } - - private void OkButtonClick() - { - NotificationResult = InAppNotificationButtonType.OkButton; - Dismiss(); - OnInAppNotificationDismissedEvent?.Invoke(this, new InAppNotificationDismissedEventArgs(NotificationResult)); - } - - #endregion - - #region Event Handlers - - private void Timer_Tick(object sender, object e) - { - // Increase the passed milliseconds by a constant value - _passedMilliseconds += Constants.UI.Notifications.NOTIFICATION_PROGRESSBAR_REFRESH_INTERVAL; - - // Get progress - double percentage = (double)_passedMilliseconds * 100.0d / (double)_showMilliseconds; - NotificationShowTimerProgressBarValue = percentage; - - if (_passedMilliseconds >= _showMilliseconds) - { - Dismiss(); - } - } - - #endregion - - #region Helpers - - private void CheckShownButtons() - { - // For OK Button - if (ShownButtons.HasFlag(InAppNotificationButtonType.OkButton)) - { - OkButtonLoad = true; - } - else - { - OkButtonLoad = false; - } - - // For Yes Button - if (ShownButtons.HasFlag(InAppNotificationButtonType.YesButton)) - { - YesButtonLoad = true; - } - else - { - YesButtonLoad = false; - } - - // For No Button - if (ShownButtons.HasFlag(InAppNotificationButtonType.NoButton)) - { - NoButtonLoad = true; - } - else - { - NoButtonLoad = false; - } - } - - public void Show(int milliseconds = 0) - { - Dismiss(); // Dismiss the last notification if there was one - - if (milliseconds > 0) - { - milliseconds = (int)(milliseconds * 0.6); // We lower down the time because the timer is slow and we need to account for an overhead - _showMilliseconds = milliseconds; - NotificationShowTimerProgressBarLoad = true; - this._timer.Start(); - } - - ShowNotification = true; - } - - public void Dismiss() - { - _timer.Stop(); - NotificationShowTimerProgressBarValue = 0.0d; - NotificationShowTimerProgressBarLoad = false; - _showMilliseconds = 0; - _passedMilliseconds = 0; - ShowNotification = false; - } - - #endregion - - #region IDisposable - - public void Dispose() - { - this._timer.Tick -= Timer_Tick; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/InteractableCanvasControlItemViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/InteractableCanvasControlItemViewModel.cs deleted file mode 100644 index c4bde73a..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/InteractableCanvasControlItemViewModel.cs +++ /dev/null @@ -1,248 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using System; -using System.Numerics; -using System.Threading; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.Input; -using System.Windows.Input; -using Windows.Storage; -using CommunityToolkit.Mvvm.DependencyInjection; -using Windows.ApplicationModel.DataTransfer; -using ClipboardCanvas.GlobalizationExtensions; -using System.Collections.ObjectModel; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.EventArguments.InfiniteCanvasEventArgs; -using ClipboardCanvas.CanvasFileReceivers; -using ClipboardCanvas.ViewModels.UserControls.InAppNotifications; -using ClipboardCanvas.Services; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.ViewModels.ContextMenu; -using ClipboardCanvas.EventArguments.CanvasControl; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class InteractableCanvasControlItemViewModel : ObservableObject, IInteractableCanvasControlItemModel, IDisposable - { - #region Private Members - - private IInteractableCanvasControlView _view; - - private readonly BaseContentTypeModel _contentType; - - private CancellationToken _cancellationToken; - - private readonly ICanvasItemReceiverModel _inifinteCanvasFileReceiver; - - #endregion - - #region Properties - - private IDialogService DialogService { get; } = Ioc.Default.GetService(); - - public IReadOnlyCanvasPreviewModel ReadOnlyCanvasPreviewModel { get; set; } - - public ICollectionModel CollectionModel { get; set; } - - public CanvasItem CanvasItem { get; private set; } - - public ObservableCollection CanvasContextMenuItems => ReadOnlyCanvasPreviewModel?.ContextMenuItems; - - private bool _IsPastedAsReference; - public bool IsPastedAsReference - { - get => _IsPastedAsReference; - set => SetProperty(ref _IsPastedAsReference, value); - } - - private bool _OverrideReferenceEnabled; - public bool OverrideReferenceEnabled - { - get => _OverrideReferenceEnabled; - set => SetProperty(ref _OverrideReferenceEnabled, value); - } - - private string _DisplayName; - public string DisplayName - { - get => _DisplayName; - set => SetProperty(ref _DisplayName, value); - } - - public int CanvasTopIndex - { - get => _view.GetCanvasTopIndex(this); - set => _view.SetCanvasTopIndex(this, value); - } - - /// - /// The item position - /// - public Vector2 ItemPosition - { - get => _view.GetItemPosition(this); - set => _view.SetItemPosition(this, value); - } - - /// - /// The horizontal position - /// - public float XPos - { - get => ItemPosition.X; - set => ItemPosition = new Vector2(value, ItemPosition.Y); - } - - /// - /// The vertical position - /// - public float YPos - { - get => ItemPosition.Y; - set => ItemPosition = new Vector2(ItemPosition.X, value); - } - - #endregion - - public event EventHandler OnInfiniteCanvasItemRemovalRequestedEvent; - - public ICommand OverrideReferenceCommand { get; private set; } - - #region Constructor - - internal InteractableCanvasControlItemViewModel(IInteractableCanvasControlView view, ICollectionModel collectionModel, BaseContentTypeModel contentType, CanvasItem canvasItem, ICanvasItemReceiverModel inifinteCanvasFileReceiver, CancellationToken cancellationToken) - { - this._view = view; - this.CollectionModel = collectionModel; - this._contentType = contentType; - this.CanvasItem = canvasItem; - this._inifinteCanvasFileReceiver = inifinteCanvasFileReceiver; - this._cancellationToken = cancellationToken; - - // Create commands - OverrideReferenceCommand = new AsyncRelayCommand(OverrideReference); - } - - #endregion - - #region Event Handlers - - private void ReadOnlyCanvasPreviewModel_OnFileDeletedEvent(object sender, FileDeletedEventArgs e) - { - OnInfiniteCanvasItemRemovalRequestedEvent?.Invoke(this, new InfiniteCanvasItemRemovalRequestedEventArgs(this)); - } - - #endregion - - #region Helpers - - private async Task OverrideReference() - { - if (!IsPastedAsReference) - { - return; - } - - OverrideReferenceEnabled = false; - SafeWrapper newCanvasItemResult = await this.ReadOnlyCanvasPreviewModel.PasteOverrideReference(); - OverrideReferenceEnabled = true; - - if (newCanvasItemResult) - { - this.CanvasItem = newCanvasItemResult; - IsPastedAsReference = false; - } - else if (newCanvasItemResult != OperationErrorCode.Canceled) - { - IInAppNotification notification = DialogService.GetNotification(); - notification.ViewModel.NotificationText = string.Format("ErrorWhilstOverridingReference".GetLocalized2(), newCanvasItemResult.ErrorCode); - notification.ViewModel.ShownButtons = InAppNotificationButtonType.OkButton; - - notification.Show(Constants.UI.Notifications.NOTIFICATION_DEFAULT_SHOW_TIME); - } - } - - public async Task OpenFile() - { - await StorageHelpers.OpenFile(await CanvasItem.SourceItem); - } - - public async Task InitializeDisplayName() - { - DisplayName = (await CanvasItem.SourceItem)?.Name ?? "InvalidFile".GetLocalized2(); - } - - public async Task InitializeItem() - { - await InitializeDisplayName(); - OverrideReferenceEnabled = (await CanvasItem.SourceItem) is not StorageFolder; - } - - public async Task LoadContent(bool withLoadDelay = false) - { - if (withLoadDelay) - { - // Wait for control to load - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - } - - SafeWrapperResult result; - if (ReadOnlyCanvasPreviewModel != null) - { - result = await ReadOnlyCanvasPreviewModel.TryLoadExistingData(CanvasItem, _contentType, _cancellationToken); - - if (result) - { - OnPropertyChanged(nameof(CanvasContextMenuItems)); - - ReadOnlyCanvasPreviewModel.OnFileDeletedEvent += ReadOnlyCanvasPreviewModel_OnFileDeletedEvent; - IsPastedAsReference = CanvasItem.IsFileAsReference; - ReadOnlyCanvasPreviewModel.CanvasItemReceiver = _inifinteCanvasFileReceiver; - } - } - else - { - return SafeWrapperResult.CANCEL; - } - - return result; - } - - public async Task SetDragData(DataPackage data) - { - bool dataSet = false; - - if (ReadOnlyCanvasPreviewModel != null) - { - dataSet = await ReadOnlyCanvasPreviewModel.SetDataToDataPackage(data); - } - - if (!dataSet) - { - data.SetStorageItems((await CanvasItem.SourceItem).ToListSingle()); - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - if (ReadOnlyCanvasPreviewModel != null) - { - ReadOnlyCanvasPreviewModel.OnFileDeletedEvent -= ReadOnlyCanvasPreviewModel_OnFileDeletedEvent; - } - - _view = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/InteractableCanvasControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/InteractableCanvasControlViewModel.cs deleted file mode 100644 index 65e44d25..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/InteractableCanvasControlViewModel.cs +++ /dev/null @@ -1,254 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using System.Collections.ObjectModel; -using System.Threading; -using System.Threading.Tasks; -using System; -using Windows.Storage.Streams; -using Microsoft.UI.Xaml; -using System.Numerics; -using Windows.ApplicationModel.DataTransfer; -using System.Linq; - -using ClipboardCanvas.DataModels; -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.EventArguments.InfiniteCanvasEventArgs; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.CanvasFileReceivers; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class InteractableCanvasControlViewModel : ObservableObject, IInteractableCanvasControlModel, IDisposable - { - #region Private Members - - private readonly IInteractableCanvasControlView _view; - - private readonly DispatcherTimer _saveTimer; - - #endregion - - #region Public Properties - - public ObservableCollection Items { get; private set; } - - private bool _NoItemsTextLoad; - public bool NoItemsTextLoad - { - get => _NoItemsTextLoad; - set => SetProperty(ref _NoItemsTextLoad, value); - } - - public InteractableCanvasDataPackageComparisionDataModel DataPackageComparisionDataModel { get; set; } - - #endregion - - #region Events - - public event EventHandler OnInfiniteCanvasSaveRequestedEvent; - - #endregion - - #region Constructor - - public InteractableCanvasControlViewModel(IInteractableCanvasControlView view) - { - this._view = view; - - this._saveTimer = new DispatcherTimer(); - this.Items = new ObservableCollection(); - - this._saveTimer.Interval = TimeSpan.FromMilliseconds(Constants.UI.CanvasContent.INFINITE_CANVAS_SAVE_INTERVAL); - this._saveTimer.Tick += SaveTimer_Tick; - } - - #endregion - - #region Event Handlers - - private async void SaveTimer_Tick(object sender, object e) - { - _saveTimer.Stop(); - - await SaveCanvas(); - } - - private void Item_OnInfiniteCanvasItemRemovalRequestedEvent(object sender, InfiniteCanvasItemRemovalRequestedEventArgs e) - { - RemoveItem(e.itemToRemove); - } - - #endregion - - #region Private Helpers - - private async Task SaveCanvas() - { - if (_view != null) - { - (IBuffer buffer, uint pixelWidth, uint pixelHeight) = await _view.GetCanvasImageBuffer(); - - if (buffer != null) - { - OnInfiniteCanvasSaveRequestedEvent?.Invoke(this, new InfiniteCanvasSaveRequestedEventArgs(buffer, pixelWidth, pixelHeight)); - } - } - } - - #endregion - - #region Public Helpers - - public async Task AddItem(ICollectionModel collectionModel, BaseContentTypeModel contentType, CanvasItem canvasItem, ICanvasItemReceiverModel inifinteCanvasFileReceiver, CancellationToken cancellationToken) - { - bool isDuplicate = Items.Any((item) => item.CanvasItem.AssociatedItem == canvasItem.AssociatedItem); - if (isDuplicate) - { - return null; - } - - var item = new InteractableCanvasControlItemViewModel(_view, collectionModel, contentType, canvasItem, inifinteCanvasFileReceiver, cancellationToken); - item.OnInfiniteCanvasItemRemovalRequestedEvent += Item_OnInfiniteCanvasItemRemovalRequestedEvent; - Items.Add(item); - await item.InitializeItem(); - NoItemsTextLoad = false; - - _view?.SetCanvasTopIndex(item, Items.Count); - - return item; - } - - public void RemoveItem(InteractableCanvasControlItemViewModel item) - { - if (item != null) - { - item.OnInfiniteCanvasItemRemovalRequestedEvent -= Item_OnInfiniteCanvasItemRemovalRequestedEvent; - Items.Remove(item); - - NoItemsTextLoad = Items.IsEmpty(); - } - } - - public bool ContainsItem(InteractableCanvasControlItemViewModel item) - { - if (item == null) - { - return false; - } - - return Items.Any((item2) => item2 == item); - } - - public InteractableCanvasControlItemViewModel FindItem(string path) - { - return Items.FirstOrDefault((item) => item.CanvasItem.AssociatedItem.Path.Equals(path)); - } - - public InfiniteCanvasConfigurationModel ConstructConfigurationModel() - { - var canvasConfigurationModel = new InfiniteCanvasConfigurationModel(); - - foreach (var item in Items) - { - canvasConfigurationModel.elements.Add(new InfiniteCanvasConfigurationItemModel(item.CanvasItem.AssociatedItem.Path, item.ItemPosition, item.CanvasTopIndex)); - } - - return canvasConfigurationModel; - } - - public void SetConfigurationModel(InfiniteCanvasConfigurationModel canvasConfigurationModel) - { - if (canvasConfigurationModel == null) - { - return; - } - - foreach (var item1 in Items) - { - foreach (var item2 in canvasConfigurationModel.elements) - { - if (item1.CanvasItem.AssociatedItem.Path == item2.associatedItemPath) - { - item1.ItemPosition = item2.locationVector; - item1.CanvasTopIndex = item2.canvasTopIndex; - } - } - } - - NoItemsTextLoad = Items.IsEmpty(); - } - - public void UpdateItemPositionFromDataPackage(DataPackageView dataPackage, InteractableCanvasControlItemViewModel interactableCanvasControlItem) - { - // If saved dataPackage == dataPackage from InfiniteCanvasViewModel - if (DataPackageComparisionDataModel?.dataPackage == dataPackage) - { - // Set the position - interactableCanvasControlItem.ItemPosition = new Vector2((float)DataPackageComparisionDataModel.dropPoint.X, (float)DataPackageComparisionDataModel.dropPoint.Y); - - // We don't need it anymore, null it so it doesn't cause trouble - DataPackageComparisionDataModel = null; - } - } - - public async Task ResetAllItemPositions() - { - foreach (var item in Items) - { - item.ItemPosition = new Vector2(0.0f, 0.0f); - } - - await SaveCanvas(); - } - - public async Task RegenerateCanvasPreview() - { - await SaveCanvas(); - } - - public async Task CanvasLoaded() - { - // Await so text doesn't flash - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - - // Items might change after the delay - NoItemsTextLoad = Items.IsEmpty(); - } - - public void ItemRearranged() - { - if (!_saveTimer.IsEnabled) - { - _saveTimer.Start(); - } - else - { - _saveTimer.Stop(); - _saveTimer.Start(); - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - for (int i = 0; i < Items.Count; i++) - { - var currentItem = Items[i]; - - currentItem.OnInfiniteCanvasItemRemovalRequestedEvent -= Item_OnInfiniteCanvasItemRemovalRequestedEvent; - currentItem.Dispose(); - } - - Items.Clear(); - - this._saveTimer.Stop(); - this._saveTimer.Tick -= SaveTimer_Tick; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/NavigationControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/NavigationControlViewModel.cs deleted file mode 100644 index dd0c8089..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/NavigationControlViewModel.cs +++ /dev/null @@ -1,332 +0,0 @@ -using System; -using System.Windows.Input; -using Windows.System; -using Microsoft.UI.Xaml.Input; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.Models; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class NavigationControlViewModel : ObservableObject, INavigationControlModel - { - #region Private Members - - private DisplayPageType _currentPage; - - #endregion - - #region Public Properties - - private bool _CanvasLayoutControlsLoad; - public bool CanvasLayoutControlsLoad - { - get => _CanvasLayoutControlsLoad; - set => SetProperty(ref _CanvasLayoutControlsLoad, value); - } - - private bool _HomepageLayoutControlsLoad; - public bool HomepageLayoutControlsLoad - { - get => _HomepageLayoutControlsLoad; - set => SetProperty(ref _HomepageLayoutControlsLoad, value); - } - - private bool _CollectionPreviewLayoutControlsLoad; - public bool CollectionPreviewLayoutControlsLoad - { - get => _CollectionPreviewLayoutControlsLoad; - set => SetProperty(ref _CollectionPreviewLayoutControlsLoad, value); - } - - private bool _NavigateBackEnabled = true; - public bool NavigateBackEnabled - { - get => _NavigateBackEnabled; - set => SetProperty(ref _NavigateBackEnabled, value); - } - - private bool _NavigateBackLoading = false; - public bool NavigateBackLoading - { - get => _NavigateBackLoading; - set => SetProperty(ref _NavigateBackLoading, value); - } - - private bool _NavigateForwardEnabled = true; - public bool NavigateForwardEnabled - { - get => _NavigateForwardEnabled; - set => SetProperty(ref _NavigateForwardEnabled, value); - } - - private bool _NavigateForwardLoading = false; - public bool NavigateForwardLoading - { - get => _NavigateForwardLoading; - set => SetProperty(ref _NavigateForwardLoading, value); - } - - private bool _GoToCanvasEnabled = true; - public bool GoToCanvasEnabled - { - get => _GoToCanvasEnabled; - set => SetProperty(ref _GoToCanvasEnabled, value); - } - - private bool _CollectionPreviewGoToCanvasEnabled = true; - public bool CollectionPreviewGoToCanvasEnabled - { - get => _CollectionPreviewGoToCanvasEnabled; - set => SetProperty(ref _CollectionPreviewGoToCanvasEnabled, value); - } - - private bool _CollectionPreviewGoToCanvasLoading; - public bool CollectionPreviewGoToCanvasLoading - { - get => _CollectionPreviewGoToCanvasLoading; - set => SetProperty(ref _CollectionPreviewGoToCanvasLoading, value); - } - - #endregion - - #region Events - - public event EventHandler OnNavigateLastRequestedEvent; - - public event EventHandler OnNavigateBackRequestedEvent; - - public event EventHandler OnNavigateFirstRequestedEvent; - - public event EventHandler OnNavigateForwardRequestedEvent; - - public event EventHandler OnGoToHomepageRequestedEvent; - - public event EventHandler OnGoToCanvasRequestedEvent; - - public event EventHandler OnCollectionPreviewNavigateBackRequestedEvent; - - public event EventHandler OnCollectionPreviewGoToCanvasRequestedEvent; - - #endregion - - #region Commands - - public ICommand NavigateLastCommand { get; private set; } - - public ICommand NavigateBackCommand { get; private set; } - - public ICommand NavigateFirstCommand { get; private set; } - - public ICommand NavigateForwardCommand { get; private set; } - - public ICommand GoToHomepageCommand { get; private set; } - - public ICommand GoToCanvasCommand { get; private set; } - - public ICommand CollectionPreviewNavigateBackCommand { get; private set; } - - public ICommand CollectionPreviewGoToCanvasCommand { get; private set; } - - public ICommand DefaultKeyboardAcceleratorInvokedCommand { get; private set; } - - #endregion - - #region Constructor - - public NavigationControlViewModel() - { - ChangeButtonLayoutOnCanvas(); - - // Create commands - NavigateLastCommand = new RelayCommand(NavigateLast); - NavigateBackCommand = new RelayCommand(NavigateBack); - NavigateFirstCommand = new RelayCommand(NavigateFirst); - NavigateForwardCommand = new RelayCommand(NavigateForward); - GoToHomepageCommand = new RelayCommand(GoToHomepage); - GoToCanvasCommand = new RelayCommand(GoToCanvas); - CollectionPreviewNavigateBackCommand = new RelayCommand(CollectionPreviewNavigateBack); - CollectionPreviewGoToCanvasCommand = new RelayCommand(CollectionPreviewGoToCanvas); - DefaultKeyboardAcceleratorInvokedCommand = new RelayCommand(DefaultKeyboardAcceleratorInvoked); - } - - #endregion - - #region Command Implementation - - private void DefaultKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs e) - { - e.Handled = true; - bool ctrl = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); - bool shift = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Shift); - bool alt = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Menu); - bool win = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Windows); - VirtualKey vkey = e.KeyboardAccelerator.Key; - uint uVkey = (uint)e.KeyboardAccelerator.Key; - - switch (c: ctrl, s: shift, a: alt, w: win, k: vkey) - { - case (c: true, s: false, a: false, w: false, k: VirtualKey.Up): - { - if (_currentPage == DisplayPageType.CanvasPage) - { - break; - } - - GoToCanvas(); - break; - } - - case (c: true, s: false, a: false, w: false, k: VirtualKey.Down): - { - if (_currentPage == DisplayPageType.Homepage) - { - break; - } - - GoToHomepage(); - break; - } - - case (c: false, s: false, a: false, w: false, k: VirtualKey.Right): - { - NavigateForward(); - break; - } - - case (c: false, s: false, a: false, w: false, k: VirtualKey.Home): - case (c: true, s: false, a: false, w: false, k: VirtualKey.Right): - { - NavigateFirst(); - break; - } - - case (c: false, s: false, a: false, w: false, k: VirtualKey.Left): - { - NavigateBack(); - break; - } - - case (c: false, s: false, a: false, w: false, k: VirtualKey.End): - { - NavigateLast(); - break; - } - - case (c: true, s: false, a: false, w: false, k: VirtualKey.Left): - { - if (_currentPage == DisplayPageType.CanvasPage) - { - NavigateLast(); - } - else - { - CollectionPreviewNavigateBack(); - } - - break; - } - } - } - - private void NavigateLast() - { - OnNavigateLastRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void NavigateBack() - { - OnNavigateBackRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void NavigateFirst() - { - OnNavigateFirstRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void NavigateForward() - { - OnNavigateForwardRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void GoToHomepage() - { - OnGoToHomepageRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void GoToCanvas() - { - OnGoToCanvasRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void CollectionPreviewNavigateBack() - { - OnCollectionPreviewNavigateBackRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - private void CollectionPreviewGoToCanvas() - { - OnCollectionPreviewGoToCanvasRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - #endregion - - #region INavigationToolBarControlModel - - public void NotifyCurrentPageChanged(DisplayPageType pageType) - { - // TODO: Instead of checking it there, hook up INavigationService event - _currentPage = pageType; - - switch (_currentPage) - { - case DisplayPageType.Homepage: - { - ChangeButtonLayoutOnHome(); - break; - } - - case DisplayPageType.CanvasPage: - { - ChangeButtonLayoutOnCanvas(); - break; - } - - case DisplayPageType.CollectionPreviewPage: - { - ChangeButtonLayoutOnCollectionPreview(); - break; - } - } - } - - #endregion - - #region Private Helpers - - private void ChangeButtonLayoutOnCanvas() - { - CanvasLayoutControlsLoad = true; - HomepageLayoutControlsLoad = false; - CollectionPreviewLayoutControlsLoad = false; - } - - private void ChangeButtonLayoutOnHome() - { - CanvasLayoutControlsLoad = false; - HomepageLayoutControlsLoad = true; - CollectionPreviewLayoutControlsLoad = false; - } - - private void ChangeButtonLayoutOnCollectionPreview() - { - CanvasLayoutControlsLoad = false; - HomepageLayoutControlsLoad = false; - CollectionPreviewLayoutControlsLoad = true; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/NavigationToolBarControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/NavigationToolBarControlViewModel.cs deleted file mode 100644 index 82c1b017..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/NavigationToolBarControlViewModel.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Windows.Input; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.Models; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.Dialogs; -using ClipboardCanvas.ViewModels.UserControls.Autopaste; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class NavigationToolBarControlViewModel : ObservableObject, INavigationToolBarControlModel - { - #region Properties - - private IDialogService DialogService { get; } = Ioc.Default.GetService(); - - public INavigationControlModel NavigationControlModel { get; set; } = new NavigationControlViewModel(); - - public ISuggestedActionsControlModel SuggestedActionsControlModel { get; set; } = new SuggestedActionsControlViewModel(); - - public IAutopasteControlModel AutopasteControlModel => AutopasteControlViewModel; - - public AutopasteControlViewModel AutopasteControlViewModel { get; set; } = new AutopasteControlViewModel(); - - private bool _IsStatusCenterButtonVisible; - public bool IsStatusCenterButtonVisible - { - get => _IsStatusCenterButtonVisible; - set => SetProperty(ref _IsStatusCenterButtonVisible, value); - } - - #endregion - - #region Commands - - public ICommand OpenSettingsCommand { get; private set; } - - #endregion - - #region Constructor - - public NavigationToolBarControlViewModel() - { - // Create Commands - OpenSettingsCommand = new AsyncRelayCommand(OpenSettings); - } - - #endregion - - #region Command Implementation - - private async Task OpenSettings() - { - await DialogService.ShowDialog(new SettingsDialogViewModel()); - } - - #endregion - - #region INavigationToolBarControlModel - - public void NotifyCurrentPageChanged(DisplayPageType pageType) - { - NavigationControlModel?.NotifyCurrentPageChanged(pageType); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/OOBE/IntroductionScreenPanelViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/OOBE/IntroductionScreenPanelViewModel.cs deleted file mode 100644 index 67e83fea..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/OOBE/IntroductionScreenPanelViewModel.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Linq; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System.Windows.Input; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.Models; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.ViewModels.UserControls.OOBE -{ - public class IntroductionScreenPanelViewModel : ObservableObject, IIntroductionScreenPanelModel - { - #region Private Members - - private readonly IIntroductionScreenPaneView _view; - - private IApplicationSettingsService ApplicationSettingsService { get; } = Ioc.Default.GetService(); - - #endregion - - #region Public Properties - - private int ItemsCount => _view.ItemsCount; - - private int _SelectedIndex = 0; - public int SelectedIndex - { - get => _SelectedIndex; - set - { - if (SetProperty(ref _SelectedIndex, value)) - { - SelectedIndexChanged(value); - } - } - } - - private string _CurrentStepText; - public string CurrentStepText - { - get => _CurrentStepText; - set => SetProperty(ref _CurrentStepText, value); - } - - private double _Progress1; - public double Progress1 - { - get => _Progress1; - set => SetProperty(ref _Progress1, value); - } - - private double _Progress2; - public double Progress2 - { - get => _Progress2; - set => SetProperty(ref _Progress2, value); - } - - private double _Progress3; - public double Progress3 - { - get => _Progress3; - set => SetProperty(ref _Progress3, value); - } - - private double _Progress4; - public double Progress4 - { - get => _Progress4; - set => SetProperty(ref _Progress4, value); - } - - private bool _BeginButtonLoad; - public bool BeginButtonLoad - { - get => _BeginButtonLoad; - set => SetProperty(ref _BeginButtonLoad, value); - } - - #endregion - - #region Commands - - public ICommand SkipCommand { get; private set; } - - public ICommand BeginCommand { get; private set; } - - #endregion - - #region Constructor - - public IntroductionScreenPanelViewModel(IIntroductionScreenPaneView view) - { - this._view = view; - - SelectedIndexChanged(0); - - // Create commands - SkipCommand = new RelayCommand(FinishOff); - BeginCommand = new RelayCommand(FinishOff); - } - - #endregion - - #region Helpers - - private void UpdateTwoHalfProgress(int index, int count, params Action[] progress) - { - int progressIndex = 0; - int progressCount = progress.Count(); - bool progressHalf = false; - - // Fill - for (int i = 0; i < count; i++) - { - if (i <= index) - { - if (!progressHalf) - { - progress[progressIndex](50.0d); - progressHalf = true; - } - else - { - progress[progressIndex](100.0d); - progressHalf = false; - progressIndex++; - } - } - else - { - if (!progressHalf) - { - // Unfill - progress[progressIndex](0.0d); - progressHalf = true; - } - else - { - progressHalf = false; - progressIndex++; - } - } - } - } - - private void SelectedIndexChanged(int newIndex) - { - UpdateTwoHalfProgress(newIndex, - _view?.ItemsCount ?? 0, - (i1) => Progress1 = i1, - (i2) => Progress2 = i2, - (i3) => Progress3 = i3, - (i4) => Progress4 = i4); - - CurrentStepText = $"{newIndex + 1}/{ItemsCount}"; - - if (newIndex == (ItemsCount - 1)) - { - BeginButtonLoad = true; - } - else - { - BeginButtonLoad = false; - } - } - - public void FinishOff() - { - _view.IntroductionPanelLoad = false; - ApplicationSettingsService.IsUserIntroduced = true; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/SettingsPanelControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/SettingsPanelControlViewModel.cs deleted file mode 100644 index f3e2f81f..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/SettingsPanelControlViewModel.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Windows.Input; -using Microsoft.UI.Xaml.Controls; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -using ClipboardCanvas.Enums; -using ClipboardCanvas.DataModels.Navigation; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class SettingsPanelControlViewModel : ObservableObject - { - #region Public Properties - - private SettingsFrameNavigationDataModel _CurrentPageNavigation; - public SettingsFrameNavigationDataModel CurrentPageNavigation - { - get => _CurrentPageNavigation; - private set => SetProperty(ref _CurrentPageNavigation, value); - } - - #endregion - - #region Commands - - public ICommand ItemInvokedCommand { get; private set; } - - #endregion - - #region Constructor - - public SettingsPanelControlViewModel() - { - CurrentPageNavigation = new SettingsFrameNavigationDataModel(SettingsPageType.General); - - // Create commands - ItemInvokedCommand = new RelayCommand(ItemInvoked); - } - - #endregion - - #region Command Implementation - - private void ItemInvoked(NavigationViewItemInvokedEventArgs e) - { - switch (e.InvokedItemContainer.Tag?.ToString()) - { - case "General": - { - CurrentPageNavigation = new SettingsFrameNavigationDataModel(SettingsPageType.General); - - break; - } - - case "Pasting": - { - CurrentPageNavigation = new SettingsFrameNavigationDataModel(SettingsPageType.Pasting); - - break; - } - - case "About": - { - CurrentPageNavigation = new SettingsFrameNavigationDataModel(SettingsPageType.About); - - break; - } - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/TextSimpleCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/TextSimpleCanvasViewModel.cs deleted file mode 100644 index aa4ea2f9..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/TextSimpleCanvasViewModel.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Windows.ApplicationModel.DataTransfer; -using System.Threading.Tasks; -using Windows.Storage; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.Helpers.Filesystem; - -namespace ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay -{ - public sealed class TextSimpleCanvasViewModel : BaseReadOnlyCanvasViewModel - { - #region Public Properties - - private string _ContentText; - public string ContentText - { - get => _ContentText; - set => SetProperty(ref _ContentText, value); - } - - #endregion - - #region Constructor - - public TextSimpleCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper text = await FilesystemOperations.ReadFileText(file); - - this._ContentText = text; - - return text; - } - - protected override async Task TryFetchDataToView() - { - OnPropertyChanged(nameof(ContentText)); - - return await Task.FromResult(SafeWrapperResult.SUCCESS); - } - - public override Task SetDataToDataPackage(DataPackage data) - { - data.SetText(ContentText); - - return Task.FromResult(true); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasViewModel.cs deleted file mode 100644 index 12556625..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/ThumbnailSimpleCanvasViewModel.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.FileProperties; -using Microsoft.UI.Xaml.Media.Imaging; -using System.IO; -using Windows.Storage.Streams; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers; - -namespace ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay -{ - public sealed class ThumbnailSimpleCanvasViewModel : BaseReadOnlyCanvasViewModel - { - #region Private Members - - private IRandomAccessStream _thumbnail; - - #endregion - - #region Public Properties - - private BitmapImage _FileIcon; - public BitmapImage FileIcon - { - get => _FileIcon; - set => SetProperty(ref _FileIcon, value); - } - - #endregion - - #region Constructor - - public ThumbnailSimpleCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - } - - #endregion - - #region Override - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - // Get thumbnail for Infinite Canvas - StorageFolder folder = item as StorageFolder; - if (folder != null && FileHelpers.IsPathEqualExtension(item.Path, Constants.FileSystem.INFINITE_CANVAS_EXTENSION)) - { - string canvasPreviewImageFileName = Constants.FileSystem.INFINITE_CANVAS_PREVIEW_IMAGE_FILENAME; - string canvasPreviewImageFilePath = Path.Combine(folder.Path, canvasPreviewImageFileName); - - SafeWrapper canvasPreviewImageFileResult = await StorageHelpers.ToStorageItemWithError(canvasPreviewImageFilePath); - if (!canvasPreviewImageFileResult) - { - return canvasPreviewImageFileResult; - } - - SafeWrapper transparentThumbnailResult = await SafeWrapperRoutines.SafeWrapAsync(() => - canvasPreviewImageFileResult.Result.GetTransparentThumbnail(ThumbnailMode.SingleItem, Constants.UI.CanvasContent.SIMPLE_CANVAS_THUMBNAIL_SIZE)); - - if (!transparentThumbnailResult) - { - transparentThumbnailResult.Result?.Dispose(); - return transparentThumbnailResult; - } - - _thumbnail = transparentThumbnailResult.Result; - } - // Get thumbnail for file - else if (item is StorageFile file) - { - _thumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem, Constants.UI.CanvasContent.SIMPLE_CANVAS_THUMBNAIL_SIZE); - } - // Get thumbnail for folder - else if (folder != null) - { - _thumbnail = await folder.GetThumbnailAsync(ThumbnailMode.SingleItem, Constants.UI.CanvasContent.SIMPLE_CANVAS_THUMBNAIL_SIZE, ThumbnailOptions.ResizeThumbnail); - } - else - { - return ItemIsNotAFileResult; - } - - _FileIcon = new BitmapImage(); - SafeWrapperResult result = await SafeWrapperRoutines.SafeWrapAsync(() => - _FileIcon.SetSourceAsync(_thumbnail).AsTask()); - - return result; - } - - protected override Task TryFetchDataToView() - { - OnPropertyChanged(nameof(FileIcon)); - - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - #endregion - - #region IDisposable - - public override void Dispose() - { - base.Dispose(); - - _thumbnail?.Dispose(); - - _thumbnail = null; - FileIcon = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasViewModel.cs deleted file mode 100644 index 245a7792..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/SimpleCanvasDisplay/UrlSimpleCanvasViewModel.cs +++ /dev/null @@ -1,343 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Windows.Storage; -using System.Threading; -using HtmlAgilityPack; -using Windows.System; -using Microsoft.UI.Xaml.Media; -using CommunityToolkit.Mvvm.Input; - -using ClipboardCanvas.DataModels.ContentDataModels; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Helpers.SafetyHelpers.ExceptionReporters; -using ClipboardCanvas.ModelViews; -using ClipboardCanvas.ViewModels.UserControls.CanvasDisplay; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.ViewModels.ContextMenu; -using System.Windows.Input; -using Windows.ApplicationModel.DataTransfer; - -namespace ClipboardCanvas.ViewModels.UserControls.SimpleCanvasDisplay -{ - public class UrlSimpleCanvasViewModel : BaseReadOnlyCanvasViewModel - { - private bool _IsLoading; - public bool IsLoading - { - get => _IsLoading; - set => SetProperty(ref _IsLoading, value); - } - - private int _Item1RowSpan; - public int Item1RowSpan - { - get => _Item1RowSpan; - set => SetProperty(ref _Item1RowSpan, value); - } - - private int _Item2RowSpan; - public int Item2RowSpan - { - get => _Item2RowSpan; - set => SetProperty(ref _Item2RowSpan, value); - } - - private string _Url; - public string Url - { - get => _Url; - set => SetProperty(ref _Url, value); - } - - private string _Title; - public string Title - { - get => _Title; - set => SetProperty(ref _Title, value); - } - - private string _SiteName; - public string SiteName - { - get => _SiteName; - set => SetProperty(ref _SiteName, value); - } - - private string _Description; - public string Description - { - get => _Description; - set => SetProperty(ref _Description, value); - } - - private bool _DescriptionExpanderLoad; - public bool DescriptionExpanderLoad - { - get => _DescriptionExpanderLoad; - set => SetProperty(ref _DescriptionExpanderLoad, value); - } - - private ImageSource _SiteIcon; - public ImageSource SiteIcon - { - get => _SiteIcon; - set => SetProperty(ref _SiteIcon, value); - } - - private bool _ContentImageLoad; - public bool ContentImageLoad - { - get => _ContentImageLoad; - set => SetProperty(ref _ContentImageLoad, value); - } - - private ImageSource _ContentImage1; - public ImageSource ContentImage1 - { - get => _ContentImage1; - set => SetProperty(ref _ContentImage1, value); - } - - private ImageSource _ContentImage2; - public ImageSource ContentImage2 - { - get => _ContentImage2; - set => SetProperty(ref _ContentImage2, value); - } - - private ImageSource _ContentImage3; - public ImageSource ContentImage3 - { - get => _ContentImage3; - set => SetProperty(ref _ContentImage3, value); - } - - private ImageSource _ContentImage4; - public ImageSource ContentImage4 - { - get => _ContentImage4; - set => SetProperty(ref _ContentImage4, value); - } - - public static List Extensions => new List() { - Constants.FileSystem.URL_CANVAS_FILE_EXTENSION - }; - - public ICommand OpenLinkCommand { get; private set; } - - public UrlSimpleCanvasViewModel(IBaseCanvasPreviewControlView view, BaseContentTypeModel contentType) - : base(StaticExceptionReporters.DefaultSafeWrapperExceptionReporter, contentType, view) - { - OpenLinkCommand = new AsyncRelayCommand(OpenLink); - } - - #region Override - - public override async Task TryLoadExistingData(CanvasItem canvasItem, BaseContentTypeModel contentType, CancellationToken cancellationToken) - { - IsLoading = true; - SafeWrapperResult result = await base.TryLoadExistingData(canvasItem, contentType, cancellationToken); - IsLoading = false; - - return result; - } - - protected override async Task SetDataFromExistingItem(IStorageItem item) - { - if (item is not StorageFile file) - { - return ItemIsNotAFileResult; - } - - SafeWrapper url = await FilesystemOperations.ReadFileText(file); - if (!AssertNoError(url)) - { - return url; - } - this.Url = url; - - // Set the document - var webGet = new HtmlWeb(); - webGet.UserAgent = @"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"; - SafeWrapper document = await SafeWrapperRoutines.SafeWrapAsync(() => webGet.LoadFromWebAsync(Url, cancellationToken)); - if (!AssertNoError(document)) - { - return document; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - HtmlNodeCollection metaTags = document.Result.DocumentNode.SelectNodes("//meta"); - - // Get metadata - SiteMetadata metadata = WebHelpers.GetMetadata(metaTags); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - this._Title = metadata.Title; - this._Description = metadata.Description; - this._SiteName = metadata.SiteName; - - if (string.IsNullOrEmpty(metadata.IconUrl)) - { - HtmlNodeCollection linkNodes = document.Result.DocumentNode.SelectNodes("//link"); - metadata.IconUrl = WebHelpers.AlternativeGetIcon(linkNodes); - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - SafeWrapper> imageUrls = await SafeWrapperRoutines.SafeWrapAsync(() => WebHelpers.FormatImageUrls(metadata.ImageUrls, Url)); - SafeWrapper imageLogo = await SafeWrapperRoutines.SafeWrapAsync(() => WebHelpers.FormatImageUrl(metadata.IconUrl, url)); - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - if (!string.IsNullOrEmpty(imageLogo)) - { - _SiteIcon = await ImagingHelpers.ToImageAsync(new Uri(imageLogo), cancellationToken); - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - - if ((Description?.Length ?? 0) > 85) - { - DescriptionExpanderLoad = true; - } - else - { - DescriptionExpanderLoad = false; - } - - // Set images - if (!imageUrls.Result.IsEmpty()) - { - ContentImageLoad = true; - - foreach (var imageLink in imageUrls.Result) - { - if (this._ContentImage1 == null) - { - _ContentImage1 = await ImagingHelpers.ToImageAsync(new Uri(imageLink), cancellationToken); - } - else if (this._ContentImage2 == null) - { - _ContentImage2 = await ImagingHelpers.ToImageAsync(new Uri(imageLink), cancellationToken); - } - else if (this._ContentImage3 == null) - { - _ContentImage3 = await ImagingHelpers.ToImageAsync(new Uri(imageLink), cancellationToken); - } - else if (this._ContentImage4 == null) - { - _ContentImage4 = await ImagingHelpers.ToImageAsync(new Uri(imageLink), cancellationToken); - } - else - { - break; - } - - if (cancellationToken.IsCancellationRequested) // Check if it's canceled - { - DiscardData(); - return SafeWrapperResult.CANCEL; - } - } - } - - return SafeWrapperResult.SUCCESS; - } - - protected override Task TryFetchDataToView() - { - OnPropertyChanged(nameof(Title)); - OnPropertyChanged(nameof(SiteName)); - OnPropertyChanged(nameof(Description)); - OnPropertyChanged(nameof(SiteIcon)); - - OnPropertyChanged(nameof(ContentImage1)); - OnPropertyChanged(nameof(ContentImage2)); - OnPropertyChanged(nameof(ContentImage3)); - OnPropertyChanged(nameof(ContentImage4)); - - return Task.FromResult(SafeWrapperResult.SUCCESS); - } - - protected override bool AssertNoError(SafeWrapperResult result) - { - bool success = base.AssertNoError(result); - if (!success) - { - Description = null; - ContentImageLoad = false; - IsLoading = false; - } - - return success; - } - - protected override void RefreshContextMenuItems() - { - base.RefreshContextMenuItems(); - - ContextMenuItems.AddFront(new MenuFlyoutItemViewModel() - { - Command = new AsyncRelayCommand(OpenFile), - IconGlyph = "\uE8A7", - Text = "Open link" - }); - } - - public override Task SetDataToDataPackage(DataPackage data) - { - data.SetText(Url); - - return Task.FromResult(true); - } - - #endregion - - #region Helpers - - private async Task OpenLink() - { - await Launcher.LaunchUriAsync(new Uri(Url)); - } - - private async Task OpenFile() - { - if (!string.IsNullOrEmpty(Url)) - { - await Launcher.LaunchUriAsync(new Uri(Url)); - } - else - { - await StorageHelpers.OpenFile(await SourceItem); - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/StatusCenter/StatusCenterItemViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/StatusCenter/StatusCenterItemViewModel.cs deleted file mode 100644 index 43161eff..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/StatusCenter/StatusCenterItemViewModel.cs +++ /dev/null @@ -1,303 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using CommunityToolkit.Mvvm.Input; -using System; -using System.Threading; -using System.Windows.Input; -using ClipboardCanvas.GlobalizationExtensions; - -using ClipboardCanvas.Contexts.Operations; -using ClipboardCanvas.Enums; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.ViewModels.UserControls.StatusCenter -{ - public class StatusCenterItemViewModel : ObservableObject, IOperationContext - { - private Progress _operationProgress; - - private CancellationTokenSource _cancellationTokenSource; - - private StatusCenterOperationType _operationType; - - private SafeWrapperResult _result; - - #region Properties - - private IStatusCenterService StatusCenterService { get; } = Ioc.Default.GetService(); - - public IProgress OperationProgress - { - get => _operationProgress; - } - - private bool _IsProgressBarVisible; - public bool IsProgressBarVisible - { - get => _IsProgressBarVisible; - private set => SetProperty(ref _IsProgressBarVisible, value); - } - - private string _OperationTitle; - public string OperationTitle - { - get => _OperationTitle; - private set => SetProperty(ref _OperationTitle, value); - } - - private string _OperationDescription; - public string OperationDescription - { - get => _OperationDescription; - set => SetProperty(ref _OperationDescription, value); - } - - private string _IconGlyph; - public string IconGlyph - { - get => _IconGlyph; - private set => SetProperty(ref _IconGlyph, value); - } - - private double _ProgressBarValue; - public double ProgressBarValue - { - get => _ProgressBarValue; - set => SetProperty(ref _ProgressBarValue, value); - } - - private bool _IsIndeterminate = true; - public bool IsIndeterminate - { - get => _IsIndeterminate; - set => SetProperty(ref _IsIndeterminate, value); - } - - private bool _ProgressPaused; - public bool ProgressPaused - { - get => _ProgressPaused; - set - { - if (SetProperty(ref _ProgressPaused, value)) - { - IsIndeterminate = true; - ProgressError = false; - } - } - } - - private bool _ProgressError; - public bool ProgressError - { - get => _ProgressError; - set - { - if (SetProperty(ref _ProgressError, value)) - { - IsIndeterminate = true; - ProgressPaused = false; - } - } - } - - public bool IsOperationStarted { get; private set; } - - public bool IsOperationFinished { get; private set; } - - public CancellationToken CancellationToken - { - get => _cancellationTokenSource.Token; - } - - #endregion - - public event EventHandler OnOperationFinishedEvent; - - public ICommand CancelOrDismissCommand { get; private set; } - - #region Constructor - - private StatusCenterItemViewModel(string operationName, StatusCenterOperationType operationType, CancellationTokenSource cancellationTokenSource) - { - this.OperationTitle = operationName; - this._operationType = operationType; - this.IsProgressBarVisible = operationType != StatusCenterOperationType.Info; - this._cancellationTokenSource = cancellationTokenSource; - - this.IconGlyph = GetIconGlyphFromOperationType(operationType); - this._operationProgress = new Progress(UpdateProgress); - - // Create commands - CancelOrDismissCommand = new RelayCommand(CancelOrDismiss); - } - - #endregion - - private void CancelOrDismiss() - { - if (_operationType != StatusCenterOperationType.Info) - { - _result = SafeWrapperResult.CANCEL; - PostCancelBanner(); - } - else - { - RemoveBanner(); - } - } - - private void UpdateProgress(double value) - { - this.IsProgressBarVisible = true; - - if (value > 0.0d) - { - OperationDescription = string.Format("StatusCenterPercentCompleted".GetLocalized2(), value.ToString("0.00")); - IsIndeterminate = false; - ProgressBarValue = value; - } - else - { - OperationDescription = "StatusCenterProcessing".GetLocalized2(); - IsIndeterminate = true; - } - } - - public static StatusCenterItemViewModel ConstructOperationBanner(string operationName, StatusCenterOperationType operationType, CancellationTokenSource cancellationTokenSource) - { - StatusCenterItemViewModel item = new StatusCenterItemViewModel(operationName, operationType, cancellationTokenSource) - { - OperationDescription = "StatusCenterStarting".GetLocalized2() - }; - - return item; - } - - public static StatusCenterItemViewModel ConstructInfoBanner(string infoTitle, string infoDescription, SafeWrapperResult result) - { - StatusCenterItemViewModel item = new StatusCenterItemViewModel(infoTitle, StatusCenterOperationType.Info, null) - { - _result = result, - OperationDescription = infoDescription - }; - - return item; - } - - private void PostCancelBanner() - { - _cancellationTokenSource?.Cancel(); - RemoveBanner(); - - string operationDescription; - switch (_operationType) - { - case StatusCenterOperationType.Paste: - { - operationDescription = "StatusCenterPastingCanceled".GetLocalized2(); - break; - } - - case StatusCenterOperationType.OverrideReference: - { - operationDescription = "StatusCenterOverwritingReferenceCanceled".GetLocalized2(); - break; - } - - default: - { - operationDescription = "StatusCenterOperationCanceled".GetLocalized2(); - break; - } - } - - var item = StatusCenterService.AppendInfoBanner("StatusCenterOperationCanceledTitle".GetLocalized2(), operationDescription, _result); - item.ProgressPaused = true; - item.IsProgressBarVisible = true; - } - - private void PostSuccessBanner() - { - RemoveBanner(); - - string operationDescription; - switch (_operationType) - { - case StatusCenterOperationType.Paste: - { - operationDescription = "StatusCenterPastingComplete".GetLocalized2(); - break; - } - - case StatusCenterOperationType.OverrideReference: - { - operationDescription = "StatusCenterOverwritingReferenceComplete".GetLocalized2(); - break; - } - - default: - { - operationDescription = "StatusCenterOperationComplete".GetLocalized2(); - break; - } - } - - var item = StatusCenterService.AppendInfoBanner("StatusCenterOperationCompleteTitle".GetLocalized2(), operationDescription, _result); - item.IconGlyph = "\uE73E"; - } - - private string GetIconGlyphFromOperationType(StatusCenterOperationType operationType) - { - switch (operationType) - { - case StatusCenterOperationType.Info: - return "\uE946"; - - case StatusCenterOperationType.Paste: - return "\uE77F"; - - case StatusCenterOperationType.OverrideReference: - return "\uE71B"; - - default: - return "\uE9CE"; // Unknown - } - } - - public void StartOperation() - { - IsIndeterminate = false; - OperationDescription = "StatusCenterCompleted".GetLocalized2(); - - if (IsOperationFinished) - { - IsOperationStarted = false; - return; - } - - IsOperationStarted = true; - } - - public void FinishOperation(SafeWrapperResult result) - { - IsOperationFinished = true; - IsOperationStarted = false; - _result = result; - - if (_result) - { - PostSuccessBanner(); - } - - OnOperationFinishedEvent?.Invoke(this, new OperationFinishedEventArgs(_result)); - } - - public void RemoveBanner() - { - StatusCenterService.RemoveBanner(this); - } - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/StatusCenter/StatusCenterViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/StatusCenter/StatusCenterViewModel.cs deleted file mode 100644 index 214cd934..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/StatusCenter/StatusCenterViewModel.cs +++ /dev/null @@ -1,55 +0,0 @@ -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Services; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using System; -using System.Collections.ObjectModel; -using System.Threading.Tasks; - -namespace ClipboardCanvas.ViewModels.UserControls.StatusCenter -{ - public class StatusCenterViewModel : ObservableObject - { - private IStatusCenterService StatusCenterService { get; } = Ioc.Default.GetService(); - - public ObservableCollection Items { get; private set; } = new ObservableCollection(); - - private bool _NoItemsTextLoad = true; - public bool NoItemsTextLoad - { - get => _NoItemsTextLoad; - set => SetProperty(ref _NoItemsTextLoad, value); - } - - public void AddItem(StatusCenterItemViewModel itemToAdd) - { - AddItem(itemToAdd, TimeSpan.Zero); - } - - public async void AddItem(StatusCenterItemViewModel itemToAdd, TimeSpan appendDelay) - { - if (appendDelay != TimeSpan.Zero) - { - await Task.Delay(appendDelay); - } - - if (!itemToAdd.IsOperationFinished) - { - NoItemsTextLoad = false; - StatusCenterService.ShowStatusCenter(); - Items.Add(itemToAdd); - } - } - - public void RemoveItem(StatusCenterItemViewModel banner) - { - Items.Remove(banner); - - if (Items.IsEmpty()) - { - NoItemsTextLoad = true; - StatusCenterService.HideStatusCenter(); - } - } - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/SuggestedActionsControlItemViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/SuggestedActionsControlItemViewModel.cs deleted file mode 100644 index 3460bfc2..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/SuggestedActionsControlItemViewModel.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Windows.Input; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Media.Imaging; -using CommunityToolkit.Mvvm.ComponentModel; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class SuggestedActionsControlItemViewModel : ObservableObject, IDisposable, IEquatable - { - #region Public Properties - - public ICommand ExecuteCommand { get; private set; } - - private string _DisplayText; - public string DisplayText - { - get => _DisplayText; - private set => SetProperty(ref _DisplayText, value); - } - - private bool _GlyphIconLoad; - public bool GlyphIconLoad - { - get => _GlyphIconLoad; - set => SetProperty(ref _GlyphIconLoad, value); - } - - private string _GlyphIcon; - public string GlyphIcon - { - get => _GlyphIcon; - set => SetProperty(ref _GlyphIcon, value); - } - - private BitmapImage _IconImage; - public BitmapImage IconImage - { - get => _IconImage; - set => SetProperty(ref _IconImage, value); - } - - private bool _IconImageLoad; - public bool IconImageLoad - { - get => _IconImageLoad; - set => SetProperty(ref _IconImageLoad, value); - } - - #endregion - - #region Constructor - - // TODO: Pass ICommand and not action - public SuggestedActionsControlItemViewModel(ICommand executeCommand, string displayText, string glyphIcon) - : this(executeCommand, displayText) - { - this.GlyphIcon = glyphIcon; - this.GlyphIconLoad = true; - this.IconImageLoad = false; - } - - public SuggestedActionsControlItemViewModel(ICommand executeCommand, string displayText, BitmapImage iconImage) - : this(executeCommand, displayText) - { - this.IconImage = iconImage; - this.GlyphIconLoad = false; - this.IconImageLoad = true; - } - - private SuggestedActionsControlItemViewModel(ICommand executeCommand, string displayText) - { - this.DisplayText = displayText; - this.ExecuteCommand = executeCommand; - } - - #endregion - - #region IEquatable - - public bool Equals(SuggestedActionsControlItemViewModel other) - { - if ( - this.DisplayText == other.DisplayText - ) - { - return true; - } - - return false; - } - - #endregion - - #region IDisposable - - public void Dispose() - { - ExecuteCommand = null; - _IconImage = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/SuggestedActionsControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/SuggestedActionsControlViewModel.cs deleted file mode 100644 index 707fb4a2..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/SuggestedActionsControlViewModel.cs +++ /dev/null @@ -1,229 +0,0 @@ -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Models; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Windows.Input; -using Windows.System; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class SuggestedActionsControlViewModel : ObservableObject, ISuggestedActionsControlModel - { - #region Public Properties - - public ObservableCollection Items { get; private set; } - - private bool _ShowNoActionsLabelSuppressed; - public bool ShowNoActionsLabelSuppressed - { - get => _ShowNoActionsLabelSuppressed; - set - { - if (value != _ShowNoActionsLabelSuppressed) - { - _ShowNoActionsLabelSuppressed = value; - - if (_ShowNoActionsLabelSuppressed) - { - NoActionsAvailableLoad = false; - } - else - { - CheckAnyActionsExist(); - } - } - } - } - - private bool _NoActionsAvailableLoad; - public bool NoActionsAvailableLoad - { - get => _NoActionsAvailableLoad; - set => SetProperty(ref _NoActionsAvailableLoad, value); - } - - #endregion - - #region Commands - - public ICommand ItemClickCommand { get; private set; } - - public ICommand DefaultKeyboardAcceleratorInvokedCommand { get; private set; } - - #endregion - - #region Constructor - - public SuggestedActionsControlViewModel() - { - Items = new ObservableCollection(); - - // Create commands - ItemClickCommand = new RelayCommand(ItemClick); - DefaultKeyboardAcceleratorInvokedCommand = new RelayCommand(DefaultKeyboardAcceleratorInvoked); - - CheckAnyActionsExist(); - } - - #endregion - - #region Command Implementation - - private void DefaultKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs e) - { - e.Handled = true; - bool ctrl = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); - bool shift = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Shift); - bool alt = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Menu); - bool win = e.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Windows); - VirtualKey vkey = e.KeyboardAccelerator.Key; - uint uVkey = (uint)e.KeyboardAccelerator.Key; - - switch (c: ctrl, s: shift, a: alt, w: win, k: vkey) - { - case (c: true, s: false, a: false, w: false, k: VirtualKey.Number1): - { - Items.ElementAtOrDefault(0)?.ExecuteCommand.Execute(null); - - break; - } - - case (c: true, s: false, a: false, w: false, k: VirtualKey.Number2): - { - Items.ElementAtOrDefault(1)?.ExecuteCommand.Execute(null); - - break; - } - - case (c: true, s: false, a: false, w: false, k: VirtualKey.Number3): - { - Items.ElementAtOrDefault(2)?.ExecuteCommand.Execute(null); - - break; - } - } - } - - private void ItemClick(ItemClickEventArgs e) - { - var clickedItem = e.ClickedItem as SuggestedActionsControlItemViewModel; - clickedItem.ExecuteCommand.Execute(null); - } - - #endregion - - #region ISuggestedActionsControlModel - - public void SetActions(IEnumerable actions) - { - if (actions == null) - { - RemoveAllActions(); - return; - } - - // The following stuff is to reuse already existing actions - - List indexesToPutActionsIn = new List(); - List itemsThatCollectionDoesntContain = Items.Where((item) => - { - if (!actions.Contains(item)) - { - indexesToPutActionsIn.Add(Items.IndexOf(item)); - - return true; - } - - return false; - }).ToList(); - - itemsThatCollectionDoesntContain.ForEach((item) => RemoveAction(item)); - - for (int i = 0; i < actions.Count(); i++) - { - if (i >= indexesToPutActionsIn.Count) - { - AddAction(actions.ElementAt(i)); - } - else - { - AddActionAt(actions.ElementAt(i), indexesToPutActionsIn[i]); - } - } - - CheckAnyActionsExist(); - } - - public void AddAction(SuggestedActionsControlItemViewModel action) - { - if (!Items.Contains(action)) - { - Items.Add(action); - } - } - - public void AddActionAt(SuggestedActionsControlItemViewModel action, int index) - { - if (!Items.Contains(action)) - { - Items.Insert(index, action); - } - } - - public void RemoveAction(SuggestedActionsControlItemViewModel action) - { - action.Dispose(); - Items.Remove(action); - - CheckAnyActionsExist(); - } - - public void RemoveActionAt(int index) - { - if (index < 0 || index > Items.Count || Items.IsEmpty()) - { - return; - } - - Items[index].Dispose(); - Items.RemoveAt(index); - - CheckAnyActionsExist(); - } - - public void RemoveAllActions() - { - Items.DisposeClear(); - CheckAnyActionsExist(); - } - - #endregion - - #region Private Helpers - - private void CheckAnyActionsExist() - { - if (ShowNoActionsLabelSuppressed) - { - return; - } - - if (Items.IsEmpty()) - { - NoActionsAvailableLoad = true; - } - else - { - NoActionsAvailableLoad = false; - } - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/UserControls/WindowTitleBarControlViewModel.cs b/ClipboardCanvas/ViewModels/UserControls/WindowTitleBarControlViewModel.cs deleted file mode 100644 index e2271440..00000000 --- a/ClipboardCanvas/ViewModels/UserControls/WindowTitleBarControlViewModel.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using CommunityToolkit.Mvvm.ComponentModel; -using System.Windows.Input; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.DependencyInjection; - -using ClipboardCanvas.Models; -using ClipboardCanvas.GlobalizationExtensions; -using ClipboardCanvas.Services; - -namespace ClipboardCanvas.ViewModels.UserControls -{ - public class WindowTitleBarControlViewModel : ObservableObject, IWindowTitleBarControlModel - { - #region Public Properties - - private bool _StandardTitleBarLoad; - public bool StandardTitleBarLoad - { - get => _StandardTitleBarLoad; - set => SetProperty(ref _StandardTitleBarLoad, value); - } - - private string _StandardTitleBarText; - public string StandardTitleBarText - { - get => _StandardTitleBarText; - set => SetProperty(ref _StandardTitleBarText, value); - } - - private bool _TwoSideTitleBarLoad; - public bool TwoSideTitleBarLoad - { - get => _TwoSideTitleBarLoad; - private set => SetProperty(ref _TwoSideTitleBarLoad, value); - } - - private string _TitleBarFirstSideText; - public string TitleBarFirstSideText - { - get => _TitleBarFirstSideText; - private set => SetProperty(ref _TitleBarFirstSideText, value); - } - - private string _TitleBarSecondSideText; - public string TitleBarSecondSideText - { - get => _TitleBarSecondSideText; - set => SetProperty(ref _TitleBarSecondSideText, value); - } - - private bool _IsInRestrictedAccess; - public bool IsInRestrictedAccess - { - get => _IsInRestrictedAccess; - set => SetProperty(ref _IsInRestrictedAccess, value); - } - - private bool _ShowTitleUnderline; - public bool ShowTitleUnderline - { - get => _ShowTitleUnderline; - set => SetProperty(ref _ShowTitleUnderline, value); - } - - private IApplicationService ApplicationService { get; } = Ioc.Default.GetService(); - - #endregion - - #region Events - - public event EventHandler OnSwitchApplicationViewRequestedEvent; - - #endregion - - #region Commands - - public ICommand SwitchApplicationViewCommand { get; } - - #endregion - - #region Constructor - - public WindowTitleBarControlViewModel() - { - // Create commands - SwitchApplicationViewCommand = new RelayCommand(SwitchApplicationView); - } - - #endregion - - #region Command Implementation - - private void SwitchApplicationView() - { - OnSwitchApplicationViewRequestedEvent?.Invoke(this, EventArgs.Empty); - } - - #endregion - - #region IWindowTitleBarControlModel - - public void SetTitleBarForDefaultView() - { - StandardTitleBarText = "Clipboard Canvas"; - StandardTitleBarLoad = true; - TwoSideTitleBarLoad = false; - } - - public void SetTitleBarForCollectionsView() - { - StandardTitleBarText = "Clipboard Canvas"; - StandardTitleBarLoad = true; - TwoSideTitleBarLoad = false; - } - - public void SetTitleBarForCanvasView(string collectionName) - { - TwoSideTitleBarLoad = true; - TitleBarFirstSideText = "CurrentCollection".GetLocalized2(); - TitleBarSecondSideText = collectionName; - - StandardTitleBarLoad = false; - } - - public void SetTitleBarForCollectionPreview(string collectionName) - { - TwoSideTitleBarLoad = true; - TitleBarFirstSideText = "CollectionPreview".GetLocalized2(); - TitleBarSecondSideText = collectionName; - - StandardTitleBarLoad = false; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineSectionItemViewModel.cs b/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineSectionItemViewModel.cs deleted file mode 100644 index 2b0f88db..00000000 --- a/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineSectionItemViewModel.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Windows.Input; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using System.IO; - -using ClipboardCanvas.Models; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.Models.Configuration; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Services; -using ClipboardCanvas.DataModels.Navigation; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.Helpers.Filesystem; - -namespace ClipboardCanvas.ViewModels.Widgets.Timeline -{ - public class TimelineSectionItemViewModel : ObservableObject, IDisposable - { - #region Properties - - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - public IReadOnlyCanvasPreviewModel ReadOnlyCanvasPreviewModel { get; set; } - - public ICollectionModel CollectionModel { get; private set; } - - public CanvasItem CanvasItem { get; private set; } - - private string _FileName; - public string FileName - { - get => _FileName; - set => SetProperty(ref _FileName, value); - } - - public string SourceCollectionName - { - get => $"in {CollectionModel.DisplayName}"; - } - - #endregion - - #region Events - - public event EventHandler OnRemoveSectionItemRequestedEvent; - - #endregion - - #region Commands - - public ICommand OpenFileCommand { get; private set; } - - public ICommand OpenCanvasCommand { get; private set; } - - public ICommand ShowInCollectionPreviewCommand { get; private set; } - - public ICommand RemoveFromSectionCommand { get; private set; } - - #endregion - - #region Constructor - - public TimelineSectionItemViewModel(ICollectionModel collectionModel, CanvasItem canvasItem) - { - this.CollectionModel = collectionModel; - this.CanvasItem = canvasItem; - - // Create commands - OpenFileCommand = new AsyncRelayCommand(OpenFile); - OpenCanvasCommand = new AsyncRelayCommand(OpenCanvas); - ShowInCollectionPreviewCommand = new RelayCommand(ShowInCollectionPreview); - RemoveFromSectionCommand = new RelayCommand(RemoveFromSection); - } - - #endregion - - #region Command Implementation - - private async Task OpenFile() - { - await StorageHelpers.OpenFile(await CanvasItem.SourceItem); - } - - private async Task OpenCanvas() - { - if (!CollectionModel.IsCollectionInitialized && !CollectionModel.IsCollectionInitializing) - { - // Initialize if not initialized - await CollectionModel.InitializeCollectionItems(); - - CollectionModel.UpdateIndex(CollectionModel.FindCollectionItem(CanvasItem)); - NavigationService.OpenCanvasPage(CollectionModel); - } - else if (CollectionModel.IsCollectionInitialized) - { - if (InfiniteCanvasItem.IsInfiniteCanvasAsParent(CanvasItem)) - { - string parentPath = Path.GetDirectoryName(CanvasItem.AssociatedItem.Path); - CollectionModel.UpdateIndex(CollectionModel.FindCollectionItem(parentPath)); - } - else - { - CollectionModel.UpdateIndex(CollectionModel.FindCollectionItem(CanvasItem)); - } - - NavigationService.OpenCanvasPage(CollectionModel); - } - } - - private void ShowInCollectionPreview() - { - CanvasItem itemToSelect; - - if (InfiniteCanvasItem.IsInfiniteCanvasAsParent(CanvasItem)) - { - string parentPath = Path.GetDirectoryName(CanvasItem.AssociatedItem.Path); - itemToSelect = CollectionModel.FindCollectionItem(parentPath); - } - else - { - itemToSelect = CanvasItem; - } - - NavigationService.OpenCollectionPreviewPage(CollectionModel, new CollectionPreviewPageNavigationParameterModel(CollectionModel, CanvasHelpers.GetDefaultCanvasType(), itemToSelect)); - } - - private void RemoveFromSection() - { - this.OnRemoveSectionItemRequestedEvent?.Invoke(this, new RemoveSectionItemRequestedEventArgs(this)); - } - - #endregion - - #region Helpers - - public async Task UpdateFileName() - { - FileName = Path.GetFileName(await CanvasHelpers.SafeGetCanvasItemPath(CanvasItem)); - } - - public async Task InitializeSectionItemContent(bool withLoadDelay = true) - { - await UpdateFileName(); - - if (withLoadDelay) - { - // Wait for control to load - await Task.Delay(Constants.UI.CONTROL_LOAD_DELAY); - } - - if (ReadOnlyCanvasPreviewModel != null) - { - return await ReadOnlyCanvasPreviewModel.TryLoadExistingData(CanvasItem, null, TimelineWidgetViewModel.LoadCancellationToken.Token); - } - else - { - return SafeWrapperResult.CANCEL; - } - } - - public TimelineSectionItemConfigurationModel ConstructConfigurationModel() - { - return new TimelineSectionItemConfigurationModel( - CanvasItem.AssociatedItem.Path, - CollectionModel.ConstructConfigurationModel()); - } - - #endregion - - #region IDisposable - - public void Dispose() - { - this.ReadOnlyCanvasPreviewModel?.Dispose(); - - this.ReadOnlyCanvasPreviewModel = null; - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineSectionViewModel.cs b/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineSectionViewModel.cs deleted file mode 100644 index 8456680f..00000000 --- a/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineSectionViewModel.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Linq; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using System.Threading.Tasks; - -using ClipboardCanvas.Models; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Models.Configuration; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.EventArguments; -using ClipboardCanvas.Services; -using ClipboardCanvas.Enums; -using ClipboardCanvas.Helpers.SafetyHelpers; - -namespace ClipboardCanvas.ViewModels.Widgets.Timeline -{ - public class TimelineSectionViewModel : ObservableObject, IDisposable - { - #region Properties - - private INavigationService NavigationService { get; } = Ioc.Default.GetService(); - - public ObservableCollection Items { get; private set; } - - public DateTime SectionDate { get; private set; } - - private string _FormattedTime; - public string FormattedTime - { - get => _FormattedTime; - set => SetProperty(ref _FormattedTime, value); - } - - private bool _IsSectionEmpty = true; - public bool IsSectionEmpty - { - get => _IsSectionEmpty; - set => SetProperty(ref _IsSectionEmpty, value); - } - - #endregion - - #region Events - - public event EventHandler OnRemoveSectionRequestedEvent; - - #endregion - - #region Constructor - - public TimelineSectionViewModel(DateTime sectionDate) - { - this.SectionDate = sectionDate; - - this.Items = new ObservableCollection(); - - SetFormattedDate(this.SectionDate); - } - - #endregion - - #region Event Handlers - - private void Item_OnRemoveSectionItemRequestedEvent(object sender, RemoveSectionItemRequestedEventArgs e) - { - RemoveItem(e.itemViewModel); - } - - #endregion - - #region Helpers - - private void SetFormattedDate(DateTime dateTime) - { - if (dateTime == DateTime.Today) - { - FormattedTime = "Today"; - } - else if ((DateTime.Now.DayOfYear - dateTime.DayOfYear) == 1) - { - FormattedTime = "Yesterday"; - } - else - { - if (dateTime.Year < DateTime.Now.Year) - { - FormattedTime = dateTime.ToString("dd MMMM yyyy"); - } - else - { - FormattedTime = dateTime.ToString("dd MMMM"); - } - } - } - - public async Task> AddItem(ICollectionModel collectionModel, CanvasItem canvasItem, bool suppressSettingsUpdate = false) - { - var item = new TimelineSectionItemViewModel(collectionModel, canvasItem); - return (item, await AddItemMode(item, true, suppressSettingsUpdate)); - } - - public async Task> AddItemBack(ICollectionModel collectionModel, CanvasItem canvasItem, bool suppressSettingsUpdate = false) - { - var item = new TimelineSectionItemViewModel(collectionModel, canvasItem); - return (item, await AddItemMode(item, false, suppressSettingsUpdate)); - } - - private async Task AddItemMode(TimelineSectionItemViewModel timelineSectionItem, bool front, bool suppressSettingsUpdate = false) - { - if (front) - { - Items.AddFront(timelineSectionItem); - } - else - { - Items.Add(timelineSectionItem); - } - timelineSectionItem.OnRemoveSectionItemRequestedEvent += Item_OnRemoveSectionItemRequestedEvent; - - if (Items.Count > Constants.UI.Timeline.MAX_ITEMS_PER_SECTION) - { - RemoveItem(Items.Last(), suppressSettingsUpdate); - } - - IsSectionEmpty = false; - - if (!suppressSettingsUpdate) - { - SettingsSerializationHelpers.UpdateUserTimelineSetting(); - } - if (NavigationService.CurrentPage == DisplayPageType.Homepage) - { - return await timelineSectionItem.InitializeSectionItemContent(); - } - else - { - return SafeWrapperResult.SUCCESS; - } - } - - public bool RemoveItem(TimelineSectionItemViewModel timelineSectionItem, bool suppressSettingsUpdate = false) - { - if (timelineSectionItem == null) - { - return false; - } - - bool result = Items.Remove(timelineSectionItem); - timelineSectionItem.OnRemoveSectionItemRequestedEvent -= Item_OnRemoveSectionItemRequestedEvent; - - if (Items.IsEmpty()) - { - IsSectionEmpty = true; - OnRemoveSectionRequestedEvent?.Invoke(this, new RemoveSectionRequestedEventArgs(this)); // This won't remove today section - } - - if (!suppressSettingsUpdate) - { - SettingsSerializationHelpers.UpdateUserTimelineSetting(); - } - - return result; - } - - public TimelineSectionItemViewModel FindTimelineSectionItem(CanvasItem canvasItem) - { - return Items.FirstOrDefault((item) => item.CanvasItem.AssociatedItem.Path == canvasItem?.AssociatedItem.Path); - } - - public TimelineSectionConfigurationModel ConstructConfigurationModel() - { - TimelineSectionConfigurationModel configurationModel = new TimelineSectionConfigurationModel(SectionDate); - - foreach (var item in Items) - { - configurationModel.items.Add(item.ConstructConfigurationModel()); - } - - return configurationModel; - } - - public void Clean() - { - foreach (var item in Items) - { - item.OnRemoveSectionItemRequestedEvent -= Item_OnRemoveSectionItemRequestedEvent; - } - } - - #endregion - - #region IDisposable - - public void Dispose() - { - Items?.DisposeAll(); - } - - #endregion - } -} diff --git a/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineWidgetViewModel.cs b/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineWidgetViewModel.cs deleted file mode 100644 index 05a2ea1a..00000000 --- a/ClipboardCanvas/ViewModels/Widgets/Timeline/TimelineWidgetViewModel.cs +++ /dev/null @@ -1,253 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using System; -using System.Collections.ObjectModel; -using System.Threading; -using System.Threading.Tasks; -using Windows.Storage; -using System.Linq; -using System.Collections.Generic; - -using ClipboardCanvas.Models.Configuration; -using ClipboardCanvas.Extensions; -using ClipboardCanvas.Services; -using ClipboardCanvas.ViewModels.UserControls.Collections; -using ClipboardCanvas.Helpers; -using ClipboardCanvas.DataModels; -using ClipboardCanvas.Helpers.Filesystem; -using ClipboardCanvas.Helpers.SafetyHelpers; -using ClipboardCanvas.EventArguments; - -namespace ClipboardCanvas.ViewModels.Widgets.Timeline -{ - public class TimelineWidgetViewModel : ObservableObject - { - #region Members - - public static CancellationTokenSource LoadCancellationToken = new CancellationTokenSource(); - - #endregion - - #region Properties - - public static ObservableCollection Sections { get; private set; } = new ObservableCollection(); - - public static bool IsInitialized { get; private set; } - - #endregion - - #region Constructor - - public TimelineWidgetViewModel() - { - } - - #endregion - - #region Event Handlers - - private static void Item_OnRemoveSectionRequestedEvent(object sender, RemoveSectionRequestedEventArgs e) - { - if (!IsTodaySection(e.sectionViewModel)) - { - RemoveSection(e.sectionViewModel); - } - } - - #endregion - - #region Helpers - - private static bool IsTodaySection(TimelineSectionViewModel section) - { - if (section == null) - { - return false; - } - - DateTime now = DateTime.Now; - - return section.SectionDate.DayOfYear == now.DayOfYear && section.SectionDate.Year == now.Year; - } - - public static TimelineSectionViewModel GetOrCreateTodaySection() - { - TimelineSectionViewModel todaySection = TimelineWidgetViewModel.Sections.FirstOrDefault((item) => IsTodaySection(item)); - - if (todaySection == null) - { - todaySection = TimelineWidgetViewModel.AddSection(DateTime.Today); - } - - return todaySection; - } - - public static void RemoveSection(TimelineSectionViewModel timelineSection, bool suppressSettingsUpdate = false) - { - timelineSection.OnRemoveSectionRequestedEvent -= Item_OnRemoveSectionRequestedEvent; - timelineSection.Clean(); - timelineSection.Dispose(); - - Sections.Remove(timelineSection); - - if (!suppressSettingsUpdate) - { - SettingsSerializationHelpers.UpdateUserTimelineSetting(); - } - } - - public static TimelineSectionViewModel AddSection(DateTime sectionDate, bool suppressSettingsUpdate = false) - { - var item = new TimelineSectionViewModel(sectionDate); - AddSectionMode(item, true, suppressSettingsUpdate); - - return item; - } - - public static TimelineSectionViewModel AddSectionBack(DateTime sectionDate, bool suppressSettingsUpdate = false) - { - var item = new TimelineSectionViewModel(sectionDate); - AddSectionMode(item, false, suppressSettingsUpdate); - - return item; - } - - private static void AddSectionMode(TimelineSectionViewModel timelineSection, bool front, bool suppressSettingsUpdate = false) - { - if (front) - { - Sections.AddFront(timelineSection); - } - else - { - Sections.Add(timelineSection); - } - - timelineSection.OnRemoveSectionRequestedEvent += Item_OnRemoveSectionRequestedEvent; - - if (Sections.Count > Constants.UI.Timeline.MAX_SECTIONS) - { - RemoveSection(Sections.Last(), suppressSettingsUpdate); - } - - if (!suppressSettingsUpdate) - { - SettingsSerializationHelpers.UpdateUserTimelineSetting(); - } - } - - public static async Task ReloadAllSections() - { - try - { - if (!await CheckIfTimelineEnabled(false)) - { - return; - } - - IsInitialized = true; - ITimelineSettingsService timelineSettingsService = Ioc.Default.GetService(); - TimelineConfigurationModel configurationModel = timelineSettingsService.UserTimeline; - - if (configurationModel != null) - { - List sortedSections = - configurationModel.sections.OrderBy((x) => x.sectionDateTime).ToList(); - - foreach (var configurationSection in sortedSections) - { - var section = AddSection(configurationSection.sectionDateTime, true); - - foreach (var configurationSectionItem in configurationSection.items) - { - SafeWrapper item = - await StorageHelpers.ToStorageItemWithError(configurationSectionItem - ?.collectionItemPath); - - if (item) - { - BaseCollectionViewModel baseCollectionViewModel = - CollectionsWidgetViewModel.FindCollection(configurationSectionItem - .collectionConfigurationModel); - if (baseCollectionViewModel != null) - { - CanvasItem canvasItem = new CanvasItem(item.Result); - await section.AddItemBack(baseCollectionViewModel, canvasItem, true); - } - } - } - } - } - - RemoveEmptySections(); - RemoveDuplicateSections(); - - // Add "Today" section - GetOrCreateTodaySection(); - } - catch (Exception ex) - { - LoggingHelpers.SafeLogExceptionToFile(ex); - } - } - - private static void RemoveEmptySections() - { - for (int i = 0; i < Sections.Count; i++) - { - if (Sections[i].Items.IsEmpty()) - { - RemoveSection(Sections[i]); - i--; - } - } - } - - private static void RemoveDuplicateSections() - { - for (int i = 0; i < Sections.Count; i++) - { - // The list is sorted - for (int j = i + 1; j < Sections.Count; j++) - { - if (Sections[i].SectionDate == Sections[j].SectionDate) - { - RemoveSection(Sections[i]); - j--; - } - } - } - } - - public static TimelineConfigurationModel ConstructConfigurationModel() - { - TimelineConfigurationModel configurationModel = new TimelineConfigurationModel(); - - foreach (var item in Sections) - { - configurationModel.sections.Add(item.ConstructConfigurationModel()); - } - - return configurationModel; - } - - public static async Task CheckIfTimelineEnabled(bool initializeIfNecessary = true) - { - IUserSettingsService userSettingsService = Ioc.Default.GetService(); - - // Don't load if we don't use it - if (!userSettingsService.ShowTimelineOnHomepage) - { - return false; - } - else if (!IsInitialized && initializeIfNecessary) - { - await ReloadAllSections(); - } - - return true; - } - - #endregion - } -} diff --git a/ClipboardCanvas/app.manifest b/ClipboardCanvas/app.manifest deleted file mode 100644 index 639d9fd8..00000000 --- a/ClipboardCanvas/app.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - true/PM - PerMonitorV2, PerMonitor - - - diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..bf15db4f --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,5 @@ + + + true + + \ No newline at end of file diff --git a/Privacy.md b/Privacy.md index 1c7ed116..04f47176 100644 --- a/Privacy.md +++ b/Privacy.md @@ -1,9 +1,29 @@ -Privacy Policy ---- +# Privacy Policy -
-Clipboard Canvas does not collect, store or publish any personal information with anyone. +###### Effective date: February 25th, 2024 -Clipboard Canvas collects anonymous AppCenter Analytics data and data provided by AppCenter Crashes analytics to improve the application based on collected information and crash reports. +This Privacy Policy ("Policy") for Clipboard Canvas ("we", "us", or "our") describes how and why we collect, store, use, and disclose information about users ("you", "your") when you use our services ("Services") which include our desktop and mobile applications (the "Application", "Clipboard Canvas"). By using our Services, you acknowledge and consent to the practices described in this Policy. -The data aquired by AppCenter is anonymous and free of any user's personal data. +## Table of Contents + +1. Information We Collect +2. How We Use Your Information +3. Changes to This Privacy Policy + +## Information We Collect + +**Diagnostic Information.** Our Application collects non-personably identifiable diagnostic data such as fault analysis and performance logs. This information may include technical details about your device, such as its make, model, operating system, and Application version. In addition, SecureFolderFS may store log files containing diagnostic information on the user's device. These files are not shared with us by default. + +**Usage Information.** We collect non-identifiable information about your use of our Services, including but not limited to interactions within the Application, enabled user preferences (Application settings), and usage patterns. Furthermore, our Application uses certain Microsoft services including Microsoft AppCenter, and Microsoft Partner Center to collect usage data. To learn more about how data is collected, used, and disclosed by Microsoft and its subsidiaries, please review the Microsoft Privacy Policy Statement available here: https://privacy.microsoft.com/en-us/privacystatement + +Please note that any information we collect is non-identifiable and does not include any personal data. We do not share collected information with any third parties. + +## How We Use Collected Information + +**Mitigate Reliability Issues.** We may use the aggregated information to diagnose and address any unexpected issues that may arise during the use of our Application. This may include analyzing diagnostic data, such as fault analysis and performance logs, to identify the root cause of the issue and develop a solution to resolve it. + +**Identify Usage Trends.** We may use the information to identify and analyze usage trends for our Services and Applications. This may include analyzing aggregated usage data to understand how users interact with our Services and to measure their utilization intensity. We may use this analysis to improve the functionality, usability, and performance of our Services and to inform future development decisions. + +## Changes to This Privacy Policy + +We may modify, update, or amend this Privacy Policy occasionally to reflect changes made to our Application. When we change this Policy in a material manner, we will inform you of such changes by updating the 'Effective date' notice. It is your responsibility to review this Privacy Policy periodically to stay informed of any updates. Your continued use of the Services after any modifications to this Policy constitutes your acceptance of such changes. diff --git a/global.json b/global.json deleted file mode 100644 index 126149e6..00000000 --- a/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "sdk": { - "version": "6.0.100", - "rollForward": "latestMajor" - } -} diff --git a/src/ClipboardCanvas.Sdk/AppModels/CollectionModel.cs b/src/ClipboardCanvas.Sdk/AppModels/CollectionModel.cs new file mode 100644 index 00000000..cc34ebe8 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/CollectionModel.cs @@ -0,0 +1,58 @@ +using ClipboardCanvas.Sdk.Models; +using OwlCore.Storage; +using System.Collections.Specialized; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels +{ + public sealed class CollectionModel : IDataSourceModel + { + private IFolderWatcher? _folderWatcher; + + /// + public IFolder Source { get; } + + /// + public string Name { get; } + + /// + public event NotifyCollectionChangedEventHandler? CollectionChanged + { + add + { + if (_folderWatcher is not null) + _folderWatcher.CollectionChanged += value; + } + remove + { + if (_folderWatcher is not null) + _folderWatcher.CollectionChanged -= value; + } + } + + public CollectionModel(IFolder folder, string? name = null) + { + Source = folder; + Name = name ?? folder.Name; + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + if (_folderWatcher is not null) + return; + + if (Source is not IMutableFolder mutableFolder) + return; + + _folderWatcher = await mutableFolder.GetFolderWatcherAsync(cancellationToken); + } + + /// + public void Dispose() + { + _folderWatcher?.Dispose(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/CollectionSourceModel.cs b/src/ClipboardCanvas.Sdk/AppModels/CollectionSourceModel.cs new file mode 100644 index 00000000..97646265 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/CollectionSourceModel.cs @@ -0,0 +1,105 @@ +using ClipboardCanvas.Sdk.DataModels; +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using CommunityToolkit.Mvvm.DependencyInjection; +using OwlCore.Storage; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels +{ + /// + public sealed class CollectionSourceModel : Collection, ICollectionSourceModel + { + private ICollectionPersistenceService CollectionPersistenceService { get; } = Ioc.Default.GetRequiredService(); + + private IStorageService StorageService { get; } = Ioc.Default.GetRequiredService(); + + /// + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + /// + protected override void ClearItems() + { + if (CollectionPersistenceService.SavedCollections is not null) + CollectionPersistenceService.SavedCollections.Clear(); + + base.ClearItems(); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset)); + } + + /// + protected override void InsertItem(int index, IDataSourceModel item) + { + // Update saved collections + CollectionPersistenceService.SavedCollections ??= new List(); + CollectionPersistenceService.SavedCollections.Insert(index, new(item.Source.Id, item.Name)); + + // Add to cache + base.InsertItem(index, item); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Add, item, index)); + } + + /// + protected override void RemoveItem(int index) + { + var removedItem = this[index]; + + // Remove persisted + if (CollectionPersistenceService.SavedCollections is not null) + CollectionPersistenceService.SavedCollections.RemoveAt(index); + + // Remove from cache + base.RemoveItem(index); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Remove, removedItem, index)); + } + + /// + protected override void SetItem(int index, IDataSourceModel item) + { + if (CollectionPersistenceService.SavedCollections is null) + return; + + CollectionPersistenceService.SavedCollections[index] = new(item.Source.Id, item.Name); + + var oldItem = this[index]; + base.SetItem(index, item); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Replace, item, oldItem, index)); + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + await CollectionPersistenceService.InitAsync(cancellationToken); + + // Clear previous collections + Items.Clear(); + + CollectionPersistenceService.SavedCollections ??= new List(); + foreach (var item in CollectionPersistenceService.SavedCollections) + { + if (item.Id is null) + continue; + + var folder = await StorageService.TryGetFolderAsync(item.Id, cancellationToken); + if (folder is not IModifiableFolder modifiableFolder) + continue; + + var collectionModel = new CollectionModel(modifiableFolder, item.Name); + Items.Add(collectionModel); + + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Add, item)); + } + } + + /// + public Task SaveAsync(CancellationToken cancellationToken = default) + { + return CollectionPersistenceService.SaveAsync(cancellationToken); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/Database/BaseDatabaseModel.cs b/src/ClipboardCanvas.Sdk/AppModels/Database/BaseDatabaseModel.cs new file mode 100644 index 00000000..717baa85 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/Database/BaseDatabaseModel.cs @@ -0,0 +1,46 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels.Database +{ + /// + /// Represents a dictionary-based database model. + /// + public abstract class BaseDatabaseModel : IDatabaseModel + { + protected readonly IAsyncSerializer serializer; + protected readonly SemaphoreSlim storageSemaphore; + protected readonly ConcurrentDictionary settingsCache; + + protected BaseDatabaseModel(IAsyncSerializer serializer) + { + this.serializer = serializer; + storageSemaphore = new(1, 1); + settingsCache = new(); + } + + /// + public abstract TValue? GetValue(string key, Func? defaultValue = null); + + /// + public abstract bool SetValue(string key, TValue? value); + + /// + public abstract Task InitAsync(CancellationToken cancellationToken = default); + + /// + public abstract Task SaveAsync(CancellationToken cancellationToken = default); + + /// + public virtual void Dispose() + { + storageSemaphore.Dispose(); + settingsCache.Clear(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/Database/ObservableDatabaseModel.cs b/src/ClipboardCanvas.Sdk/AppModels/Database/ObservableDatabaseModel.cs new file mode 100644 index 00000000..12f6d2e7 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/Database/ObservableDatabaseModel.cs @@ -0,0 +1,71 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.Collections.Specialized; +using System.IO; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels.Database +{ + /// + public abstract class ObservableDatabaseModel : BaseDatabaseModel + { + /// + /// Gets the used to report database changes. + /// + protected abstract INotifyCollectionChanged? NotifyCollectionChanged { get; } + + protected ObservableDatabaseModel(IAsyncSerializer serializer) + : base(serializer) + { + } + + private async void Settings_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + await OnCollectionChangedAsync(e); + } + + /// + /// Starts capturing any changes that occur to the database storage using . + /// + /// + /// If the is null, is raised. + /// + protected void StartCapturingChanges() + { + _ = NotifyCollectionChanged ?? throw new NullReferenceException($"{nameof(NotifyCollectionChanged)} was null."); + NotifyCollectionChanged.CollectionChanged += Settings_CollectionChanged; + } + + /// + /// Captures the recent changes of the database storage. + /// + /// The class which represents the change that occurred. + /// A that represents the asynchronous operation. + protected virtual async Task OnCollectionChangedAsync(NotifyCollectionChangedEventArgs e) + { + if (e.Action != NotifyCollectionChangedAction.Replace) + return; + + if (e.NewItems?[0] is not string changedItem) + return; + + await ProcessChangeAsync(changedItem); + } + + /// + /// Updates the state of this database model based on the recent storage changes. + /// + /// The item that was changed. + /// A that represents the asynchronous operation. + protected abstract Task ProcessChangeAsync(string changedItem); + + /// + public override void Dispose() + { + if (NotifyCollectionChanged is null) + return; + + NotifyCollectionChanged.CollectionChanged -= Settings_CollectionChanged; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/Database/SingleFileDatabaseModel.cs b/src/ClipboardCanvas.Sdk/AppModels/Database/SingleFileDatabaseModel.cs new file mode 100644 index 00000000..08724d7d --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/Database/SingleFileDatabaseModel.cs @@ -0,0 +1,160 @@ +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using OwlCore.Storage; +using System; +using System.Collections; +using System.Collections.Specialized; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels.Database +{ + /// + public sealed class SingleFileDatabaseModel : ObservableDatabaseModel + { + private readonly string _fileName; + private readonly IModifiableFolder _settingsFolder; + private IFile? _databaseFile; + private IFolderWatcher? _folderWatcher; + + /// + protected override INotifyCollectionChanged? NotifyCollectionChanged => _folderWatcher; + + public SingleFileDatabaseModel(string fileName, IModifiableFolder settingsFolder, IAsyncSerializer serializer) + : base(serializer) + { + _fileName = fileName; + _settingsFolder = settingsFolder; + } + + /// + public override TValue? GetValue(string key, Func? defaultValue = null) + where TValue : default + { + if (settingsCache.TryGetValue(key, out var value)) + return value.GetValue() ?? (defaultValue is not null ? defaultValue() : default); + + var fallback = defaultValue is not null ? defaultValue() : default; + settingsCache[key] = new NonSerializedData(fallback); + + return fallback; + } + + /// + public override bool SetValue(string key, TValue? value) + where TValue : default + { + settingsCache[key] = new NonSerializedData(value); + return true; + } + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + try + { + await storageSemaphore.WaitAsync(cancellationToken); + await EnsureSettingsFileAsync(cancellationToken); + + _ = _databaseFile ?? throw new InvalidOperationException("The database file was not properly initialized."); + + await using var stream = await _databaseFile!.OpenStreamAsync(FileAccess.Read, FileShare.Read, cancellationToken); + var settings = await serializer.DeserializeAsync(stream, cancellationToken); + + // Reset the cache + settingsCache.Clear(); + + if (settings is null) // No settings saved, set cache to empty and return + return; + + foreach (DictionaryEntry item in settings) + { + if (item.Key is not string key) + continue; + + if (item.Value is ISerializedModel serializedData) + settingsCache[key] = serializedData; + else + settingsCache[key] = new NonSerializedData(item.Value); + } + } + finally + { + _ = storageSemaphore.Release(); + } + } + + /// + public override async Task SaveAsync(CancellationToken cancellationToken = default) + { + try + { + await storageSemaphore.WaitAsync(cancellationToken); + await EnsureSettingsFileAsync(cancellationToken); + + _ = _databaseFile ?? throw new InvalidOperationException("The database file was not properly initialized."); + + await using var dataStream = await _databaseFile.OpenStreamAsync(FileAccess.ReadWrite, FileShare.Read, cancellationToken); + await using var settingsStream = await serializer.SerializeAsync(settingsCache, cancellationToken); + + // Overwrite existing content + dataStream.Position = 0L; + dataStream.SetLength(0L); + + // Copy contents + settingsStream.Position = 0L; + await settingsStream.CopyToAsync(dataStream, cancellationToken); + + return true; + } + finally + { + _ = storageSemaphore.Release(); + } + } + + /// + protected override async Task ProcessChangeAsync(string changedItem) + { + if (_databaseFile?.Id == changedItem) + await InitAsync(); + } + + private async Task EnsureSettingsFileAsync(CancellationToken cancellationToken) + { + _databaseFile ??= await _settingsFolder.CreateFileAsync(_fileName, false, cancellationToken); + if (_folderWatcher is null && _settingsFolder is IMutableFolder mutableFolder) + { + _folderWatcher = await mutableFolder.GetFolderWatcherAsync(cancellationToken); + StartCapturingChanges(); + } + } + + /// + public override void Dispose() + { + _folderWatcher?.Dispose(); + base.Dispose(); + } + + /// + private sealed class NonSerializedData : ISerializedModel + { + private readonly object? _value; + + public NonSerializedData(object? value) + { + _value = value; + } + + /// + public T? GetValue() + { + return _value.TryCast(); + } + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/DoubleSerializedStreamSerializer.cs b/src/ClipboardCanvas.Sdk/AppModels/DoubleSerializedStreamSerializer.cs new file mode 100644 index 00000000..2dea2837 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/DoubleSerializedStreamSerializer.cs @@ -0,0 +1,96 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Shared.Extensions; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels +{ + /// + public sealed class DoubleSerializedStreamSerializer : StreamSerializer + { + /// + /// A single instance of . + /// + public new static DoubleSerializedStreamSerializer Instance { get; } = new(); + + /// + public override Task SerializeAsync(object? data, Type dataType, CancellationToken cancellationToken = default) + { + if (data is IDictionary serializedDictionary) + { + var actualDictionary = new Dictionary(); + foreach (DictionaryEntry item in serializedDictionary) + { + actualDictionary[item.Key] = item.Value is ISerializedModel serializedModel + ? serializedModel.GetValue() + : item.Value; + } + + return base.SerializeAsync(actualDictionary, actualDictionary.GetType(), cancellationToken); + } + + return base.SerializeAsync(data, dataType, cancellationToken); + } + + /// + public override async Task DeserializeAsync(Stream serialized, Type dataType, CancellationToken cancellationToken = default) + { + var deserialized = await base.DeserializeAsync(serialized, dataType, cancellationToken); + if (deserialized is IDictionary deserializedDictionary) + { + var actualDictionary = new Dictionary(); + foreach (DictionaryEntry item in deserializedDictionary) + { + actualDictionary[item.Key] = item.Value is JsonElement jsonElement + ? new JsonSerializedData(jsonElement) + : new NonSerializedData(item.Value); + } + + return actualDictionary; + } + + return deserialized; + } + + /// + private sealed class JsonSerializedData : ISerializedModel + { + private readonly JsonElement _jsonElement; + private object? _deserialized; + + public JsonSerializedData(JsonElement jsonElement) + { + _jsonElement = jsonElement; + } + + /// + public T? GetValue() + { + _deserialized ??= _jsonElement.Deserialize(); + return _deserialized.TryCast(); + } + } + + /// + private sealed class NonSerializedData : ISerializedModel + { + private readonly object? _value; + + public NonSerializedData(object? value) + { + _value = value; + } + + /// + public T? GetValue() + { + return _value.TryCast(); + } + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/SettingsModel.cs b/src/ClipboardCanvas.Sdk/AppModels/SettingsModel.cs new file mode 100644 index 00000000..53e6a8ff --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/SettingsModel.cs @@ -0,0 +1,79 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels +{ + /// + public abstract class SettingsModel : IPersistable, IAsyncInitialize, INotifyPropertyChanged + { + /// + /// Gets the where settings are stored. + /// + protected abstract IDatabaseModel SettingsDatabase { get; } + + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + public virtual Task InitAsync(CancellationToken cancellationToken = default) + { + return SettingsDatabase.InitAsync(cancellationToken); + } + + /// + public virtual Task SaveAsync(CancellationToken cancellationToken = default) + { + return SettingsDatabase.SaveAsync(cancellationToken); + } + + /// + /// Gets a value of a setting defined by . + /// + /// The type of value. + /// Retrieves the default value. If is null, returns the default value of . + /// The name of the setting. + /// A requested setting. The value is determined by the availability of the setting in the storage or by the . + [return: NotNullIfNotNull(nameof(defaultValue))] + protected virtual T? GetSetting(Func? defaultValue = null, [CallerMemberName] string settingName = "") + { + if (string.IsNullOrEmpty(settingName)) + return defaultValue is not null ? defaultValue() : default; + + return SettingsDatabase.GetValue(settingName, defaultValue); + } + + /// + /// Sets a setting value defined by . + /// + /// The type of value. + /// The value to be stored. + /// The name of the setting. + /// If the setting has been updated, returns true otherwise false. + protected virtual bool SetSetting(T? value, [CallerMemberName] string settingName = "") + { + if (string.IsNullOrEmpty(settingName)) + return false; + + var result = SettingsDatabase.SetValue(settingName, value); + if (result) + OnPropertyChanged(settingName); + + return result; + } + + /// + /// Invokes event notifying that a value of a specific setting has changed. + /// + /// The name of the property whose value has changed. + protected void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new(propertyName)); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/StreamSerializer.cs b/src/ClipboardCanvas.Sdk/AppModels/StreamSerializer.cs new file mode 100644 index 00000000..dd566643 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/StreamSerializer.cs @@ -0,0 +1,52 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.AppModels +{ + /// + /// Implementation for that uses to serialize/deserialize JSON. + /// + public class StreamSerializer : IAsyncSerializer + { + private JsonSerializerOptions DefaultSerializerOptions { get; } + + /// + /// A single instance of . + /// + public static StreamSerializer Instance { get; } = new(); + + protected StreamSerializer() + { + DefaultSerializerOptions = new() + { + WriteIndented = true + }; + } + + /// + public virtual async Task SerializeAsync(object? data, Type dataType, CancellationToken cancellationToken = default) + { + var outputStream = new MemoryStream(); + + // Serialize data to stream + await JsonSerializer.SerializeAsync(outputStream, data, dataType, DefaultSerializerOptions, cancellationToken); + outputStream.Position = 0; + + return outputStream; + } + + /// + public virtual async Task DeserializeAsync(Stream serialized, Type dataType, CancellationToken cancellationToken = default) + { + if (serialized.CanSeek) + serialized.Position = 0L; + + var deserialized = await JsonSerializer.DeserializeAsync(serialized, dataType, DefaultSerializerOptions, cancellationToken); + return deserialized; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/AppModels/TypeClassification.cs b/src/ClipboardCanvas.Sdk/AppModels/TypeClassification.cs new file mode 100644 index 00000000..374f0dd4 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/AppModels/TypeClassification.cs @@ -0,0 +1,29 @@ +using ClipboardCanvas.Shared.Enums; + +namespace ClipboardCanvas.Sdk.AppModels +{ + public struct TypeClassification + { + /// + /// Gets the MIME content type. + /// + public string MimeType { get; } + + /// + /// Gets the hint which may or may not indicate the correct type. + /// + public TypeHint TypeHint { get; } + + /// + /// Gets the content extension, if any. + /// + public string? Extension { get; } + + public TypeClassification(string mimeType, TypeHint typeHint, string? extension = null) + { + MimeType = mimeType; + TypeHint = typeHint; + Extension = extension; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ClipboardCanvas.Sdk.csproj b/src/ClipboardCanvas.Sdk/ClipboardCanvas.Sdk.csproj new file mode 100644 index 00000000..3676c4f0 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ClipboardCanvas.Sdk.csproj @@ -0,0 +1,20 @@ + + + + net7.0 + disable + latest + enable + + + + + + + + + + + + + diff --git a/src/ClipboardCanvas.Sdk/DataModels/CollectionDataModel.cs b/src/ClipboardCanvas.Sdk/DataModels/CollectionDataModel.cs new file mode 100644 index 00000000..8b987ac1 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/DataModels/CollectionDataModel.cs @@ -0,0 +1,7 @@ +using System; + +namespace ClipboardCanvas.Sdk.DataModels +{ + [Serializable] + public sealed record class CollectionDataModel(string? Id, string? Name); +} diff --git a/src/ClipboardCanvas.Sdk/Enums/DialogOption.cs b/src/ClipboardCanvas.Sdk/Enums/DialogOption.cs new file mode 100644 index 00000000..eacab57b --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Enums/DialogOption.cs @@ -0,0 +1,9 @@ +namespace ClipboardCanvas.Sdk.Enums +{ + public enum DialogOption + { + Cancel = 0, + Primary = 1, + Secondary = 2 + } +} diff --git a/src/ClipboardCanvas.Sdk/Enums/IconType.cs b/src/ClipboardCanvas.Sdk/Enums/IconType.cs new file mode 100644 index 00000000..389a8583 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Enums/IconType.cs @@ -0,0 +1,9 @@ +namespace ClipboardCanvas.Sdk.Enums +{ + public enum IconType + { + Share, + Open, + Edit, + } +} diff --git a/src/ClipboardCanvas.Sdk/Enums/NavigationType.cs b/src/ClipboardCanvas.Sdk/Enums/NavigationType.cs new file mode 100644 index 00000000..090a0bae --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Enums/NavigationType.cs @@ -0,0 +1,23 @@ +namespace ClipboardCanvas.Sdk.Enums +{ + /// + /// Defines types of navigation. + /// + public enum NavigationType + { + /// + /// Navigation is performed to an arbitrary target which may or may not preserve the navigation timeline. + /// + Chained = 0, + + /// + /// Navigating backward. + /// + Backward = 1, + + /// + /// Navigating forward. + /// + Forward = 2 + } +} diff --git a/src/ClipboardCanvas.Sdk/Extensions/NavigationExtensions.cs b/src/ClipboardCanvas.Sdk/Extensions/NavigationExtensions.cs new file mode 100644 index 00000000..796d68be --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Extensions/NavigationExtensions.cs @@ -0,0 +1,77 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Extensions +{ + public static class NavigationExtensions + { + public static T? TryGetView(this INavigationService navigationService) + where T : class, IViewDesignation + { + return (T?)navigationService.Views.FirstOrDefault(x => x is T); + } + + public static async Task TryNavigateAsync(this INavigationService navigationService, Func? initializer = null, bool useInitialization = true) + where T : class, IViewDesignation + { + var view = navigationService.TryGetView(); + var isNewView = view is null; + + view ??= initializer?.Invoke() ?? null; + if (view is null) + return false; + + // Initialize if the target supports IAsyncInitialize and doesn't already exist + if (isNewView && useInitialization && view is IAsyncInitialize supportsAsyncInitialize) + _ = supportsAsyncInitialize.InitAsync(); + + // Navigate to the target + return await navigationService.NavigateAsync(view); + } + + public static async Task TryNavigateAsync(this INavigationService navigationService, Func>? initializer = null, bool useInitialization = true) + where T : class, IViewDesignation + { + var view = navigationService.TryGetView(); + var isNewView = view is null; + + if (view is null && initializer is not null) + view = await initializer.Invoke(); + else + return false; + + // Initialize if the target supports IAsyncInitialize and doesn't already exist + if (isNewView && useInitialization && view is IAsyncInitialize supportsAsyncInitialize) + _ = supportsAsyncInitialize.InitAsync(); + + // Navigate to the target + return await navigationService.NavigateAsync(view); + } + + public static async Task TryNavigateAndForgetAsync(this INavigationService navigationService, IViewDesignation view) + { + var navigated = false; + IViewDesignation? currentView = null; + + try + { + if (navigationService.CurrentView is not null) + { + navigationService.Views.Remove(navigationService.CurrentView); + currentView = navigationService.CurrentView; + } + + navigated = await navigationService.NavigateAsync(view); + return navigated; + } + finally + { + if (navigated) + (currentView as IDisposable)?.Dispose(); + } + } + } +} diff --git a/src/ClipboardCanvas.Sdk/Extensions/OverlayExtensions.cs b/src/ClipboardCanvas.Sdk/Extensions/OverlayExtensions.cs new file mode 100644 index 00000000..f95d9411 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Extensions/OverlayExtensions.cs @@ -0,0 +1,39 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Helpers; + +namespace ClipboardCanvas.Sdk.Extensions +{ + public static class OverlayExtensions + { + public static IResult ParseOverlayOption(this DialogOption dialogOption) + { + return dialogOption switch + { + DialogOption.Cancel => Result.Failure(dialogOption), + _ => Result.Success(dialogOption) + }; + } + + public static bool Positive(this IResult result) + { + return result is IResult optionResult + ? optionResult.Value == DialogOption.Primary + : result.Successful; + } + + public static bool InBetween(this IResult result) + { + return result is IResult optionResult + ? optionResult.Value == DialogOption.Secondary + : !result.Successful; + } + + public static bool Aborted(this IResult result) + { + return result is IResult optionResult + ? optionResult.Value == DialogOption.Cancel + : !result.Successful; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/Extensions/StorageExtensions.File.cs b/src/ClipboardCanvas.Sdk/Extensions/StorageExtensions.File.cs new file mode 100644 index 00000000..d2c1e97d --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Extensions/StorageExtensions.File.cs @@ -0,0 +1,138 @@ +using ClipboardCanvas.Sdk.Storage; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Helpers; +using OwlCore.Storage; +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Extensions +{ + public static partial class StorageExtensions + { + /// + public static async Task OpenStreamAsync(this IFile file, FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default) + { + if (file is IFileExtended fileExtended) + return await fileExtended.OpenStreamAsync(access, share, cancellationToken); + + // TODO: Check if the file inherits from ILockableStorable and ensure a disposable handle to it via Stream bridge + return await file.OpenStreamAsync(access, cancellationToken); + } + + /// If successful, returns a ; otherwise null. + /// + public static async Task TryOpenStreamAsync(this IFile file, FileAccess access, CancellationToken cancellationToken = default) + { + try + { + return await file.OpenStreamAsync(access, cancellationToken); + } + catch (Exception) + { + return null; + } + } + + /// If successful, returns a ; otherwise null. + /// + public static async Task TryOpenStreamAsync(this IFile file, FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default) + { + try + { + return await OpenStreamAsync(file, access, share, cancellationToken); + } + catch (Exception) + { + return null; + } + } + + #region With Result + + /// Value is depending on whether the stream was successfully opened on the file. + /// + public static async Task> OpenStreamWithResultAsync(this IFile file, FileAccess access, CancellationToken cancellationToken = default) + { + try + { + return Result.Success(await file.OpenStreamAsync(access, cancellationToken)); + } + catch (Exception ex) + { + return Result.Failure(ex); + } + } + + /// Value is depending on whether the stream was successfully opened on the file. + /// + public static async Task> OpenStreamWithResultAsync(this IFile file, FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default) + { + try + { + if (file is IFileExtended fileExtended) + return Result.Success(await fileExtended.OpenStreamAsync(access, share, cancellationToken)); + + // TODO: Check if the file inherits from ILockableStorable and ensure a disposable handle to it via Stream bridge + return Result.Success(await file.OpenStreamAsync(access, cancellationToken)); + } + catch (Exception ex) + { + return Result.Failure(ex); + } + } + + #endregion + + /// + /// Copies contents of to overwriting existing data. + /// + /// The source file to copy from. + /// The destination file to copy to. + /// A that cancels this action. + /// A that represents the asynchronous operation. + public static async Task CopyContentsToAsync(this IFile source, IFile destination, CancellationToken cancellationToken = default) + { + await using var sourceStream = await source.OpenStreamAsync(FileAccess.Read, cancellationToken); + await using var destinationStream = await destination.OpenStreamAsync(FileAccess.Read, cancellationToken); + await sourceStream.CopyToAsync(destinationStream, cancellationToken); + } + + /// + /// Writes into specified overwriting existing content. + /// + /// The file to write to. + /// The text to write. + /// The encoding to use when writing. Default is . + /// A that cancels this action. + /// A that represents the asynchronous operation. + public static async Task WriteAllTextAsync(this IFile file, string text, Encoding? encoding = null, CancellationToken cancellationToken = default) + { + await using var fileStream = await file.OpenStreamAsync(FileAccess.ReadWrite, cancellationToken); + + // Reset the stream + fileStream.SetLength(0L); + fileStream.Seek(0L, SeekOrigin.Begin); + + await using var streamWriter = new StreamWriter(fileStream, encoding ?? Encoding.UTF8); + await streamWriter.WriteAsync(text.AsMemory(), cancellationToken); + } + + /// + /// Reads all text contents from specified . + /// + /// The file to read from. + /// The encoding to use when reading. Default is . + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is that contains text found in the file. + public static async Task ReadAllTextAsync(this IFile file, Encoding? encoding = null, CancellationToken cancellationToken = default) + { + await using var fileStream = await file.OpenStreamAsync(FileAccess.Read, cancellationToken); + using var streamReader = new StreamReader(fileStream, encoding ?? Encoding.UTF8); + + return await streamReader.ReadToEndAsync(cancellationToken); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/Extensions/StorageExtensions.Service.cs b/src/ClipboardCanvas.Sdk/Extensions/StorageExtensions.Service.cs new file mode 100644 index 00000000..2960f764 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Extensions/StorageExtensions.Service.cs @@ -0,0 +1,52 @@ +using ClipboardCanvas.Sdk.Services; +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Extensions +{ + public static partial class StorageExtensions + { + /// + /// Tries to retrieve a folder associated with . + /// + /// The service. + /// The unique ID of the folder to retrieve. + /// A that cancels this action. + /// A that represents the asynchronous operation. If successful, value is that represents the folder; otherwise null. + public static async Task TryGetFolderAsync(this IStorageService storageService, string id, CancellationToken cancellationToken = default) + { + try + { + var item = await storageService.GetFromBookmarkAsync(id, cancellationToken); + return item as IChildFolder; + } + catch (Exception ex) + { + _ = ex; + return null; + } + } + + /// + /// Tries to retrieve a file associated with . + /// + /// The service. + /// The unique ID of the file to retrieve. + /// A that cancels this action. + /// A that represents the asynchronous operation. If successful, value is that represents the file; otherwise null. + public static async Task TryGetFileAsync(this IStorageService storageService, string id, CancellationToken cancellationToken = default) + { + try + { + var item = await storageService.GetFromBookmarkAsync(id, cancellationToken); + return item as IChildFile; + } + catch (Exception) + { + return null; + } + } + } +} diff --git a/src/ClipboardCanvas.Sdk/Helpers/FormattingHelpers.cs b/src/ClipboardCanvas.Sdk/Helpers/FormattingHelpers.cs new file mode 100644 index 00000000..ca683368 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Helpers/FormattingHelpers.cs @@ -0,0 +1,17 @@ +using System; +using System.Globalization; + +namespace ClipboardCanvas.Sdk.Helpers +{ + public static class FormattingHelpers + { + public static string GetDateFileName(string extension, CultureInfo? culture = null) + { + // TODO: Use CultureInfo in the future to format the date string + const string FILE_DATE_NAME_FORMAT = "HHmm dd-MM-yyyy"; + + var now = DateTime.Now; + return $"{now.ToString(FILE_DATE_NAME_FORMAT)}{extension}"; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/Models/ICanvasModel.cs b/src/ClipboardCanvas.Sdk/Models/ICanvasModel.cs new file mode 100644 index 00000000..99d591c3 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Models/ICanvasModel.cs @@ -0,0 +1,8 @@ +using OwlCore.Storage; + +namespace ClipboardCanvas.Sdk.Models +{ + public interface ICanvasModel : IStorableChild // TODO: Is this needed? + { + } +} diff --git a/src/ClipboardCanvas.Sdk/Models/ICollectionSourceModel.cs b/src/ClipboardCanvas.Sdk/Models/ICollectionSourceModel.cs new file mode 100644 index 00000000..e9417787 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Models/ICollectionSourceModel.cs @@ -0,0 +1,13 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace ClipboardCanvas.Sdk.Models +{ + /// + /// Manages the list of user-saved collections. + /// + public interface ICollectionSourceModel : ICollection, IPersistable, IAsyncInitialize, INotifyCollectionChanged + { + } +} diff --git a/src/ClipboardCanvas.Sdk/Models/IDataSourceModel.cs b/src/ClipboardCanvas.Sdk/Models/IDataSourceModel.cs new file mode 100644 index 00000000..8aae3973 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Models/IDataSourceModel.cs @@ -0,0 +1,23 @@ +using ClipboardCanvas.Shared.ComponentModel; +using OwlCore.Storage; +using System; +using System.Collections.Specialized; + +namespace ClipboardCanvas.Sdk.Models +{ + /// + /// Represents a data source where canvases reside. + /// + public interface IDataSourceModel : INotifyCollectionChanged, IAsyncInitialize + { + /// + /// Gets the source folder of the data. + /// + IFolder Source { get; } + + /// + /// Gets the name of this source model. + /// + string Name { get; } + } +} diff --git a/src/ClipboardCanvas.Sdk/Models/IDatabaseModel.cs b/src/ClipboardCanvas.Sdk/Models/IDatabaseModel.cs new file mode 100644 index 00000000..c5948ea0 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Models/IDatabaseModel.cs @@ -0,0 +1,30 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System; + +namespace ClipboardCanvas.Sdk.Models +{ + /// + /// Represents a database to store data identified by . + /// + /// The key to identify data with. + public interface IDatabaseModel : IPersistable, IAsyncInitialize, IDisposable + { + /// + /// Gets a value from the database. + /// + /// The type of value. + /// The name of the value to get. + /// Retrieves the default value. If is null, returns the default value of . + /// A value from the database. The value is determined by the availability in the storage or by the . + TValue? GetValue(TKey key, Func? defaultValue = null); + + /// + /// Sets a value in the database. + /// + /// The type of value. + /// The name of the value to set. + /// The value to be stored. + /// If the value has been updated in the database, returns true otherwise false. + bool SetValue(TKey key, TValue? value); + } +} diff --git a/src/ClipboardCanvas.Sdk/Models/IMediaSource.cs b/src/ClipboardCanvas.Sdk/Models/IMediaSource.cs new file mode 100644 index 00000000..3adb0928 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Models/IMediaSource.cs @@ -0,0 +1,8 @@ +using System; + +namespace ClipboardCanvas.Sdk.Models +{ + public interface IMediaSource : IDisposable + { + } +} diff --git a/src/ClipboardCanvas.Sdk/Models/ISerializedModel.cs b/src/ClipboardCanvas.Sdk/Models/ISerializedModel.cs new file mode 100644 index 00000000..e038fd77 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Models/ISerializedModel.cs @@ -0,0 +1,15 @@ +namespace ClipboardCanvas.Sdk.Models +{ + /// + /// Represents a model that holds serialized data. + /// + public interface ISerializedModel + { + /// + /// Retrieves requested of the serialized data. + /// + /// The type of data to retrieve. + /// Deserialized data of type . If the value cannot be deserialized, returns default. + T? GetValue(); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/IApplicationService.cs b/src/ClipboardCanvas.Sdk/Services/IApplicationService.cs new file mode 100644 index 00000000..110f25ac --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IApplicationService.cs @@ -0,0 +1,53 @@ +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// A service that interacts with common app-related APIs. + /// + public interface IApplicationService + { + /// + /// Gets the name that uniquely identifies a platform. + /// + string Platform { get; } + + /// + /// Gets the version of the app. + /// + Version AppVersion { get; } + + /// + /// Gets the version information of the platform that the app is running on. + /// + /// + /// The return value may contain information like OS build version, release number, and other platform-specific members. + /// + /// A containing version data. + string GetSystemVersion(); + + /// + /// Launches an URI from app. This can be an URL, folder path, etc. + /// + /// The URI to launch. + /// A that represents the asynchronous operation. + Task OpenUriAsync(Uri uri); + + /// + /// Tries to schedule the application for restart. + /// + /// A that represents the asynchronous operation. + Task TryRestartAsync(); + + /// + /// Launches the associated app to handle the file being opened. + /// + /// The file to open in a handler. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task LaunchHandlerAsync(IFile file, CancellationToken cancellationToken); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/ICanvasService.cs b/src/ClipboardCanvas.Sdk/Services/ICanvasService.cs new file mode 100644 index 00000000..8e25824b --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/ICanvasService.cs @@ -0,0 +1,13 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.ViewModels.Controls.Canvases; +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + public interface ICanvasService + { + Task GetCanvasForStorableAsync(IStorableChild storable, IDataSourceModel sourceModel, CancellationToken cancellationToken); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/IClipboardService.cs b/src/ClipboardCanvas.Sdk/Services/IClipboardService.cs new file mode 100644 index 00000000..fe947a45 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IClipboardService.cs @@ -0,0 +1,91 @@ +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Enums; +using OwlCore.Storage; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using ClipboardCanvas.Sdk.AppModels; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// Represents a service for interacting with the clipboard. + /// + public interface IClipboardService : INotifyCollectionChanged + { + /// + /// Gets the current content of the clipboard. + /// + /// A that cancels this action. + /// + /// A that represents the asynchronous operation. + /// If clipboard is not empty, returns the current clipboard content represented by ; otherwise null. + /// + Task GetContentAsync(CancellationToken cancellationToken); + + /// + /// Sets the clipboard content to the specified . + /// + /// The image to set in the clipboard. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task SetImageAsync(IImage image, CancellationToken cancellationToken); + + /// + /// Sets the clipboard content to the specified . + /// + /// The text to set in the clipboard. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task SetTextAsync(string text, CancellationToken cancellationToken); + + /// + /// Sets the clipboard content to the specified . + /// + /// The collection of storage to set in the clipboard. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task SetStorageAsync(IEnumerable storage, CancellationToken cancellationToken); + } + + /// + /// Represents a clipboard data object. + /// + public interface IClipboardData + { + /// + /// Gets the type of the clipboard data. + /// + TypeClassification Classification { get; } + + /// + /// Gets the text that is contained within the clipboard data. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is that represents the clipboard data. + Task GetTextAsync(CancellationToken cancellationToken); + + /// + /// Gets the image that is contained within the clipboard data. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is that represents the clipboard data. + Task GetImageAsync(CancellationToken cancellationToken); + + /// + /// Gets the stream that contains the clipboard data. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is that represents the clipboard data. + Task OpenReadAsync(CancellationToken cancellationToken); + + /// + /// Gets a collection of storage items in the clipboard data. + /// + /// A that cancels this action. + /// Returns an async operation represented by of type for storage items found in the clipboard data. + IAsyncEnumerable GetStorageAsync(CancellationToken cancellationToken); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/ICollectionPersistenceService.cs b/src/ClipboardCanvas.Sdk/Services/ICollectionPersistenceService.cs new file mode 100644 index 00000000..c7df79e0 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/ICollectionPersistenceService.cs @@ -0,0 +1,17 @@ +using ClipboardCanvas.Sdk.DataModels; +using ClipboardCanvas.Shared.ComponentModel; +using System.Collections.Generic; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// Represents a service to manage collection-related data. + /// + public interface ICollectionPersistenceService : IPersistable, IAsyncInitialize + { + /// + /// Gets or sets the list of saved collections. + /// + IList? SavedCollections { get; set; } + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/IDocumentService.cs b/src/ClipboardCanvas.Sdk/Services/IDocumentService.cs new file mode 100644 index 00000000..41395e5e --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IDocumentService.cs @@ -0,0 +1,18 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + public interface IDocumentService + { + /// + /// Reads the PDF file and translates it into . + /// + /// The source of the PDF file. + /// A that cancels this action. + /// A new instance of that represents the PDF file. + Task ReadPdfAsync(Stream pdfStream, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/src/ClipboardCanvas.Sdk/Services/IFileExplorerService.cs b/src/ClipboardCanvas.Sdk/Services/IFileExplorerService.cs new file mode 100644 index 00000000..a75a4366 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IFileExplorerService.cs @@ -0,0 +1,35 @@ +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// A service that interacts with the system file explorer. + /// + public interface IFileExplorerService + { + /// + /// Opens the app folder. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task OpenAppFolderAsync(CancellationToken cancellationToken = default); + + /// + /// Opens provided in file explorer. + /// + /// The folder to open file explorer in. + /// The optional item to highlight. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task OpenInFileExplorerAsync(IFolder folder, IStorableChild? highlight = null, CancellationToken cancellationToken = default); + + /// + /// Awaits the user input and picks single folder from the file explorer dialog. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. If successful and a folder has been picked, returns ; otherwise null. + Task PickFolderAsync(CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/ILocalizationService.cs b/src/ClipboardCanvas.Sdk/Services/ILocalizationService.cs new file mode 100644 index 00000000..51b19b66 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/ILocalizationService.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// A service that manages localization of the app. + /// + public interface ILocalizationService + { + /// + /// Gets the current language of the app. + /// + CultureInfo CurrentCulture { get; } + + /// + /// Gets all supported languages by the app. + /// + IReadOnlyList AppLanguages { get; } + + /// + /// Tries to gets the localized string for the . + /// + /// The resource key that associates with translations. + /// If successful, returns a localized string for the ; otherwise null. + string? TryGetString(string resourceKey); + + /// + /// Sets the current language of the app. + /// + /// The language to set. + /// A that represents the asynchronous operation. + Task SetCultureAsync(CultureInfo cultureInfo); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/IMediaService.cs b/src/ClipboardCanvas.Sdk/Services/IMediaService.cs new file mode 100644 index 00000000..3dded1c4 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IMediaService.cs @@ -0,0 +1,37 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Shared.ComponentModel; +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// A service used to manage app image assets. + /// + public interface IMediaService + { + Task SaveImageAsync(IImage image, IFile destination, CancellationToken cancellationToken); + + /// + /// Reads the bitmap from provided and converts it to . + /// + /// The image file to read. + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is representation of the bitmap file. + Task ReadImageAsync(IFile file, CancellationToken cancellationToken); + + /// + /// Retrieves an image based on the contents of the . + /// + /// The data source. + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is representation of the collection icon. + Task GetCollectionIconAsync(IDataSourceModel collectionModel, CancellationToken cancellationToken); + + Task GetVideoPlaybackAsync(IFile file, CancellationToken cancellationToken); + + IImage? GetIcon(IconType iconType); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/INavigationService.cs b/src/ClipboardCanvas.Sdk/Services/INavigationService.cs new file mode 100644 index 00000000..c0234123 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/INavigationService.cs @@ -0,0 +1,52 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// A service used for target-to-target navigation of s. + /// + public interface INavigationService : IDisposable + { + /// + /// An event that is fired when navigation occurs. + /// + event EventHandler? NavigationChanged; + + /// + /// Gets the value that determines whether this service is initialized and can handle navigation. + /// + bool IsInitialized { get; } + + /// + /// Gets the currently navigated-to target. + /// + IViewDesignation? CurrentView { get; } + + /// + /// Gets the collection of all previously navigated-to targets. + /// + ICollection Views { get; } + + /// + /// Navigates to a given and updates existing . + /// + /// The target to navigate to. + /// A that represents the asynchronous operation. If successful, returns true; otherwise false. + Task NavigateAsync(IViewDesignation view); + + /// + /// Tries to navigate to the previous target, if possible. + /// + /// A that represents the asynchronous operation. If the navigation target was present, returns true; otherwise false. + Task GoBackAsync(); + + /// + /// Tries to navigate to the next target, if possible. + /// + /// A that represents the asynchronous operation. If the navigation target was present, returns true; otherwise false. + Task GoForwardAsync(); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/IOverlayService.cs b/src/ClipboardCanvas.Sdk/Services/IOverlayService.cs new file mode 100644 index 00000000..997c3073 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IOverlayService.cs @@ -0,0 +1,22 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// A service to manage dialogs and overlays. + /// + public interface IOverlayService + { + /// + /// Shows the provided as an overlay. + /// If an overlay is already shown, a new one will be presented on top of the existing one. + /// + /// The view to present. + /// A that represents the asynchronous operation. Value is of the operation. + /// + /// The return value may contain additional information about the chosen option. + /// + Task ShowAsync(IViewable viewable); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/ISettingsService.cs b/src/ClipboardCanvas.Sdk/Services/ISettingsService.cs new file mode 100644 index 00000000..a308509a --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/ISettingsService.cs @@ -0,0 +1,21 @@ +using ClipboardCanvas.Sdk.Services.Settings; +using ClipboardCanvas.Shared.ComponentModel; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// The main settings service to manage other settings services. + /// + public interface ISettingsService : IPersistable, IAsyncInitialize + { + /// + /// Gets the service which is used to store application-related settings. + /// + IAppSettings AppSettings { get; } + + /// + /// Gets the service which is used to store user-related settings. + /// + IUserSettings UserSettings { get; } + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/IStorageService.cs b/src/ClipboardCanvas.Sdk/Services/IStorageService.cs new file mode 100644 index 00000000..75d8b4d8 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/IStorageService.cs @@ -0,0 +1,35 @@ +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Services +{ + /// + /// Provides an abstract storage layer for accessing the file system. + /// + public interface IStorageService + { + /// + /// Gets the application folder. + /// + /// + /// + Task GetAppFolderAsync(CancellationToken cancellationToken = default); + + /// + /// Gets the item with associated bookmark . + /// + /// The unique bookmark ID of the item to retrieve. + /// A that cancels this action. + /// A that represents the asynchronous operation. If the item associated with the bookmark ID is found, returns . + Task GetFromBookmarkAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Removes application access from bookmarked file system resource. + /// + /// The instance that was bookmarked to remove. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task RemoveBookmark(IStorable storable, CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/ITextRecognitionService.cs b/src/ClipboardCanvas.Sdk/Services/ITextRecognitionService.cs new file mode 100644 index 00000000..65073fe8 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/ITextRecognitionService.cs @@ -0,0 +1,18 @@ +using ClipboardCanvas.Sdk.ViewModels.Controls.Documents; +using ClipboardCanvas.Shared.ComponentModel; +using System.Collections.Generic; +using System.Threading; + +namespace ClipboardCanvas.Sdk.Services +{ + public interface ITextRecognitionService + { + /// + /// Recognizes the text from provided and returns a collection of recognized words. + /// + /// The image to recognize the text from. + /// A that cancels this action. + /// An instance of of that represent recognized words. + IAsyncEnumerable RecognizeAsync(IImage image, CancellationToken cancellationToken); + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/Settings/IAppSettings.cs b/src/ClipboardCanvas.Sdk/Services/Settings/IAppSettings.cs new file mode 100644 index 00000000..7da71f93 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/Settings/IAppSettings.cs @@ -0,0 +1,31 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System.ComponentModel; + +namespace ClipboardCanvas.Sdk.Services.Settings +{ + /// + /// An interface for storing application configuration and settings. + /// + public interface IAppSettings : IPersistable, IAsyncInitialize, INotifyPropertyChanged + { + /// + /// Gets or sets the value containing information about the app theme. + /// + string? ApplicationTheme { get; set; } + + /// + /// Gets or sets the last version number used before an update. + /// + string? LastVersion { get; set; } + + /// + /// Gets or sets the app language preference. + /// + string? AppLanguage { get; set; } + + /// + /// Gets or sets the location represented by ID of the last canvas navigated by the user. + /// + string? LastLocationId { get; set; } + } +} diff --git a/src/ClipboardCanvas.Sdk/Services/Settings/IUserSettings.cs b/src/ClipboardCanvas.Sdk/Services/Settings/IUserSettings.cs new file mode 100644 index 00000000..1c4078d5 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Services/Settings/IUserSettings.cs @@ -0,0 +1,16 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System.ComponentModel; + +namespace ClipboardCanvas.Sdk.Services.Settings +{ + /// + /// An interface to manage user preferences and settings. + /// + public interface IUserSettings : IPersistable, IAsyncInitialize, INotifyPropertyChanged + { + /// + /// Gets or sets the value whether to resume the previous session on last canvas. + /// + bool UninterruptedResume { get; set; } + } +} diff --git a/src/ClipboardCanvas.Sdk/Storage/IDirectCopy.cs b/src/ClipboardCanvas.Sdk/Storage/IDirectCopy.cs new file mode 100644 index 00000000..709364b8 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Storage/IDirectCopy.cs @@ -0,0 +1,17 @@ +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Storage +{ + /// + /// Provides direct copy operation of storage objects. + /// + public interface IDirectCopy : IModifiableFolder + { + /// + /// Creates a copy of the provided storable item in this folder. + /// + Task CreateCopyOfAsync(IStorableChild itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/Storage/IDirectMove.cs b/src/ClipboardCanvas.Sdk/Storage/IDirectMove.cs new file mode 100644 index 00000000..28cb7a63 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Storage/IDirectMove.cs @@ -0,0 +1,17 @@ +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Storage +{ + /// + /// Provides direct move operation of storage objects. + /// + public interface IDirectMove : IModifiableFolder + { + /// + /// Moves a storable item out of the provided folder, and into this folder. Returns the new item that resides in this folder. + /// + Task MoveFromAsync(IStorableChild itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/Storage/IFileExtended.cs b/src/ClipboardCanvas.Sdk/Storage/IFileExtended.cs new file mode 100644 index 00000000..5ca1afe4 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/Storage/IFileExtended.cs @@ -0,0 +1,17 @@ +using OwlCore.Storage; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.Storage +{ + /// + /// Extends existing interface with additional functionality. + /// + public interface IFileExtended : IFile + { + /// The file sharing flags that specify access other processes have to the file. + /// + Task OpenStreamAsync(FileAccess access, FileShare share, CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/BaseCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/BaseCanvasViewModel.cs new file mode 100644 index 00000000..c104bdae --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/BaseCanvasViewModel.cs @@ -0,0 +1,122 @@ +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using ClipboardCanvas.Sdk.ViewModels.Views.Overlays; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using OwlCore.Storage; +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public abstract partial class BaseCanvasViewModel : ObservableObject, IAsyncInitialize, IViewable, IDisposable + { + [ObservableProperty] private string? _Title; + [ObservableProperty] private bool _IsEditing; + [ObservableProperty] private bool _IsImmersed; + [ObservableProperty] private bool _WasAltered; + [ObservableProperty] private ObservableCollection? _PrimaryActions; + [ObservableProperty] private ObservableCollection? _SecondaryActions; + + public IDataSourceModel SourceModel { get; } + + public virtual IStorable? Storable { get; } + + protected IFileExplorerService FileExplorerService { get; } = Ioc.Default.GetRequiredService(); + + protected IApplicationService ApplicationService { get; } = Ioc.Default.GetRequiredService(); + + protected IClipboardService ClipboardService { get; } = Ioc.Default.GetRequiredService(); + + protected IOverlayService OverlayService { get; } = Ioc.Default.GetRequiredService(); + + protected BaseCanvasViewModel(IStorable storable, IDataSourceModel sourceModel) + : this(sourceModel) + { + Storable = storable; + Title = Path.GetFileName(storable.Id); + } + + protected BaseCanvasViewModel(IDataSourceModel sourceModel) + { + SourceModel = sourceModel; + } + + /// + public abstract Task InitAsync(CancellationToken cancellationToken = default); + + [RelayCommand] + protected virtual async Task OpenAsync(CancellationToken cancellationToken) + { + if (Storable is not IFile file) + return; + + await ApplicationService.LaunchHandlerAsync(file, cancellationToken); + } + + [RelayCommand] + protected virtual async Task ShowInExplorerAsync(CancellationToken cancellationToken) + { + await FileExplorerService.OpenInFileExplorerAsync(SourceModel.Source, Storable as IStorableChild, cancellationToken); + } + + [RelayCommand] + protected virtual async Task CopyPathAsync(CancellationToken cancellationToken) + { + if (Storable is not null) + await ClipboardService.SetTextAsync(Storable.Id, cancellationToken); + } + + [RelayCommand] + protected virtual async Task EditAsync(MenuItemViewModel itemViewModel, CancellationToken cancellationToken) + { + if (IsEditing && WasAltered && this is IPersistable persistable) + { + if (Storable is not null) + { + var viewModel = new SaveConfirmationOverlayViewModel(Storable.Name); + var result = await OverlayService.ShowAsync(viewModel); + if (result.Positive()) + { + await persistable.SaveAsync(cancellationToken); + IsEditing = false; + } + else if (result.InBetween()) + { + IsEditing = false; + } + else + { + // Aborted, do nothing + } + } + else + { + // TODO: Display a dialog asking the user if where they want to save the file + //var result = await OverlayService.ShowAsync(...); + } + } + else + IsEditing = !IsEditing; + + // Reset WasAltered when the item is no longer being edited + if (WasAltered && !IsEditing) + WasAltered = false; + + if (itemViewModel is MenuToggleViewModel toggleViewModel) + toggleViewModel.IsToggled = IsEditing; + } + + /// + public virtual void Dispose() + { + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/CodeCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/CodeCanvasViewModel.cs new file mode 100644 index 00000000..bd72cdb6 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/CodeCanvasViewModel.cs @@ -0,0 +1,82 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using OwlCore.Storage; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public partial class CodeCanvasViewModel : BaseCanvasViewModel, IPersistable + { + [ObservableProperty] private string? _Text; + [ObservableProperty] private string? _Language; + + private IMediaService MediaService { get; } = Ioc.Default.GetRequiredService(); + + public CodeCanvasViewModel(IFile codeFile, IDataSourceModel sourceModel) + : base(codeFile, sourceModel) + { + Language = Path.GetExtension(codeFile.Id); + } + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + PrimaryActions = new() + { + new MenuActionViewModel() + { + Name = "Share", + Icon = MediaService.GetIcon(IconType.Share), + Command = new AsyncRelayCommand(async () => + { + // TODO + await Console.Out.WriteLineAsync(); + }) + }, + new MenuActionViewModel() + { + Name = "Open", + Icon = MediaService.GetIcon(IconType.Open), + Command = OpenCommand + }, + new MenuToggleViewModel() + { + Name = "Edit", + Icon = MediaService.GetIcon(IconType.Edit), + Command = EditCommand + } + }; + + if (Storable is not IFile file || Text is not null) + return; + + Text = await file.ReadAllTextAsync(null, cancellationToken); + } + + /// + [RelayCommand] + public async Task SaveAsync(CancellationToken cancellationToken = default) + { + if (Storable is not IFile file) + return; + + // Set WasAltered beforehand to account for any updates + WasAltered = false; + + if (Text is null) + return; + + await file.WriteAllTextAsync(Text, null, cancellationToken); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/FolderCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/FolderCanvasViewModel.cs new file mode 100644 index 00000000..15f0de77 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/FolderCanvasViewModel.cs @@ -0,0 +1,30 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.ViewModels.Views.Browser; +using OwlCore.Storage; +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public sealed partial class FolderCanvasViewModel : BaseCanvasViewModel + { + public ObservableCollection Items { get; } + + public FolderCanvasViewModel(IFolder folder, IDataSourceModel sourceModel) + : base(folder, sourceModel) + { + Items = new(); + } + + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + if (Storable is not IFolder folder) + return; + + var folderViewModel = new FolderViewModel(folder); + _ = folderViewModel.InitAsync(cancellationToken); + Items.Add(folderViewModel); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/ImageCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/ImageCanvasViewModel.cs new file mode 100644 index 00000000..8e8c3ef6 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/ImageCanvasViewModel.cs @@ -0,0 +1,94 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Helpers; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using MimeTypes; +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public partial class ImageCanvasViewModel : BaseCanvasViewModel + { + [ObservableProperty] private IImage? _Image; + + private IMediaService MediaService { get; } = Ioc.Default.GetRequiredService(); + + public ImageCanvasViewModel(IImage image, IDataSourceModel sourceModel) + : base(sourceModel) + { + Image = image; + } + + public ImageCanvasViewModel(IFile imageFile, IDataSourceModel sourceModel) + : base(imageFile, sourceModel) + { + } + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + // TODO: Move to UI + PrimaryActions = new() + { + new MenuActionViewModel() + { + Name = "Share", + Icon = MediaService.GetIcon(IconType.Share), + Command = new AsyncRelayCommand(async () => + { + // TODO + await Console.Out.WriteLineAsync(); + }) + }, + new MenuActionViewModel() + { + Name = "Open", + Icon = MediaService.GetIcon(IconType.Open), + Command = OpenCommand + }, + new MenuToggleViewModel() + { + Name = "Edit", + Icon = MediaService.GetIcon(IconType.Edit), + Command = EditCommand + } + }; + + if (Storable is not IFile file || Image is not null) + return; + + Image = await MediaService.ReadImageAsync(file, cancellationToken); + } + + public static async Task ParseAsync(IClipboardData data, IDataSourceModel sourceModel, CancellationToken cancellationToken) + { + var mediaService = Ioc.Default.GetRequiredService(); + var image = await data.GetImageAsync(cancellationToken); + if (sourceModel.Source is not IModifiableFolder modifiableFolder) + return new(image, sourceModel); + + var extension = MimeTypeMap.GetExtension(data.Classification.MimeType, false); + var file = await modifiableFolder.CreateFileAsync(FormattingHelpers.GetDateFileName(extension), false, cancellationToken); + + await mediaService.SaveImageAsync(image, file, cancellationToken); + return new(file, sourceModel) + { + Image = image + }; + } + + /// + public override void Dispose() + { + Image?.Dispose(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/PdfCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/PdfCanvasViewModel.cs new file mode 100644 index 00000000..84927a44 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/PdfCanvasViewModel.cs @@ -0,0 +1,62 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Documents; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.DependencyInjection; +using OwlCore.Storage; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public class PdfCanvasViewModel : BaseCanvasViewModel + { + /// + /// Gets the collection of displayable pages. + /// + public ObservableCollection Pages { get; } + + private IDocumentService DocumentService { get; } = Ioc.Default.GetRequiredService(); + + public PdfCanvasViewModel(IFile pdfFile, IDataSourceModel sourceModel) + : base(pdfFile, sourceModel) + { + Pages = new(); + } + + public PdfCanvasViewModel(IEnumerable pages, IDataSourceModel sourceModel) + : base(sourceModel) + { + Pages = new(pages); + } + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + if (Storable is not IFile pdfFile || !Pages.IsEmpty()) + return; + + await using var pdfStream = await pdfFile.OpenStreamAsync(FileAccess.Read, cancellationToken); + using var pdfDocument = await DocumentService.ReadPdfAsync(pdfStream, cancellationToken); + + // TODO: Load pages dynamically + await foreach (var item in pdfDocument.GetPagesAsync(cancellationToken)) + { + var pageViewModel = new PdfPageViewModel(item); + await pageViewModel.InitAsync(cancellationToken); + + Pages.Add(pageViewModel); + } + } + + /// + public override void Dispose() + { + lock (Pages) + Pages.DisposeElements(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/TextCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/TextCanvasViewModel.cs new file mode 100644 index 00000000..8525cac9 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/TextCanvasViewModel.cs @@ -0,0 +1,104 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Helpers; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using MimeTypes; +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public sealed partial class TextCanvasViewModel : BaseCanvasViewModel, IPersistable + { + [ObservableProperty] private string? _Text; + + private IMediaService MediaService { get; } = Ioc.Default.GetRequiredService(); + + public TextCanvasViewModel(string text, IDataSourceModel sourceModel) + : base(sourceModel) + { + Text = text; + } + + public TextCanvasViewModel(IFile textFile, IDataSourceModel sourceModel) + : base(textFile, sourceModel) + { + } + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + // TODO: Move to UI + PrimaryActions = new() + { + new MenuActionViewModel() + { + Name = "Share", + Icon = MediaService.GetIcon(IconType.Share), + Command = new AsyncRelayCommand(async () => + { + // TODO + await Console.Out.WriteLineAsync(); + }) + }, + new MenuActionViewModel() + { + Name = "Open", + Icon = MediaService.GetIcon(IconType.Open), + Command = OpenCommand + }, + new MenuToggleViewModel() + { + Name = "Edit", + Icon = MediaService.GetIcon(IconType.Edit), + Command = EditCommand + } + }; + + if (Storable is not IFile file || Text is not null) + return; + + Text = await file.ReadAllTextAsync(null, cancellationToken); + } + + /// + [RelayCommand] + public async Task SaveAsync(CancellationToken cancellationToken = default) + { + if (Storable is not IFile file) + return; + + // Set WasAltered beforehand to account for any updates + WasAltered = false; + + if (Text is null) + return; + + await file.WriteAllTextAsync(Text, null, cancellationToken); + } + + public static async Task ParseAsync(IClipboardData data, IDataSourceModel sourceModel, CancellationToken cancellationToken) + { + var text = await data.GetTextAsync(cancellationToken); + if (sourceModel.Source is not IModifiableFolder modifiableFolder) + return new(text, sourceModel); + + var extension = MimeTypeMap.GetExtension(data.Classification.MimeType, false); + var file = await modifiableFolder.CreateFileAsync(FormattingHelpers.GetDateFileName(extension), false, cancellationToken); + await file.WriteAllTextAsync(text, null, cancellationToken); + + return new(file, sourceModel) + { + Text = text, + }; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/VideoCanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/VideoCanvasViewModel.cs new file mode 100644 index 00000000..64f16d22 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Canvases/VideoCanvasViewModel.cs @@ -0,0 +1,44 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Canvases +{ + public partial class VideoCanvasViewModel : BaseCanvasViewModel + { + [ObservableProperty] private IMediaSource? _MediaSource; + + private IMediaService MediaService { get; } = Ioc.Default.GetRequiredService(); + + public VideoCanvasViewModel(IMediaSource mediaSource, IDataSourceModel sourceModel) + : base(sourceModel) + { + _MediaSource = mediaSource; + } + + public VideoCanvasViewModel(IFile videoFile, IDataSourceModel sourceModel) + : base(videoFile, sourceModel) + { + } + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + if (Storable is not IFile file) + return; + + MediaSource?.Dispose(); + MediaSource = await MediaService.GetVideoPlaybackAsync(file, cancellationToken); + } + + /// + public override void Dispose() + { + MediaSource?.Dispose(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Documents/OcrStringViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Documents/OcrStringViewModel.cs new file mode 100644 index 00000000..c6719bf9 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Documents/OcrStringViewModel.cs @@ -0,0 +1,11 @@ +using System.Drawing; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Documents +{ + public sealed class OcrStringViewModel(string text, Rectangle rectangle) + { + public string Text { get; } = text; + + public Rectangle Rectangle { get; } = rectangle; + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Documents/PdfPageViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Documents/PdfPageViewModel.cs new file mode 100644 index 00000000..b3ef00f1 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Documents/PdfPageViewModel.cs @@ -0,0 +1,43 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using System; +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Documents +{ + public sealed partial class PdfPageViewModel : ObservableObject, IAsyncInitialize, IDisposable + { + private readonly IDocumentPage _documentPage; + [ObservableProperty] private IImage? _PageImage; + [ObservableProperty] private ObservableCollection _OcrText; + + private ITextRecognitionService TextRecognitionService { get; } = Ioc.Default.GetRequiredService(); + + public PdfPageViewModel(IDocumentPage documentPage) + { + _documentPage = documentPage; + OcrText = new(); + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + PageImage = await _documentPage.AsImageAsync(cancellationToken); + if (PageImage is null) + return; + + await foreach (var item in TextRecognitionService.RecognizeAsync(PageImage, cancellationToken)) + OcrText.Add(item); + } + + /// + public void Dispose() + { + _documentPage.Dispose(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/LanguageViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/LanguageViewModel.cs new file mode 100644 index 00000000..95f391cb --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/LanguageViewModel.cs @@ -0,0 +1,66 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Diagnostics; +using System.Globalization; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls +{ + /// + /// Represents a language view model. + /// + public sealed class LanguageViewModel : ObservableObject + { + /// + /// Gets the of the language. + /// + public CultureInfo CultureInfo { get; } + + /// + /// Gets the user-friendly name representation of the language. + /// + public string DisplayName { get; } + + public LanguageViewModel(CultureInfo cultureInfo) + : this(cultureInfo, FormatName(cultureInfo)) + { + } + + public LanguageViewModel(CultureInfo cultureInfo, string displayName) + { + CultureInfo = cultureInfo; + DisplayName = displayName; + } + + /// + public override string ToString() + { + return DisplayName; + } + + private static string FormatName(CultureInfo cultureInfo) + { + var name = cultureInfo.NativeName; + + // Convert the first letter to uppercase + name = char.ToUpperInvariant(name[0]) + name.Substring(1); + + // Sometimes the name may not have the country + if (name.Contains('(')) + return name; + + // Get the region to use for the country name + try + { + var regionInfo = new RegionInfo(cultureInfo.LCID); + return $"{name} ({regionInfo.DisplayName})"; + } + catch (Exception ex) + { + _ = ex; + Debugger.Break(); + + return name; + } + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuActionViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuActionViewModel.cs new file mode 100644 index 00000000..8c1fc746 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuActionViewModel.cs @@ -0,0 +1,10 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System.Windows.Input; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Menu +{ + public partial class MenuActionViewModel : MenuItemViewModel + { + [ObservableProperty] private ICommand? _Command; + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuItemViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuItemViewModel.cs new file mode 100644 index 00000000..cd793a4d --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuItemViewModel.cs @@ -0,0 +1,14 @@ +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using System; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Menu +{ + public abstract partial class MenuItemViewModel : ObservableObject + { + [ObservableProperty] private IImage? _Icon; + [ObservableProperty] private string? _Name; + [ObservableProperty] private string? _Description; + [ObservableProperty] private ConsoleKeyInfo? _KeyCombination; + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuToggleViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuToggleViewModel.cs new file mode 100644 index 00000000..d9e21966 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/Menu/MenuToggleViewModel.cs @@ -0,0 +1,11 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System.Windows.Input; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls.Menu +{ + public partial class MenuToggleViewModel : MenuItemViewModel + { + [ObservableProperty] private bool _IsToggled; + [ObservableProperty] private ICommand? _Command; + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/NavigationViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/NavigationViewModel.cs new file mode 100644 index 00000000..33b126c5 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/NavigationViewModel.cs @@ -0,0 +1,40 @@ +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Views; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls +{ + public sealed partial class NavigationViewModel : ObservableObject + { + private readonly ICollectionSourceModel _collectionSourceModel; + + [ObservableProperty] private ICommand? _NavigateBackCommand; + [ObservableProperty] private ICommand? _NavigateForwardCommand; + [ObservableProperty] private bool _IsNavigationVisible; + [ObservableProperty] private bool _IsForwardEnabled; + [ObservableProperty] private bool _IsBackEnabled; + + public INavigationService NavigationService { get; } + + public NavigationViewModel(ICollectionSourceModel collectionSourceModel, INavigationService navigationService) + { + _collectionSourceModel = collectionSourceModel; + NavigationService = navigationService; + IsNavigationVisible = false; + IsForwardEnabled = true; + IsBackEnabled = true; + } + + [RelayCommand] + private async Task NavigateHomeAsync(CancellationToken cancellationToken) + { + await NavigationService.TryNavigateAsync(() => new HomeViewModel(_collectionSourceModel, this)); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Controls/RibbonViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Controls/RibbonViewModel.cs new file mode 100644 index 00000000..7b175cca --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Controls/RibbonViewModel.cs @@ -0,0 +1,26 @@ +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace ClipboardCanvas.Sdk.ViewModels.Controls +{ + public sealed partial class RibbonViewModel : ObservableObject + { + [ObservableProperty] private string? _RibbonTitle; + [ObservableProperty] private bool _IsRibbonVisible; + [ObservableProperty] private ObservableCollection? _PrimaryActions; + [ObservableProperty] private ObservableCollection? _SecondaryActions; + [ObservableProperty] private ICommand? _RenameCommand; + [ObservableProperty] private ICommand? _ShowInExplorerCommand; + [ObservableProperty] private ICommand? _CopyPathCommand; + + /// + public Task InitAsync(CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/MainViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/MainViewModel.cs new file mode 100644 index 00000000..981b4e6e --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/MainViewModel.cs @@ -0,0 +1,36 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Views; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels +{ + public sealed partial class MainViewModel : ObservableObject, IAsyncInitialize + { + [ObservableProperty] private MainAppViewModel _AppViewModel; // TODO: Limitation since the UI requires specific type for x:Bind on DependencyProperty + + public ICollectionSourceModel CollectionStoreModel { get; } + + private ISettingsService SettingsService { get; } = Ioc.Default.GetRequiredService(); + + public MainViewModel() + { + CollectionStoreModel = new CollectionSourceModel(); + _AppViewModel = new MainAppViewModel(CollectionStoreModel); + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + await Task.WhenAll(SettingsService.TryInitAsync(cancellationToken), CollectionStoreModel.TryInitAsync(cancellationToken)); + if (AppViewModel is not null) + await AppViewModel.InitAsync(cancellationToken); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/QuickOptionsViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/QuickOptionsViewModel.cs new file mode 100644 index 00000000..79c8658a --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/QuickOptionsViewModel.cs @@ -0,0 +1,27 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Views.Overlays; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace ClipboardCanvas.Sdk.ViewModels +{ + public sealed partial class QuickOptionsViewModel : ObservableObject + { + [ObservableProperty] private ICommand? _CreateNewDocumentCommand; + + private IOverlayService OverlayService { get; } = Ioc.Default.GetRequiredService(); + + private ISettingsService SettingsService { get; } = Ioc.Default.GetRequiredService(); + + [RelayCommand] + private async Task OpenSettingsAsync() + { + await OverlayService.ShowAsync(SettingsOverlayViewModel.Instance); + await SettingsService.TrySaveAsync(); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/BrowserItemViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/BrowserItemViewModel.cs new file mode 100644 index 00000000..afbf1e98 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/BrowserItemViewModel.cs @@ -0,0 +1,28 @@ +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Browser +{ + public abstract partial class BrowserItemViewModel : ObservableObject, IWrapper, IViewable, IAsyncInitialize + { + [ObservableProperty] private string? _Title; + [ObservableProperty] private IImage? _Thumbnail; + + /// + /// Gets the item associated with this view model. + /// + public virtual IStorable Inner { get; } + + protected BrowserItemViewModel(IStorable storable) + { + Inner = storable; + Title = storable.Name; + } + + /// + public abstract Task InitAsync(CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/FileViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/FileViewModel.cs new file mode 100644 index 00000000..81a3def3 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/FileViewModel.cs @@ -0,0 +1,17 @@ +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Browser +{ + public class FileViewModel(IFile file) : BrowserItemViewModel(file) + { + /// + public override Task InitAsync(CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + // TODO: Load thumbnail + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/FolderViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/FolderViewModel.cs new file mode 100644 index 00000000..2db1ad93 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Browser/FolderViewModel.cs @@ -0,0 +1,36 @@ +using OwlCore.Storage; +using System; +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Browser +{ + public partial class FolderViewModel(IFolder folder) : BrowserItemViewModel(folder) + { + /// + /// Gets the items in this folder. + /// + public ObservableCollection Items { get; } = new(); + + /// + public override async Task InitAsync(CancellationToken cancellationToken = default) + { + if (Inner is not IFolder folder) + return; + + Items.Clear(); + await foreach (var item in folder.GetItemsAsync(StorableType.All, cancellationToken)) + { + Items.Add(item switch + { + IFile file => new FileViewModel(file), + IFolder folder2 => new FolderViewModel(folder2), + _ => throw new ArgumentOutOfRangeException(nameof(item)) + }); + } + + // TODO: Load thumbnail + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/CanvasViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/CanvasViewModel.cs new file mode 100644 index 00000000..999040bd --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/CanvasViewModel.cs @@ -0,0 +1,200 @@ +using ClipboardCanvas.Sdk.Helpers; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.Sdk.ViewModels.Controls.Canvases; +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Enums; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using OwlCore.Storage; +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views +{ + public sealed partial class CanvasViewModel : ObservableObject, IViewDesignation, IAsyncInitialize + { + private readonly ISeekable? _seekable; + private readonly IDataSourceModel _canvasSourceModel; + + [ObservableProperty] private string? _Title; + [ObservableProperty] private NavigationViewModel _NavigationViewModel; + [ObservableProperty] private BaseCanvasViewModel? _CurrentCanvasViewModel; + + private ICanvasService CanvasService { get; } = Ioc.Default.GetRequiredService(); + + private IClipboardService ClipboardService { get; } = Ioc.Default.GetRequiredService(); + + private QuickOptionsViewModel QuickOptionsViewModel { get; } = Ioc.Default.GetRequiredService(); + + private RibbonViewModel RibbonViewModel { get; } = Ioc.Default.GetRequiredService(); + + public CanvasViewModel(IDataSourceModel canvasSourceModel, NavigationViewModel navigationViewModel, ISeekable? seekable) + { + _canvasSourceModel = canvasSourceModel; + _seekable = seekable; + NavigationViewModel = navigationViewModel; + Title = canvasSourceModel.Name; + } + + /// + public Task InitAsync(CancellationToken cancellationToken = default) + { + _ = _canvasSourceModel; + return Task.CompletedTask; + } + + /// + public void OnAppearing() + { + QuickOptionsViewModel.CreateNewDocumentCommand = CreateNewDocumentCommand; + RibbonViewModel.IsRibbonVisible = CurrentCanvasViewModel is not null; + NavigationViewModel.IsNavigationVisible = true; + } + + /// + public void OnDisappearing() + { + // The canvas is not disposed here since we want the state + // to be remembered when navigating back to the canvas + } + + public void ChangeImmersion(bool isImmersed) + { + RibbonViewModel.IsRibbonVisible = !isImmersed; + NavigationViewModel.IsNavigationVisible = !isImmersed; + + if (CurrentCanvasViewModel is not null) + CurrentCanvasViewModel.IsImmersed = isImmersed; + } + + public async Task DisplayAsync(IStorable source, CancellationToken cancellationToken) + { + // TODO: Infrastructure strategy: + // For pasting: listen for changes from clipboard (service) and retrieve data friendly format (object, or IData/IFormat) + // For saving: add a method or use an existing one inside _canvasSourceModel to save items there, however, first check + // if CurrentCanvasViewModel can be cast to ICanvasSourceModel/IWrapper/InfiniteCanvasViewModel + + if (source is not IStorableChild storable) + return; + + var canvasViewModel = await CanvasService.GetCanvasForStorableAsync(storable, _canvasSourceModel, cancellationToken); + CurrentCanvasViewModel?.Dispose(); + CurrentCanvasViewModel = null; + CurrentCanvasViewModel = canvasViewModel; + + BindRibbon(); + } + + [Obsolete("This method will be replaced in the future")] + private void BindRibbon() + { + if (CurrentCanvasViewModel is null) + return; + + // TODO: Find a better way to bind + RibbonViewModel.RibbonTitle = CurrentCanvasViewModel.Title; + RibbonViewModel.PrimaryActions = CurrentCanvasViewModel.PrimaryActions; + RibbonViewModel.SecondaryActions = CurrentCanvasViewModel.SecondaryActions; + RibbonViewModel.CopyPathCommand = CurrentCanvasViewModel.CopyPathCommand; + RibbonViewModel.ShowInExplorerCommand = CurrentCanvasViewModel.ShowInExplorerCommand; + } + + [RelayCommand] + private async Task PasteFromClipboardAsync(CancellationToken cancellationToken) + { + var data = await ClipboardService.GetContentAsync(cancellationToken); + if (data is null) + return; + + var sourceModel = CurrentCanvasViewModel as IDataSourceModel ?? _canvasSourceModel; + var canvasViewModel = data.Classification.TypeHint switch + { + TypeHint.Image => await ImageCanvasViewModel.ParseAsync(data, sourceModel, cancellationToken), + TypeHint.PlainText => await TextCanvasViewModel.ParseAsync(data, sourceModel, cancellationToken), + TypeHint.Storage => await StorageAsync(), + + _ or TypeHint.Unclassified => null + }; + + CurrentCanvasViewModel?.Dispose(); + CurrentCanvasViewModel = null; + CurrentCanvasViewModel = canvasViewModel; + + // The canvas was null so open on new canvas + if (canvasViewModel is null) + { + // TODO: Report a paste error + _seekable?.Seek(0, SeekOrigin.End); + return; + } + + // Initialize the canvas + await canvasViewModel.InitAsync(cancellationToken); + BindRibbon(); + RibbonViewModel.IsRibbonVisible = true; + + // Seek to the pasted item + _seekable?.Seek(-1, SeekOrigin.End); + + Task StorageAsync() + { + // TODO: Maybe use infinite canvas or only allow for one item to be pasted? + // Perhaps prompt the user to choose what to do? + + throw new NotImplementedException(); + } + } + + [RelayCommand] + private async Task CreateNewDocumentAsync(CancellationToken cancellationToken) + { + if (_canvasSourceModel.Source is not IModifiableFolder modifiableFolder) + return; + + // Seek to new canvas + var position = _seekable?.Seek(0, SeekOrigin.End) ?? 0; + + // Create new file + var fileName = FormattingHelpers.GetDateFileName(".txt"); + var file = await modifiableFolder.CreateFileAsync(fileName, false, cancellationToken); + + // Display the text canvas + await DisplayAsync(file, cancellationToken); + RibbonViewModel.IsRibbonVisible = true; + + // Immediately seek back to synchronize the position after the item as successfully added to the collection. + // This is done because when a new item is added and the index is on new canvas, the position will update + // to stay on the new canvas. + _seekable?.Seek(position, SeekOrigin.Begin); + + // TODO: This is a workaround since we know that the only toggle is the Edit one + // A better approach would be to change the property directly in the command itself + + // Start editing + var item = CurrentCanvasViewModel?.PrimaryActions?.FirstOrDefault(static x => x is MenuToggleViewModel); + if (CurrentCanvasViewModel is not null) + await CurrentCanvasViewModel.EditCommand.ExecuteAsync(item); + } + + [RelayCommand] + private async Task DeleteAsync(BaseCanvasViewModel? canvasViewModel, CancellationToken cancellationToken) + { + canvasViewModel ??= CurrentCanvasViewModel; + if (canvasViewModel?.Storable is not IStorableChild storableChild) + return; + + var sourceModel = (canvasViewModel as IDataSourceModel) ?? _canvasSourceModel; + if (sourceModel.Source is not IModifiableFolder modifiableFolder) + return; + + await modifiableFolder.DeleteAsync(storableChild, cancellationToken); + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/HomeViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/HomeViewModel.cs new file mode 100644 index 00000000..69d95474 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/HomeViewModel.cs @@ -0,0 +1,51 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.Sdk.ViewModels.Widgets; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views +{ + public sealed partial class HomeViewModel : ObservableObject, IViewDesignation, IAsyncInitialize + { + private readonly ICollectionSourceModel _collectionStoreModel; + private readonly NavigationViewModel _navigationViewModel; + + [ObservableProperty] private string? _Title; + [ObservableProperty] private ObservableCollection _Widgets; + + private RibbonViewModel RibbonViewModel { get; } = Ioc.Default.GetRequiredService(); + + public HomeViewModel(ICollectionSourceModel collectionStoreModel, NavigationViewModel navigationViewModel) + { + _collectionStoreModel = collectionStoreModel; + _navigationViewModel = navigationViewModel; + Widgets = new(); + Title = "Clipboard Canvas"; + } + + /// + public Task InitAsync(CancellationToken cancellationToken = default) + { + Widgets.Add(new CollectionsWidgetViewModel(_collectionStoreModel, _navigationViewModel).WithInitAsync(cancellationToken)); + return Task.CompletedTask; + } + + /// + public void OnAppearing() + { + RibbonViewModel.IsRibbonVisible = false; + _navigationViewModel.IsNavigationVisible = false; + } + + /// + public void OnDisappearing() + { + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/MainAppViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/MainAppViewModel.cs new file mode 100644 index 00000000..6bace950 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/MainAppViewModel.cs @@ -0,0 +1,64 @@ +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views +{ + public sealed partial class MainAppViewModel : ObservableObject, IAsyncInitialize, IViewable + { + private readonly ICollectionSourceModel _collectionSourceModel; + + [ObservableProperty] private string _Title; + + public ISettingsService SettingsService { get; } = Ioc.Default.GetRequiredService(); + + public INavigationService NavigationService { get; } = Ioc.Default.GetRequiredService(); + + public QuickOptionsViewModel QuickOptionsViewModel { get; } = Ioc.Default.GetRequiredService(); + + public RibbonViewModel RibbonViewModel { get; } = Ioc.Default.GetRequiredService(); + + public NavigationViewModel NavigationViewModel { get; } + + public MainAppViewModel(ICollectionSourceModel collectionSourceModel) + { + _collectionSourceModel = collectionSourceModel; + NavigationViewModel = new(collectionSourceModel, NavigationService); + Title = "Clipboard Canvas"; + + NavigationService.NavigationChanged += NavigationService_NavigationChanged; + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + if (SettingsService.UserSettings.UninterruptedResume) + { + var parentId = Path.GetDirectoryName(SettingsService.AppSettings.LastLocationId); + foreach (var collection in _collectionSourceModel) + { + if (collection.Source.Id == parentId) + { + // TODO: Figure out a way to navigate to canvas without (or with?) collections initialized + await NavigationService.NavigateAsync((CanvasViewModel?)null!); + break; + } + } + } + else + await NavigationService.TryNavigateAsync(() => new HomeViewModel(_collectionSourceModel, NavigationViewModel)); + } + + private void NavigationService_NavigationChanged(object? sender, IViewDesignation? e) + { + Title = e?.Title ?? Title ?? "Clipboard Canvas"; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/OverlayViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/OverlayViewModel.cs new file mode 100644 index 00000000..e7d0c95c --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/OverlayViewModel.cs @@ -0,0 +1,51 @@ +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Overlays +{ + /// + /// Serves as the base dialog view model containing reusable code for every dialog. + /// + public partial class OverlayViewModel : ObservableObject, IViewDesignation + { + /// + /// Gets or sets the title of the dialog. + /// + [ObservableProperty] private string? _Title; + + /// + /// Gets or sets whether the primary button should be enabled or not. + /// + [ObservableProperty] private bool _PrimaryButtonEnabled; + + /// + /// Gets or sets whether the secondary button should be enabled or not. + /// + [ObservableProperty] private bool _SecondaryButtonEnabled; + + /// + /// Gets or sets the text of primary button. If value is null, the button is hidden. + /// + [ObservableProperty] private string? _PrimaryButtonText; + + /// + /// Gets or sets the text of secondary button. If value is null, the button is hidden. + /// + [ObservableProperty] private string? _SecondaryButtonText; + + /// + /// Gets or sets the text of close button. If value is null, the button is hidden. + /// + [ObservableProperty] private string? _CloseButtonText; + + /// + public virtual void OnAppearing() + { + } + + /// + public virtual void OnDisappearing() + { + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/SaveConfirmationOverlayViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/SaveConfirmationOverlayViewModel.cs new file mode 100644 index 00000000..252b50bd --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/SaveConfirmationOverlayViewModel.cs @@ -0,0 +1,14 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Overlays +{ + public sealed partial class SaveConfirmationOverlayViewModel : OverlayViewModel + { + [ObservableProperty] private string? _FileName; + + public SaveConfirmationOverlayViewModel(string fileName) + { + FileName = fileName; + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/SettingsOverlayViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/SettingsOverlayViewModel.cs new file mode 100644 index 00000000..3b85525e --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Overlays/SettingsOverlayViewModel.cs @@ -0,0 +1,12 @@ +using ClipboardCanvas.Sdk.Services; +using CommunityToolkit.Mvvm.DependencyInjection; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Overlays +{ + public sealed partial class SettingsOverlayViewModel : OverlayViewModel + { + public static SettingsOverlayViewModel Instance { get; } = new(); + + public INavigationService NavigationService { get; } = Ioc.Default.GetRequiredService(); + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Settings/AboutSettingsViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Settings/AboutSettingsViewModel.cs new file mode 100644 index 00000000..52d46d0a --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Settings/AboutSettingsViewModel.cs @@ -0,0 +1,71 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Settings +{ + public sealed partial class AboutSettingsViewModel : ObservableObject, IViewDesignation + { + [ObservableProperty] private string? _AppVersion; + [ObservableProperty] private string? _Title; + + private IApplicationService ApplicationService { get; } = Ioc.Default.GetRequiredService(); + + private IFileExplorerService FileExplorerService { get; } = Ioc.Default.GetRequiredService(); + + private IClipboardService ClipboardService { get; } = Ioc.Default.GetRequiredService(); + + private IStorageService StorageService { get; } = Ioc.Default.GetRequiredService(); + + public AboutSettingsViewModel() + { + AppVersion = $"{ApplicationService.AppVersion} ({ApplicationService.Platform})"; + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private async Task CopyAppVersionAsync(CancellationToken cancellationToken) + { + await ClipboardService.SetTextAsync(AppVersion ?? string.Empty, cancellationToken); + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private async Task CopySystemVersionAsync(CancellationToken cancellationToken) + { + await ClipboardService.SetTextAsync(ApplicationService.GetSystemVersion(), cancellationToken); + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private Task OpenGitHubRepositoryAsync() + { + return ApplicationService.OpenUriAsync(new Uri("https://github.com/securefolderfs-community/SecureFolderFS")); + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private Task OpenPrivacyPolicyAsync() + { + return ApplicationService.OpenUriAsync(new Uri("https://github.com/securefolderfs-community/SecureFolderFS/blob/master/PRIVACY.md")); + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private async Task OpenLogLocationAsync(CancellationToken cancellationToken) + { + var appFolder = await StorageService.GetAppFolderAsync(cancellationToken); + await FileExplorerService.OpenInFileExplorerAsync(appFolder); + } + + /// + public void OnAppearing() + { + } + + /// + public void OnDisappearing() + { + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Views/Settings/GeneralSettingsViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Views/Settings/GeneralSettingsViewModel.cs new file mode 100644 index 00000000..b9c08c44 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Views/Settings/GeneralSettingsViewModel.cs @@ -0,0 +1,80 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Views.Settings +{ + public sealed partial class GeneralSettingsViewModel : ObservableObject, IViewDesignation, IAsyncInitialize + { + private readonly CultureInfo _currentCulture; + private bool _noNotify; + + [ObservableProperty] private string? _Title; + [ObservableProperty] private ObservableCollection _Languages; + [ObservableProperty] private LanguageViewModel? _SelectedLanguage; + [ObservableProperty] private bool _IsRestartRequired; + + private ILocalizationService LocalizationService { get; } = Ioc.Default.GetRequiredService(); + + private IApplicationService ApplicationService { get; } = Ioc.Default.GetRequiredService(); + + public GeneralSettingsViewModel() + { + Languages = new(); + _currentCulture = LocalizationService.CurrentCulture; + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + foreach (var item in LocalizationService.AppLanguages) + Languages.Add(new(item)); + + // Add wildcard language + Languages.Add(new(CultureInfo.InvariantCulture, "Not seeing your language?")); + + // Set selected language + _noNotify = true; + SelectedLanguage = Languages.FirstOrDefault(x => x.CultureInfo.Equals(LocalizationService.CurrentCulture)); + _noNotify = false; + } + + /// + public void OnAppearing() + { + } + + /// + public void OnDisappearing() + { + } + + async partial void OnSelectedLanguageChanged(LanguageViewModel? value) + { + if (value is null || _noNotify) + return; + + if (value.CultureInfo.Equals(CultureInfo.InvariantCulture)) + { + // Wildcard + await ApplicationService.OpenUriAsync(new("https://github.com/d2dyno1/ClipboardCanvas")); + + SelectedLanguage = Languages.FirstOrDefault(x => x.CultureInfo.Equals(LocalizationService.CurrentCulture)); + if (SelectedLanguage is not null) + await LocalizationService.SetCultureAsync(SelectedLanguage.CultureInfo); + } + else + { + await LocalizationService.SetCultureAsync(value.CultureInfo); + IsRestartRequired = !_currentCulture.Equals(SelectedLanguage?.CultureInfo); + } + } + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Widgets/BaseWidgetViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Widgets/BaseWidgetViewModel.cs new file mode 100644 index 00000000..2a823f42 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Widgets/BaseWidgetViewModel.cs @@ -0,0 +1,15 @@ +using System.Threading; +using System.Threading.Tasks; +using ClipboardCanvas.Shared.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace ClipboardCanvas.Sdk.ViewModels.Widgets +{ + public abstract partial class BaseWidgetViewModel : ObservableObject, IAsyncInitialize, IViewable + { + [ObservableProperty] private string? _Title; + + /// + public abstract Task InitAsync(CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Widgets/CollectionViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Widgets/CollectionViewModel.cs new file mode 100644 index 00000000..14f6c13c --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Widgets/CollectionViewModel.cs @@ -0,0 +1,225 @@ +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.Sdk.ViewModels.Views; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using OwlCore.Storage; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Widgets +{ + public sealed partial class CollectionViewModel : ObservableObject, ISeekable, IAsyncInitialize, IDisposable + { + private readonly ICollectionSourceModel _collectionSourceModel; + private readonly NavigationViewModel _navigationViewModel; + private readonly CanvasViewModel _canvasViewModel; + private readonly List _items; + private int _position; + + [ObservableProperty] private string? _Name; + [ObservableProperty] private IImage? _Icon; + + private IFileExplorerService FileExplorerService { get; } = Ioc.Default.GetRequiredService(); + + private IMediaService MediaService { get; } = Ioc.Default.GetRequiredService(); + + private ISettingsService SettingsService { get; } = Ioc.Default.GetRequiredService(); + + private RibbonViewModel RibbonViewModel { get; } = Ioc.Default.GetRequiredService(); + + public IDataSourceModel SourceModel { get; } + + public CollectionViewModel(ICollectionSourceModel collectionSourceModel, IDataSourceModel sourceModel, NavigationViewModel navigationViewModel) + { + _items = new(); + _collectionSourceModel = collectionSourceModel; + _navigationViewModel = navigationViewModel; + _canvasViewModel = new(sourceModel, navigationViewModel, this); + SourceModel = sourceModel; + Name = sourceModel.Name; + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + await SourceModel.InitAsync(cancellationToken); + SourceModel.CollectionChanged += DataSourceModel_CollectionChanged; + Icon = await MediaService.GetCollectionIconAsync(SourceModel, cancellationToken); + _items.Clear(); + + // TODO: Order by creation date + var items = await SourceModel.Source.GetItemsAsync(StorableType.All, cancellationToken).ToArrayAsync(cancellationToken); + _items.AddRange(items); + + _position = _items.Count; // Count is out of bounds intentionally to put the index on new (empty) canvas + } + + /// + public int Seek(int offset, SeekOrigin origin) + { + // Return the current position only if not seeking + if (offset == 0 && origin == SeekOrigin.Current) + return _position; + + _position = Math.Max(Math.Min(origin switch + { + SeekOrigin.End => _items.Count + offset, + SeekOrigin.Current => _position + offset, + _ or SeekOrigin.Begin => offset, + }, _items.Count), 0); + + UpdateNavigationButtons(); + return _position; + } + + [RelayCommand] + private async Task OpenCollectionAsync(CancellationToken cancellationToken) + { + if (!_navigationViewModel.NavigationService.Views.Contains(_canvasViewModel)) + _ = _canvasViewModel.InitAsync(cancellationToken); + + await _navigationViewModel.NavigationService.NavigateAsync(_canvasViewModel); + _navigationViewModel.NavigateBackCommand = GoBackCommand; + _navigationViewModel.NavigateForwardCommand = GoForwardCommand; + UpdateNavigationButtons(); + } + + [RelayCommand] + private Task ShowInFileExplorerAsync(CancellationToken cancellationToken) + { + return FileExplorerService.OpenInFileExplorerAsync(SourceModel.Source, null, cancellationToken); + } + + [RelayCommand] + private Task RenameAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + [RelayCommand] + private async Task RemoveAsync(CancellationToken cancellationToken) + { + _collectionSourceModel.Remove(SourceModel); + await _collectionSourceModel.SaveAsync(cancellationToken); + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private async Task GoBackAsync(CancellationToken cancellationToken) + { + if (_items.IsEmpty()) + return; + + // Show ribbon if coming from new canvas + if (_position == _items.Count) + RibbonViewModel.IsRibbonVisible = true; + + Seek(-1, SeekOrigin.Current); + await NavigateToItemAsync(_items[_position], cancellationToken); + } + + [RelayCommand(AllowConcurrentExecutions = true)] + private async Task GoForwardAsync(CancellationToken cancellationToken) + { + Seek(1, SeekOrigin.Current); + + // If on new canvas... + if (_position >= _items.Count) + { + ClearCanvas(); + return; + } + + // Otherwise, display the next item + await NavigateToItemAsync(_items[_position], cancellationToken); + } + + private async Task NavigateToItemAsync(IStorable source, CancellationToken cancellationToken) + { + try + { + if (SettingsService.UserSettings.UninterruptedResume) + SettingsService.AppSettings.LastLocationId = source.Id; + + await _canvasViewModel.DisplayAsync(source, cancellationToken); + } + catch (TaskCanceledException) { } + catch (OperationCanceledException) { } + } + + private void UpdateNavigationButtons() + { + _navigationViewModel.IsForwardEnabled = _position < _items.Count; + _navigationViewModel.IsBackEnabled = _position > 0 && _items.Count > 0; + } + + private void ClearCanvas() + { + _canvasViewModel.CurrentCanvasViewModel?.Dispose(); + _canvasViewModel.CurrentCanvasViewModel = null; + RibbonViewModel.IsRibbonVisible = false; + } + + private async void DataSourceModel_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Add) + { + if (e.NewItems is null) + return; + + var isNewCanvas = _position == _items.Count; + foreach (IStorableChild item in e.NewItems) + _items.Add(item); + + // TODO: The CurrentCanvasViewModel check might result in race condition + if (isNewCanvas && _canvasViewModel.CurrentCanvasViewModel is null) + _position = _items.Count; + } + else if (e.Action == NotifyCollectionChangedAction.Remove) + { + if (e.OldItems is null) + return; + + var isCanvasInvalid = false; + var isNewCanvas = _position == _items.Count; + foreach (IStorable item in e.OldItems) + { + _items.RemoveMatch((x) => x.Id == item.Id); + if (!isNewCanvas && _canvasViewModel.CurrentCanvasViewModel?.Storable?.Id == item.Id) + { + isCanvasInvalid = true; + _position = Math.Max(_position - 1, 0); + } + } + + if (isNewCanvas) + _position = _items.Count; + + if (isCanvasInvalid) + { + var storable = _items.ElementAtOrDefault(_position); + if (storable is not null) + await _canvasViewModel.DisplayAsync(storable, default); + else + ClearCanvas(); + } + } + } + + /// + public void Dispose() + { + SourceModel.CollectionChanged -= DataSourceModel_CollectionChanged; + _canvasViewModel.CurrentCanvasViewModel?.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/ClipboardCanvas.Sdk/ViewModels/Widgets/CollectionsWidgetViewModel.cs b/src/ClipboardCanvas.Sdk/ViewModels/Widgets/CollectionsWidgetViewModel.cs new file mode 100644 index 00000000..8d9d5c95 --- /dev/null +++ b/src/ClipboardCanvas.Sdk/ViewModels/Widgets/CollectionsWidgetViewModel.cs @@ -0,0 +1,74 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using OwlCore.Storage; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Sdk.ViewModels.Widgets +{ + public sealed partial class CollectionsWidgetViewModel : BaseWidgetViewModel, IAsyncInitialize + { + private readonly ICollectionSourceModel _collectionStoreModel; + private readonly NavigationViewModel _navigationViewModel; + + private IFileExplorerService FileExplorerService { get; } = Ioc.Default.GetRequiredService(); + + public ObservableCollection Items { get; } = new(); + + public CollectionsWidgetViewModel(ICollectionSourceModel collectionStoreModel, NavigationViewModel navigationViewModel) + { + _collectionStoreModel = collectionStoreModel; + _navigationViewModel = navigationViewModel; + Title = "Collections"; + + _collectionStoreModel.CollectionChanged += CollectionStoreModel_CollectionChanged; + } + + /// + public override Task InitAsync(CancellationToken cancellationToken = default) + { + Items.Clear(); + foreach (var item in _collectionStoreModel) + Items.Add(new CollectionViewModel(_collectionStoreModel, item, _navigationViewModel).WithInitAsync(cancellationToken)); + + return Task.CompletedTask; + } + + [RelayCommand] + private async Task AddCollectionAsync(CancellationToken cancellationToken) + { + var folder = await FileExplorerService.PickFolderAsync(cancellationToken); + if (folder is not IModifiableFolder modifiableFolder) + return; + + _collectionStoreModel.Add(new CollectionModel(modifiableFolder)); + await _collectionStoreModel.SaveAsync(cancellationToken); + } + + private void CollectionStoreModel_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add when e.NewItems is not null && e.NewItems[0] is IDataSourceModel collectionModel: + Items.Add(new CollectionViewModel(_collectionStoreModel, collectionModel, _navigationViewModel).WithInitAsync()); + break; + + case NotifyCollectionChangedAction.Remove when e.OldItems is not null && e.OldItems[0] is IDataSourceModel collectionModel: + Items.RemoveMatch(x => x.SourceModel.Source.Id == collectionModel.Source.Id); + break; + + case NotifyCollectionChangedAction.Reset: + Items.Clear(); + break; + } + } + } +} diff --git a/src/ClipboardCanvas.Shared/ClipboardCanvas.Shared.csproj b/src/ClipboardCanvas.Shared/ClipboardCanvas.Shared.csproj new file mode 100644 index 00000000..d35d8ffc --- /dev/null +++ b/src/ClipboardCanvas.Shared/ClipboardCanvas.Shared.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + disable + enable + + + diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IAsyncInitialize.cs b/src/ClipboardCanvas.Shared/ComponentModel/IAsyncInitialize.cs new file mode 100644 index 00000000..b3e2685e --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IAsyncInitialize.cs @@ -0,0 +1,18 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Allows an object to be initialized asynchronously. + /// + public interface IAsyncInitialize + { + /// + /// Initializes resources and prepares them for use. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task InitAsync(CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IAsyncSerializer.cs b/src/ClipboardCanvas.Shared/ComponentModel/IAsyncSerializer.cs new file mode 100644 index 00000000..44497403 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IAsyncSerializer.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Provides data serialization abstractions for data. + /// + /// The type of data serialized to. + public interface IAsyncSerializer + { + /// + /// Serializes into . + /// + /// The data to serialize. + /// The type of data to serialize. + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is of transformed . + Task SerializeAsync(object? data, Type dataType, CancellationToken cancellationToken = default); + + /// + /// Deserializes into type. + /// + /// The data to deserialize. + /// The type to deserialize into. + /// A that cancels this action. + /// A that represents the asynchronous operation. Value is of type of transformed . + Task DeserializeAsync(TSerialized serialized, Type dataType, CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IAsyncValidator.cs b/src/ClipboardCanvas.Shared/ComponentModel/IAsyncValidator.cs new file mode 100644 index 00000000..eb69336a --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IAsyncValidator.cs @@ -0,0 +1,20 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Provides data validation abstractions for data. + /// + /// The type of data validated. + public interface IAsyncValidator + { + /// + /// Validates and returns of validation. + /// + /// The value to validate. + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task ValidateAsync(T value, CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IAwaitable.cs b/src/ClipboardCanvas.Shared/ComponentModel/IAwaitable.cs new file mode 100644 index 00000000..7ca7161a --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IAwaitable.cs @@ -0,0 +1,26 @@ +using System.Runtime.CompilerServices; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents an awaitable action. + /// + public interface IAwaitable : INotifyCompletion + { + /// + /// Gets whether this has completed. + /// + bool IsCompleted { get; } + + /// + /// Gets an awaiter used to await this . + /// + /// An awaiter instance. + IAwaitable GetAwaiter(); + + /// + /// Ends the await on the completed . + /// + void GetResult(); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IDocument.cs b/src/ClipboardCanvas.Shared/ComponentModel/IDocument.cs new file mode 100644 index 00000000..9dbebac3 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IDocument.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + public interface IDocument : IDisposable + { + int PageCount { get; } + + Task GetPageAsync(int index, CancellationToken cancellationToken); + + IAsyncEnumerable GetPagesAsync(CancellationToken cancellationToken); + } + + public interface IDocumentPage : IDisposable + { + Task AsImageAsync(CancellationToken cancellationToken); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IImage.cs b/src/ClipboardCanvas.Shared/ComponentModel/IImage.cs new file mode 100644 index 00000000..5d1b8884 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IImage.cs @@ -0,0 +1,11 @@ +using System; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents an image which can be displayed on the UI. + /// + public interface IImage : IDisposable + { + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IIterator.cs b/src/ClipboardCanvas.Shared/ComponentModel/IIterator.cs new file mode 100644 index 00000000..37b3af26 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IIterator.cs @@ -0,0 +1,24 @@ +using System.Collections; +using System.Collections.Generic; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents an iterator that can iterate through a collection. + /// + public interface IIterator : IEnumerator + { + /// + /// Gets a value indicating whether the iterator has a next element. + /// + bool HasNext { get; } + } + + /// + /// Represents a generic iterator that can iterate through a collection. + /// + /// The type of the element. + public interface IIterator : IEnumerator, IIterator + { + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/INotifyStateChanged.cs b/src/ClipboardCanvas.Shared/ComponentModel/INotifyStateChanged.cs new file mode 100644 index 00000000..331f9fa2 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/INotifyStateChanged.cs @@ -0,0 +1,19 @@ +using System; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Provides a contract for objects that need to notify subscribers when their state changes. + /// + public interface INotifyStateChanged + { + /// + /// Occurs when a state of an object changes. + /// + /// + /// Subscribers can register to this event in order to receive notifications when the state of the object changes. + /// The event may contain additional information about the new state in the event arguments. + /// + event EventHandler? StateChanged; + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IPersistable.cs b/src/ClipboardCanvas.Shared/ComponentModel/IPersistable.cs new file mode 100644 index 00000000..6ef06ae0 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IPersistable.cs @@ -0,0 +1,18 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Allows for data to be saved into a persistence store. + /// + public interface IPersistable + { + /// + /// Asynchronously saves data stored in memory. + /// + /// A that cancels this action. + /// A that represents the asynchronous operation. + Task SaveAsync(CancellationToken cancellationToken = default); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IResult.cs b/src/ClipboardCanvas.Shared/ComponentModel/IResult.cs new file mode 100644 index 00000000..73ed8b10 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IResult.cs @@ -0,0 +1,46 @@ +using System; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents a result of an action. + /// + public interface IResult + { + /// + /// Gets the value that determines whether the action completed successfully or not. + /// + bool Successful { get; } + + /// + /// Gets the exception associated with the action, if any. + /// + Exception? Exception { get; } + } + + /// + /// Represents a result of an action with a return value. + /// + /// The type of value associated with the result. + public interface IResult : IResult + { + /// + /// Gets the value of the result. + /// + T? Value { get; } + } + + /// + public interface IResultWithMessage : IResult + { + /// + /// Gets the message describing result of the action. + /// + string? Message { get; } + } + + /// + public interface IResultWithMessage : IResultWithMessage, IResult + { + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/ISeekable.cs b/src/ClipboardCanvas.Shared/ComponentModel/ISeekable.cs new file mode 100644 index 00000000..df810d40 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/ISeekable.cs @@ -0,0 +1,18 @@ +using System.IO; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents an object which uses a pointer to move within a collection. + /// + public interface ISeekable + { + /// + /// Sets the position of the pointer within the collection. + /// + /// The offset measured in the amount of items. + /// A value of type indicating the reference point used to obtain the new position. + /// The new position of the pointer. + int Seek(int offset, SeekOrigin origin); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IViewDesignation.cs b/src/ClipboardCanvas.Shared/ComponentModel/IViewDesignation.cs new file mode 100644 index 00000000..a4eba2b2 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IViewDesignation.cs @@ -0,0 +1,18 @@ +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents a view which can be notified when it is being navigated to or from. + /// + public interface IViewDesignation : IViewable + { + /// + /// Notifies the view that it is being navigated to. + /// + void OnAppearing(); + + /// + /// Notifies the view that it is being navigated from. + /// + void OnDisappearing(); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IViewable.cs b/src/ClipboardCanvas.Shared/ComponentModel/IViewable.cs new file mode 100644 index 00000000..3e3bf6ed --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IViewable.cs @@ -0,0 +1,15 @@ +using System.ComponentModel; + +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Represents a generic viewable display. + /// + public interface IViewable : INotifyPropertyChanged + { + /// + /// Gets the title of this view. + /// + string? Title { get; } + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IWrappable.cs b/src/ClipboardCanvas.Shared/ComponentModel/IWrappable.cs new file mode 100644 index 00000000..246ec4c8 --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IWrappable.cs @@ -0,0 +1,16 @@ +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Allows an object represented by to be wrapped into . + /// + /// The type to wrap. + public interface IWrappable + { + /// + /// Wraps an object into . + /// + /// The object to wrap. + /// A wrapped object by the implementation represented by . + IWrapper Wrap(T obj); + } +} diff --git a/src/ClipboardCanvas.Shared/ComponentModel/IWrapper.cs b/src/ClipboardCanvas.Shared/ComponentModel/IWrapper.cs new file mode 100644 index 00000000..2231486a --- /dev/null +++ b/src/ClipboardCanvas.Shared/ComponentModel/IWrapper.cs @@ -0,0 +1,14 @@ +namespace ClipboardCanvas.Shared.ComponentModel +{ + /// + /// Wraps and exposes implementation for access. + /// + /// The wrapped type. + public interface IWrapper + { + /// + /// Gets the inner member wrapped by the implementation. + /// + T Inner { get; } + } +} diff --git a/src/ClipboardCanvas.Shared/Enums/TypeHint.cs b/src/ClipboardCanvas.Shared/Enums/TypeHint.cs new file mode 100644 index 00000000..7f491838 --- /dev/null +++ b/src/ClipboardCanvas.Shared/Enums/TypeHint.cs @@ -0,0 +1,14 @@ +namespace ClipboardCanvas.Shared.Enums +{ + public enum TypeHint + { + Unclassified, + PlainText, + Document, + UriLink, + Storage, + Image, + Media, + Audio + } +} diff --git a/src/ClipboardCanvas.Shared/Extensions/CollectionExtensions.cs b/src/ClipboardCanvas.Shared/Extensions/CollectionExtensions.cs new file mode 100644 index 00000000..855994ac --- /dev/null +++ b/src/ClipboardCanvas.Shared/Extensions/CollectionExtensions.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace ClipboardCanvas.Shared.Extensions +{ + public static class CollectionExtensions + { + public static bool RemoveMatch(this IList list, Func predicate) + { + foreach (var item in list) + { + if (predicate(item)) + return list.Remove(item); + } + + return false; + } + + public static bool IsEmpty(this IEnumerable? enumerable) + { + if (enumerable is null) + return true; + + if (enumerable is IList { Count: 0 }) + return true; + + return !enumerable.Any(); + } + + public static void DisposeElements(this IEnumerable enumerable) + { + foreach (var item in enumerable) + { + if (item is IDisposable disposable) + disposable.Dispose(); + } + } + + public static void AddWithMaxCapacity(this IList list, T item, int maxCapacity) + { + if (list.Count >= maxCapacity) + list.RemoveAt(0); + + list.Add(item); + } + + public static void ForEach(this IEnumerable enumerable, Action action) + { + foreach (var item in enumerable) + { + action(item); + } + } + } +} diff --git a/src/ClipboardCanvas.Shared/Extensions/DictionaryExtensions.cs b/src/ClipboardCanvas.Shared/Extensions/DictionaryExtensions.cs new file mode 100644 index 00000000..680aa1a6 --- /dev/null +++ b/src/ClipboardCanvas.Shared/Extensions/DictionaryExtensions.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Linq; + +namespace ClipboardCanvas.Shared.Extensions +{ + public static class DictionaryExtensions + { + public static TValue? Get(this IDictionary dictionary, TKey key) + { + if (dictionary.TryGetValue(key, out var value)) + return value; + + return default; + } + + public static TKV? GetByKeyOrValue(this IDictionary dictionary, TKV tkv) + where TKV : class + { + if (dictionary.TryGetValue(tkv, out var value)) + return value; + + return dictionary.FirstOrDefault(x => x.Value == tkv).Key; + } + } +} diff --git a/src/ClipboardCanvas.Shared/Extensions/GenericExtensions.cs b/src/ClipboardCanvas.Shared/Extensions/GenericExtensions.cs new file mode 100644 index 00000000..6e8cfe27 --- /dev/null +++ b/src/ClipboardCanvas.Shared/Extensions/GenericExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace ClipboardCanvas.Shared.Extensions +{ + public static class GenericExtensions + { + [return: NotNullIfNotNull(nameof(defaultValue))] + public static TOut? TryCast(this object? value, Func? defaultValue = null) + { + if (value is TOut outValue) + return outValue; + + return defaultValue is not null ? defaultValue() : default; + } + } +} diff --git a/src/ClipboardCanvas.Shared/Extensions/PersistableExtensions.cs b/src/ClipboardCanvas.Shared/Extensions/PersistableExtensions.cs new file mode 100644 index 00000000..067680f7 --- /dev/null +++ b/src/ClipboardCanvas.Shared/Extensions/PersistableExtensions.cs @@ -0,0 +1,58 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.Shared.Extensions +{ + /// + /// Contains common extensions for and . + /// + public static class PersistableExtensions + { + /// + /// Tries to asynchronously initialize + /// + /// The instance to use. + /// A that cancels this action. + /// A that represents the asynchronous operation. If successful, returns true; otherwise false. + public static async Task TryInitAsync(this IAsyncInitialize asyncInitialize, CancellationToken cancellationToken = default) + { + try + { + await asyncInitialize.InitAsync(cancellationToken); + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Tries to asynchronously save data stored in memory. + /// + /// The instance to use. + /// A that cancels this action. + /// A that represents the asynchronous operation. If successful, returns true; otherwise false. + public static async Task TrySaveAsync(this IPersistable persistable, CancellationToken cancellationToken = default) + { + try + { + await persistable.SaveAsync(cancellationToken); + return true; + } + catch (Exception) + { + return false; + } + } + + public static T WithInitAsync(this T asyncInitialize, CancellationToken cancellationToken = default) + where T : IAsyncInitialize + { + _ = asyncInitialize.InitAsync(cancellationToken); + return asyncInitialize; + } + } +} diff --git a/src/ClipboardCanvas.Shared/Extensions/SerializationExtensions.cs b/src/ClipboardCanvas.Shared/Extensions/SerializationExtensions.cs new file mode 100644 index 00000000..fffc12b1 --- /dev/null +++ b/src/ClipboardCanvas.Shared/Extensions/SerializationExtensions.cs @@ -0,0 +1,25 @@ +using System.Threading; +using System.Threading.Tasks; +using ClipboardCanvas.Shared.ComponentModel; + +namespace ClipboardCanvas.Shared.Extensions +{ + public static class SerializationExtensions + { + public static async Task SerializeAsync( + this IAsyncSerializer serializer, + TData? data, + CancellationToken cancellationToken = default) + { + return await serializer.SerializeAsync(data, typeof(TData), cancellationToken); + } + + public static async Task DeserializeAsync( + this IAsyncSerializer serializer, + TSerialized serialized, + CancellationToken cancellationToken = default) + { + return (TData?)await serializer.DeserializeAsync(serialized, typeof(TData), cancellationToken); + } + } +} diff --git a/src/ClipboardCanvas.Shared/Extensions/StreamExtensions.cs b/src/ClipboardCanvas.Shared/Extensions/StreamExtensions.cs new file mode 100644 index 00000000..126a82de --- /dev/null +++ b/src/ClipboardCanvas.Shared/Extensions/StreamExtensions.cs @@ -0,0 +1,50 @@ +using System; +using System.IO; + +namespace ClipboardCanvas.Shared.Extensions +{ + public static class StreamExtensions + { + /// + /// Tries to set the for the stream. + /// + /// The stream to update the length. + /// The desired length of the current stream in bytes. + /// If the length was successfully set, returns true; otherwise false. + public static bool TrySetLength(this Stream stream, long length) + { + try + { + stream.SetLength(length); + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Tries to set the position within the . + /// + /// The stream to seek. + /// A byte offset relative to the parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// If the position was successfully updated, returns true; otherwise false. + public static bool TrySeek(this Stream stream, long offset, SeekOrigin origin) + { + try + { + if (!stream.CanSeek) + return false; + + stream.Seek(offset, origin); + return true; + } + catch (Exception) + { + return false; + } + } + } +} diff --git a/src/ClipboardCanvas.Shared/Helpers/Result.cs b/src/ClipboardCanvas.Shared/Helpers/Result.cs new file mode 100644 index 00000000..4716940e --- /dev/null +++ b/src/ClipboardCanvas.Shared/Helpers/Result.cs @@ -0,0 +1,80 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System; + +namespace ClipboardCanvas.Shared.Helpers +{ + /// + public class Result : IResult + { + public static Result Success { get; } = new(true); + + /// + public bool Successful { get; } + + /// + public Exception? Exception { get; } + + protected Result(Exception? exception) + : this(false) + { + Exception = exception; + } + + protected Result(bool isSuccess) + { + Successful = isSuccess; + } + + /// + public override string ToString() + { + return Exception?.ToString() ?? (Successful ? "Success" : "Unsuccessful"); + } + + /// + /// Creates a new with an exception. + /// + /// The exception of the operation. + /// A new failed . + public static Result Failure(Exception? exception) => new(exception); + } + + /// + public class Result : Result, IResult + { + /// + public T? Value { get; } + + protected Result(T value, bool isSuccess = true) + : base(isSuccess) + { + Value = value; + } + + protected Result(Exception? exception) + : base(exception) + { + } + + /// + /// Creates a new with a value. + /// + /// The vault of the result. + /// A new successful . + public new static Result Success(T value) => new(value); + + /// + /// Creates a new with an exception. + /// + /// The exception of the operation. + /// A new failed . + public new static Result Failure(Exception? exception) => new(exception); + + /// + /// Creates a new without an exception.. + /// + /// The vault of the result. + /// A new failed . + public static Result Failure(T value) => new(value); + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ClipboardCanvas.UI.csproj b/src/Platforms/ClipboardCanvas.UI/ClipboardCanvas.UI.csproj new file mode 100644 index 00000000..24ae4c98 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ClipboardCanvas.UI.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + disable + enable + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/Platforms/ClipboardCanvas.UI/Constants.cs b/src/Platforms/ClipboardCanvas.UI/Constants.cs new file mode 100644 index 00000000..d0b6c112 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Constants.cs @@ -0,0 +1,29 @@ +namespace ClipboardCanvas.UI +{ + public static class Constants + { + public static class FileNames + { + public const string SETTINGS_FOLDER_NAME = "settings"; + public const string SAVED_COLLECTIONS_FILENAME = "saved_collections.json"; + public const string APPLICATION_SETTINGS_FILENAME = "application_settings.json"; + public const string USER_SETTINGS_FILENAME = "user_settings.json"; + public const string ICON_ASSET_PATH = "Assets/AppAssets/AppIcon.ico"; + public const string EXCEPTION_LOG_FILENAME = "clipboardcanvas_exceptionlog.log"; + } + + public static class Application + { + public const string MAIN_WINDOW_ID = "ClipboardCanvas_mainwindow"; + public const string EXCEPTION_BLOCK_DATE_FORMAT = "dd.MM.yyyy HH_mm_ss"; + public const string DEFAULT_CULTURE_STRING = "en-US"; + } + + public static class AppThemes + { + public const string LIGHT_THEME = "LIGHT"; + public const string DARK_THEME = "DARK"; + public const string THEME_PREFERENCE_SETTING = "ImmersiveTheme"; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Controls/INavigationControl.cs b/src/Platforms/ClipboardCanvas.UI/Controls/INavigationControl.cs new file mode 100644 index 00000000..a24b4c4d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Controls/INavigationControl.cs @@ -0,0 +1,10 @@ +using System; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.Utils +{ + public interface INavigationControl : IDisposable + { + Task NavigateAsync(TTarget? target, TTransition? transition = default) where TTransition : class; + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Controls/IOverlayControl.cs b/src/Platforms/ClipboardCanvas.UI/Controls/IOverlayControl.cs new file mode 100644 index 00000000..c9ec3fe7 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Controls/IOverlayControl.cs @@ -0,0 +1,32 @@ +using ClipboardCanvas.Shared.ComponentModel; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.Utils +{ + /// + /// Represents an overlay with an associated view model. + /// + public interface IOverlayControl + { + /// + /// Shows the overlay and awaits until an option is selected or the overlay is closed. + /// + /// A that represents the asynchronous operation. Value is of the operation. + /// + /// The return value may contain additional information about the chosen option. + /// + Task ShowAsync(); + + /// + /// Sets the view associated with the overlay. + /// + /// + void SetView(IViewable viewable); + + /// + /// Hides the overlay if possible. + /// + /// A that represents the asynchronous operation. + Task HideAsync(); + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Enums/ThemeType.cs b/src/Platforms/ClipboardCanvas.UI/Enums/ThemeType.cs new file mode 100644 index 00000000..00cce9c6 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Enums/ThemeType.cs @@ -0,0 +1,9 @@ +namespace ClipboardCanvas.UI.Enums +{ + public enum ThemeType : uint + { + Default = 0, + Light = 1, + Dark = 2 + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Helpers/BaseLifecycleHelper.cs b/src/Platforms/ClipboardCanvas.UI/Helpers/BaseLifecycleHelper.cs new file mode 100644 index 00000000..1191e139 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Helpers/BaseLifecycleHelper.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.DependencyInjection; +using OwlCore.Storage; +using OwlCore.Storage.System.IO; +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.Helpers +{ + public abstract class BaseLifecycleHelper + { + public virtual Task ConfigureAsync(CancellationToken cancellationToken = default) + { + var settingsFolderPath = Path.Combine(Directory.GetCurrentDirectory(), Constants.FileNames.SETTINGS_FOLDER_NAME); + var settingsFolder = new SystemFolder(Directory.CreateDirectory(settingsFolderPath)); + + return Task.FromResult(ConfigureServices(settingsFolder)); + } + + /// + /// Logs the exception to a common output. + /// + /// The exception to log. + public virtual void LogException(Exception? ex) // TODO: Maybe use ILogger + { + var formattedException = ExceptionHelpers.FormatException(ex); + Debug.WriteLine(formattedException); + + // Please check the "Output Window" for exception details (On Visual Studio, go to View -> Output Window or Ctr+Alt+O) + Debugger.Break(); + } + + /// + /// Configures services for the app. + /// + /// The folder where app settings reside. + /// A new instance of containing the services. + protected abstract IServiceCollection ConfigureServices(IModifiableFolder settingsFolder); + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Helpers/ExceptionHelpers.cs b/src/Platforms/ClipboardCanvas.UI/Helpers/ExceptionHelpers.cs new file mode 100644 index 00000000..21823ea8 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Helpers/ExceptionHelpers.cs @@ -0,0 +1,25 @@ +using System; + +namespace ClipboardCanvas.UI.Helpers +{ + public static class ExceptionHelpers + { + public static string? FormatException(Exception? ex) + { + if (ex is null) + return null; + + var exceptionString = string.Empty; + + exceptionString += DateTime.Now.ToString(Constants.Application.EXCEPTION_BLOCK_DATE_FORMAT); + exceptionString += "\n"; + exceptionString += $">>> HRESULT {ex.HResult}\n"; + exceptionString += $">>> MESSAGE {ex.Message}\n"; + exceptionString += $">>> STACKTRACE {ex.StackTrace}\n"; + exceptionString += $">>> INNER {ex.InnerException}\n"; + exceptionString += $">>> SOURCE {ex.Source}\n\n"; + + return exceptionString; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Helpers/NavigationHelpers.cs b/src/Platforms/ClipboardCanvas.UI/Helpers/NavigationHelpers.cs new file mode 100644 index 00000000..8ba28a2c --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Helpers/NavigationHelpers.cs @@ -0,0 +1,29 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.UI.ServiceImplementation; +using ClipboardCanvas.UI.Utils; + +namespace ClipboardCanvas.UI.Helpers +{ + public static class NavigationHelpers + { + public static void ResetNavigation(this INavigationService navigationService) + { + if (navigationService is INavigationControlContract navigationControlContract) + navigationControlContract.NavigationControl = null; + } + + public static bool SetupNavigation(this INavigationService navigationService, INavigationControl navigationControl, bool overrideNavigation = false) + { + if (!overrideNavigation && navigationService.IsInitialized) + return true; + + if (navigationService is INavigationControlContract navigationControlContract) + { + navigationControlContract.NavigationControl = navigationControl; + return navigationService.IsInitialized; + } + + return false; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Helpers/ThemeHelper.cs b/src/Platforms/ClipboardCanvas.UI/Helpers/ThemeHelper.cs new file mode 100644 index 00000000..6180b9fc --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Helpers/ThemeHelper.cs @@ -0,0 +1,79 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.Services.Settings; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using ClipboardCanvas.UI.Enums; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.Helpers +{ + /// + /// Represents a helper class used for manipulating application themes. + /// + public abstract class ThemeHelper : ObservableObject, IAsyncInitialize + { + protected IAppSettings AppSettings { get; } = Ioc.Default.GetRequiredService().AppSettings; + + private ThemeType _CurrentTheme; + /// + /// Gets the current theme used by the app. + /// + public virtual ThemeType CurrentTheme + { + get => _CurrentTheme; + protected set => SetProperty(ref _CurrentTheme, value); + } + + /// + /// Updates the UI to reflect the new changes, if necessary. + /// + public abstract void UpdateTheme(); + + /// + /// Updates the application's theme to specified . + /// + /// The theme to set for the app. + /// A that cancels this action. + /// A that represents the asynchronous operation. + public Task SetThemeAsync(ThemeType themeType, CancellationToken cancellationToken = default) + { + CurrentTheme = themeType; + AppSettings.ApplicationTheme = ConvertThemeType(themeType); + + UpdateTheme(); + return AppSettings.TrySaveAsync(cancellationToken); + } + + /// + public virtual Task InitAsync(CancellationToken cancellationToken = default) + { + CurrentTheme = ConvertThemeString(AppSettings.ApplicationTheme); + UpdateTheme(); + + return Task.CompletedTask; + } + + protected static string? ConvertThemeType(ThemeType themeType) + { + return themeType switch + { + ThemeType.Light => Constants.AppThemes.LIGHT_THEME, + ThemeType.Dark => Constants.AppThemes.DARK_THEME, + _ => null + }; + } + + protected static ThemeType ConvertThemeString(string? themeString) + { + return themeString switch + { + Constants.AppThemes.LIGHT_THEME => ThemeType.Light, + Constants.AppThemes.DARK_THEME => ThemeType.Dark, + _ => ThemeType.Default + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseApplicationService.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseApplicationService.cs new file mode 100644 index 00000000..e4dd1320 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseApplicationService.cs @@ -0,0 +1,39 @@ +using ClipboardCanvas.Sdk.Services; +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public abstract class BaseApplicationService : IApplicationService + { + /// + public abstract string Platform { get; } + + /// + public abstract Version AppVersion { get; } + + /// + public virtual string GetSystemVersion() + { + if (OperatingSystem.IsWindows()) + { + var windows = Environment.OSVersion; + return $"Windows {windows.Version}"; + } + + return string.Empty; + } + + /// + public abstract Task OpenUriAsync(Uri uri); + + /// + public abstract Task TryRestartAsync(); + + /// + public abstract Task LaunchHandlerAsync(IFile file, CancellationToken cancellationToken); + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseNavigationService.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseNavigationService.cs new file mode 100644 index 00000000..b0c48cba --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseNavigationService.cs @@ -0,0 +1,136 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using ClipboardCanvas.UI.Utils; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public interface INavigationControlContract + { + /// + /// Sets the control used for navigation. + /// + public INavigationControl? NavigationControl { set; } + } + + /// + public abstract class BaseNavigationService : INavigationControlContract, INavigationService + { + /// + public INavigationControl? NavigationControl { get; set; } + + /// + public IViewDesignation? CurrentView { get; protected set; } + + /// + public ICollection Views { get; protected set; } + + /// + public virtual bool IsInitialized => NavigationControl is not null; + + /// + public event EventHandler? NavigationChanged; + + protected BaseNavigationService() + { + Views = new List(); + } + + /// + public virtual async Task NavigateAsync(IViewDesignation view) + { + if (!IsInitialized) + return false; + + // Notify the current target that it's being navigated from + CurrentView?.OnDisappearing(); + + // Notify the new target that it's been navigated to + view.OnAppearing(); + + // Start actual navigation + var navigationResult = await BeginNavigationAsync(view, NavigationType.Chained); + if (!navigationResult) + return false; + + // Update current target + CurrentView = view; + + // Add new target + if (!Views.Contains(view)) + Views.Add(view); + + // Notify that navigation has occurred + NavigationChanged?.Invoke(this, view); + + return true; + } + + /// + public virtual async Task GoBackAsync() + { + if (!IsInitialized) + return false; + + // Notify the current target that it's being navigated from + CurrentView?.OnDisappearing(); + + var navigationResult = await BeginNavigationAsync(null, NavigationType.Backward); + if (navigationResult) + { + // Notify that navigation has occurred + NavigationChanged?.Invoke(this, CurrentView); + } + + return navigationResult; + } + + /// + public virtual async Task GoForwardAsync() + { + if (!IsInitialized) + return false; + + // Notify the current target that it's being navigated from + CurrentView?.OnDisappearing(); + + var navigationResult = await BeginNavigationAsync(null, NavigationType.Forward); + if (navigationResult) + { + // Notify that navigation has occurred + NavigationChanged?.Invoke(this, CurrentView); + } + + return navigationResult; + } + + /// + /// Starts the navigation routine. + /// + /// The target to navigate to. + /// The type of navigation to perform. + /// + /// Parameter may be null when the parameter + /// is set to or . + /// In such case, it is the implementor's responsibility to update the property + /// and notify the that it's being navigated to. + /// + /// A that represents the asynchronous operation. If successful, returns true; otherwise false. + protected abstract Task BeginNavigationAsync(IViewDesignation? target, NavigationType navigationType); + + /// + public virtual void Dispose() + { + CurrentView = null; + NavigationControl?.Dispose(); + + Views.DisposeElements(); + Views.Clear(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseOverlayService.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseOverlayService.cs new file mode 100644 index 00000000..65444341 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/BaseOverlayService.cs @@ -0,0 +1,23 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.UI.Utils; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public abstract class BaseOverlayService : IOverlayService + { + /// + public virtual async Task ShowAsync(IViewable viewable) + { + var overlay = GetOverlay(viewable); + overlay.SetView(viewable); + + // Show overlay + return await overlay.ShowAsync(); + } + + protected abstract IOverlayControl GetOverlay(IViewable viewable); + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/CollectionPersistenceService.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/CollectionPersistenceService.cs new file mode 100644 index 00000000..af70ebb9 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/CollectionPersistenceService.cs @@ -0,0 +1,29 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.AppModels.Database; +using ClipboardCanvas.Sdk.DataModels; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using OwlCore.Storage; +using System.Collections.Generic; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public sealed class CollectionPersistenceService : SettingsModel, ICollectionPersistenceService + { + /// + protected override IDatabaseModel SettingsDatabase { get; } + + public CollectionPersistenceService(IModifiableFolder settingsFolder) + { + SettingsDatabase = new SingleFileDatabaseModel(Constants.FileNames.SAVED_COLLECTIONS_FILENAME, settingsFolder, DoubleSerializedStreamSerializer.Instance); + } + + /// + public IList? SavedCollections + { + get => GetSetting?>(); + set => SetSetting(value); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/ResourceLocalizationService.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/ResourceLocalizationService.cs new file mode 100644 index 00000000..40424967 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/ResourceLocalizationService.cs @@ -0,0 +1,96 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.Services.Settings; +using CommunityToolkit.Mvvm.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Resources; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public class ResourceLocalizationService : ILocalizationService + { + protected static CultureInfo DefaultCulture { get; } = new(Constants.Application.DEFAULT_CULTURE_STRING); + + protected static IReadOnlyList SupportedLanguages { get; } = new List() + { + // Commented out languages exist in Resources but are not translated + + "en-US" + }; + + protected IAppSettings AppSettings { get; } = Ioc.Default.GetRequiredService().AppSettings; + + protected virtual ResourceManager ResourceManager { get; } + + /// + public CultureInfo CurrentCulture { get; protected set; } + + /// + public IReadOnlyList AppLanguages { get; } + + public ResourceLocalizationService() + { + AppLanguages = GetAppLanguages().ToImmutableList(); + CurrentCulture = GetCurrentCulture(); + ResourceManager = new($"ClipboardCanvas.UI.Strings.{GetLanguageString(CurrentCulture)}.Resources", typeof(UI.Constants).Assembly); + } + + /// + public virtual string? TryGetString(string resourceKey) + { + try + { + return ResourceManager.GetString(resourceKey); + } + catch (Exception ex) + { + _ = ex; + Debugger.Break(); + + return null; + } + } + + /// + public virtual Task SetCultureAsync(CultureInfo cultureInfo) + { + CurrentCulture = cultureInfo; + AppSettings.AppLanguage = cultureInfo.Name; + + return AppSettings.SaveAsync(); + } + + protected virtual IEnumerable GetAppLanguages() + { + foreach (var item in SupportedLanguages) + { + yield return new(item); + } + } + + protected virtual CultureInfo GetCurrentCulture() + { + if (string.IsNullOrEmpty(AppSettings.AppLanguage)) + return DefaultCulture; + + if (!SupportedLanguages.Contains(AppSettings.AppLanguage)) + return DefaultCulture; + + return new(AppSettings.AppLanguage); + } + + protected virtual string GetLanguageString(CultureInfo cultureInfo) + { + if (cultureInfo.Name.Contains('-', StringComparison.OrdinalIgnoreCase)) + return cultureInfo.Name.Replace('-', '_'); + + return SupportedLanguages.First(x => x.Contains(cultureInfo.Name)).Replace('-', '_'); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/Settings/AppSettings.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/Settings/AppSettings.cs new file mode 100644 index 00000000..b5bbed1a --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/Settings/AppSettings.cs @@ -0,0 +1,48 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.AppModels.Database; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services.Settings; +using OwlCore.Storage; + +namespace ClipboardCanvas.UI.ServiceImplementation.Settings +{ + /// + public sealed class AppSettings : SettingsModel, IAppSettings + { + /// + protected override IDatabaseModel SettingsDatabase { get; } + + public AppSettings(IModifiableFolder settingsFolder) + { + SettingsDatabase = new SingleFileDatabaseModel(Constants.FileNames.APPLICATION_SETTINGS_FILENAME, settingsFolder, DoubleSerializedStreamSerializer.Instance); + } + + /// + public string? ApplicationTheme + { + get => GetSetting(); + set => SetSetting(value); + } + + /// + public string? LastVersion + { + get => GetSetting(); + set => SetSetting(value); + } + + /// + public string? AppLanguage + { + get => GetSetting(); + set => SetSetting(value); + } + + /// + public string? LastLocationId + { + get => GetSetting(); + set => SetSetting(value); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/Settings/UserSettings.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/Settings/UserSettings.cs new file mode 100644 index 00000000..57f8db1f --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/Settings/UserSettings.cs @@ -0,0 +1,26 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.AppModels.Database; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services.Settings; +using OwlCore.Storage; + +namespace ClipboardCanvas.UI.ServiceImplementation.Settings +{ + /// + public sealed class UserSettings : SettingsModel, IUserSettings + { + /// + protected override IDatabaseModel SettingsDatabase { get; } + + public UserSettings(IModifiableFolder settingsFolder) + { + SettingsDatabase = new SingleFileDatabaseModel(Constants.FileNames.USER_SETTINGS_FILENAME, settingsFolder, DoubleSerializedStreamSerializer.Instance); + } + + public bool UninterruptedResume + { + get => GetSetting(static () => false); + set => SetSetting(value); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/SettingsService.cs b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/SettingsService.cs new file mode 100644 index 00000000..df70107b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ServiceImplementation/SettingsService.cs @@ -0,0 +1,37 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.Services.Settings; +using ClipboardCanvas.UI.ServiceImplementation.Settings; +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public sealed class SettingsService : ISettingsService + { + /// + public IAppSettings AppSettings { get; } + + /// + public IUserSettings UserSettings { get; } + + public SettingsService(IModifiableFolder settingsFolder) + { + AppSettings = new AppSettings(settingsFolder); + UserSettings = new UserSettings(settingsFolder); + } + + /// + public Task InitAsync(CancellationToken cancellationToken = default) + { + return Task.WhenAll(AppSettings.InitAsync(cancellationToken), UserSettings.InitAsync(cancellationToken)); + } + + /// + public Task SaveAsync(CancellationToken cancellationToken = default) + { + return Task.WhenAll(AppSettings.SaveAsync(cancellationToken), UserSettings.SaveAsync(cancellationToken)); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/Strings/en-US/Resources.resx b/src/Platforms/ClipboardCanvas.UI/Strings/en-US/Resources.resx new file mode 100644 index 00000000..0eb8b091 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/Strings/en-US/Resources.resx @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Close + + + Language + + + Select the display language + + + About + + + General + + + Theme + + + Dark + + + Change the look and feel + + + Light + + + System default + + \ No newline at end of file diff --git a/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseConverter.cs b/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseConverter.cs new file mode 100644 index 00000000..94830737 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseConverter.cs @@ -0,0 +1,14 @@ +using System; + +namespace ClipboardCanvas.UI.ValueConverters +{ + /// + /// Base class for value converters. + /// + public abstract class BaseConverter + { + protected abstract object? TryConvert(object? value, Type targetType, object? parameter); + + protected abstract object? TryConvertBack(object? value, Type targetType, object? parameter); + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseGenericEnumConverter.cs b/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseGenericEnumConverter.cs new file mode 100644 index 00000000..0e72af08 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseGenericEnumConverter.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ClipboardCanvas.UI.ValueConverters +{ + public abstract class BaseGenericEnumConverter : BaseConverter + { + /// + protected override object? TryConvert(object? value, Type targetType, object? parameter) + { + return ConvertInternal(value, targetType, parameter, + s => s.Split(',').ToDictionary(k => System.Convert.ToInt64(k.Split('-')[0]), v => System.Convert.ToInt64(v.Split('-')[1]))); + } + + /// + protected override object? TryConvertBack(object? value, Type targetType, object? parameter) + { + return ConvertInternal(value, targetType, parameter, + s => s.Split(',').ToDictionary(k => System.Convert.ToInt64(k.Split('-')[0]), v => System.Convert.ToInt64(v.Split('-')[1]))); + } + + private object ConvertInternal(object? value, Type targetType, object? parameter, Func> enumConversion) + { + var numberEnumValue = Convert.ToInt64(value); + if (parameter is string strParam) + { + // enumValue-convertedValue: 0-1,1-2 + var enumConversionValues = enumConversion(strParam); + if (enumConversionValues.TryGetValue(numberEnumValue, out var convertedValue)) + numberEnumValue = convertedValue; + + // else.. use value from the cast above + } + + try + { + if (Enum.GetName(targetType, numberEnumValue) is string enumName) + return Enum.Parse(targetType, enumName); + } + catch (Exception) { } + + try + { + return System.Convert.ChangeType(numberEnumValue, targetType); + } + catch (Exception) { } + + try + { + return Enum.ToObject(targetType, numberEnumValue); + } + catch (Exception) { } + + return numberEnumValue; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseNullToBoolConverter.cs b/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseNullToBoolConverter.cs new file mode 100644 index 00000000..034f677b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.UI/ValueConverters/BaseNullToBoolConverter.cs @@ -0,0 +1,30 @@ +using System; + +namespace ClipboardCanvas.UI.ValueConverters +{ + public abstract class BaseNullToBoolConverter : BaseConverter + { + /// + protected override object? TryConvert(object? value, Type targetType, object? parameter) + { + if (parameter is string strParam && strParam.ToLower() == "invert") + { + if (value is string str1) + return string.IsNullOrEmpty(str1); + + return value is null; + } + + if (value is string str) + return !string.IsNullOrEmpty(str); + + return value is not null; + } + + /// + protected override object? TryConvertBack(object? value, Type targetType, object? parameter) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/App.xaml b/src/Platforms/ClipboardCanvas.WinUI/App.xaml new file mode 100644 index 00000000..84cf6e90 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/App.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/App.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/App.xaml.cs new file mode 100644 index 00000000..e99e1c1c --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/App.xaml.cs @@ -0,0 +1,63 @@ +using ClipboardCanvas.UI.Helpers; +using ClipboardCanvas.WinUI.Helpers; +using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.UI.Xaml; +using System; +using System.Threading.Tasks; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + public partial class App : Application + { + private readonly BaseLifecycleHelper _applicationLifecycle; + private IServiceProvider? _serviceProvider; + + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + _applicationLifecycle = new WindowsLifecycleHelper(); + InitializeComponent(); + + // Configure exception handlers + UnhandledException += App_UnhandledException; + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; + } + + /// + /// Invoked when the application is launched. + /// + /// Details about the launch request and process. + protected override async void OnLaunched(LaunchActivatedEventArgs args) + { + // Configure IoC + var serviceCollection = await _applicationLifecycle.ConfigureAsync(); + _serviceProvider = serviceCollection.BuildServiceProvider(); + Ioc.Default.ConfigureServices(_serviceProvider); + + // Activate MainWindow + var window = MainWindow.Instance; + window.Activate(); + } + + #region Exception Handlers + + private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) => _applicationLifecycle.LogException(e.Exception); + + private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e) => _applicationLifecycle.LogException(e.ExceptionObject as Exception); + + private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e) => _applicationLifecycle.LogException(e.Exception); + + #endregion + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/AppModels/PdfFileDocument.cs b/src/Platforms/ClipboardCanvas.WinUI/AppModels/PdfFileDocument.cs new file mode 100644 index 00000000..9af748bf --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/AppModels/PdfFileDocument.cs @@ -0,0 +1,90 @@ +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.WinUI.Imaging; +using Microsoft.UI.Xaml.Media.Imaging; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Windows.Data.Pdf; +using Windows.Graphics.Imaging; +using Windows.Storage.Streams; + +namespace ClipboardCanvas.WinUI.AppModels +{ + /// + internal sealed class PdfFileDocument : IDocument + { + private readonly PdfDocument _pdfDocument; + + /// + public int PageCount => (int)_pdfDocument.PageCount; + + public PdfFileDocument(PdfDocument pdfDocument) + { + _pdfDocument = pdfDocument; + } + + /// + public Task GetPageAsync(int index, CancellationToken cancellationToken) + { + var page = _pdfDocument.GetPage((uint)index); + return Task.FromResult(new PdfDocumentPage(page)); + } + + /// + public async IAsyncEnumerable GetPagesAsync([EnumeratorCancellation] CancellationToken cancellationToken) + { + await Task.CompletedTask; + + for (var i = 0u; i < _pdfDocument.PageCount; i++) + { + var page = _pdfDocument.GetPage(i); + yield return new PdfDocumentPage(page); + } + } + + /// + public void Dispose() + { + } + } + + /// + internal sealed class PdfDocumentPage : IDocumentPage + { + private readonly PdfPage _pdfPage; + private IImage? _cachedImage; + + public PdfDocumentPage(PdfPage pdfPage) + { + _pdfPage = pdfPage; + } + + /// + public async Task AsImageAsync(CancellationToken cancellationToken) + { + if (_cachedImage is not null) + return _cachedImage; + + using var winrtStream = new InMemoryRandomAccessStream(); + await _pdfPage.RenderToStreamAsync(winrtStream).AsTask(cancellationToken); + + var decoder = await BitmapDecoder.CreateAsync(winrtStream).AsTask(cancellationToken); + var softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied).AsTask(cancellationToken); + + var source = new SoftwareBitmapSource(); + await source.SetBitmapAsync(softwareBitmap).AsTask(cancellationToken); + + return _cachedImage = new PdfPageImage(source, softwareBitmap); + } + + /// + public void Dispose() + { + // _cachedImage is not disposed here since it's the consumer + // responsibility to dispose of the resource they requested + _pdfPage.Dispose(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/AppModels/VideoSource.cs b/src/Platforms/ClipboardCanvas.WinUI/AppModels/VideoSource.cs new file mode 100644 index 00000000..90485bb4 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/AppModels/VideoSource.cs @@ -0,0 +1,26 @@ +using System; +using Windows.Media.Core; +using IMediaSource = ClipboardCanvas.Sdk.Models.IMediaSource; + +namespace ClipboardCanvas.WinUI.AppModels +{ + internal sealed class VideoSource : IMediaSource + { + private readonly IDisposable? _sourceDisposable; + + public MediaSource MediaSource { get; } + + public VideoSource(MediaSource mediaSource, IDisposable? sourceDisposable) + { + MediaSource = mediaSource; + _sourceDisposable = sourceDisposable; + } + + /// + public void Dispose() + { + _sourceDisposable?.Dispose(); + MediaSource.Dispose(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/LockScreenLogo.scale-200.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 00000000..7440f0d4 Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/LockScreenLogo.scale-200.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/SplashScreen.scale-200.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/SplashScreen.scale-200.png new file mode 100644 index 00000000..32f486a8 Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/SplashScreen.scale-200.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/Square150x150Logo.scale-200.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 00000000..53ee3777 Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/Square150x150Logo.scale-200.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/Square44x44Logo.scale-200.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 00000000..f713bba6 Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/Square44x44Logo.scale-200.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 00000000..dc9f5bea Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/StoreLogo.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/StoreLogo.png new file mode 100644 index 00000000..a4586f26 Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/StoreLogo.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Assets/Wide310x150Logo.scale-200.png b/src/Platforms/ClipboardCanvas.WinUI/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 00000000..8b4a5d0d Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Assets/Wide310x150Logo.scale-200.png differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/ClipboardCanvas.WinUI.csproj b/src/Platforms/ClipboardCanvas.WinUI/ClipboardCanvas.WinUI.csproj new file mode 100644 index 00000000..9f38db2e --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ClipboardCanvas.WinUI.csproj @@ -0,0 +1,227 @@ + + + + + True + True + win10-x86;win10-x64;win10-arm64 + x86;x64;ARM64 + net7.0-windows10.0.22621.0 + win10-$(Platform).pubxml + WinExe + ClipboardCanvas.WinUI + app.manifest + + 10.0.19041.0 + win10-$(Platform).pubxml + + + Language=en-US + en-US + + + True + True + + + disable + enable + + + False + False + True + False + Always + 0 + x86|x64|arm64 + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + MSBuild:Compile + + + + + + + + + + PreserveNewest + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + + + + true + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SaveConfirmationDialog.xaml b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SaveConfirmationDialog.xaml new file mode 100644 index 00000000..648b842a --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SaveConfirmationDialog.xaml @@ -0,0 +1,18 @@ + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SaveConfirmationDialog.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SaveConfirmationDialog.xaml.cs new file mode 100644 index 00000000..ea675a6f --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SaveConfirmationDialog.xaml.cs @@ -0,0 +1,41 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.ViewModels.Views.Overlays; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.UI.Utils; +using Microsoft.UI.Xaml.Controls; +using ClipboardCanvas.Sdk.Extensions; +using System; +using System.Threading.Tasks; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.Dialogs +{ + public sealed partial class SaveConfirmationDialog : ContentDialog, IOverlayControl + { + public SaveConfirmationOverlayViewModel ViewModel + { + get => (SaveConfirmationOverlayViewModel)DataContext; + set => DataContext = value; + } + + public SaveConfirmationDialog() + { + InitializeComponent(); + } + + /// + public new async Task ShowAsync() => ((DialogOption)await base.ShowAsync()).ParseOverlayOption(); + + /// + public void SetView(IViewable viewable) => ViewModel = (SaveConfirmationOverlayViewModel)viewable; + + /// + public Task HideAsync() + { + Hide(); + return Task.CompletedTask; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SettingsDialog.xaml b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SettingsDialog.xaml new file mode 100644 index 00000000..905206d2 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SettingsDialog.xaml @@ -0,0 +1,88 @@ + + + + + 1300 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SettingsDialog.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SettingsDialog.xaml.cs new file mode 100644 index 00000000..e2c53ec3 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Dialogs/SettingsDialog.xaml.cs @@ -0,0 +1,95 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Extensions; +using ClipboardCanvas.Sdk.ViewModels.Views.Overlays; +using ClipboardCanvas.Sdk.ViewModels.Views.Settings; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.UI.Helpers; +using ClipboardCanvas.UI.Utils; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System; +using System.Linq; +using System.Threading.Tasks; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.Dialogs +{ + public sealed partial class SettingsDialog : ContentDialog, IOverlayControl + { + public SettingsOverlayViewModel ViewModel + { + get => (SettingsOverlayViewModel)DataContext; + set => DataContext = value; + } + + public SettingsDialog() + { + InitializeComponent(); + } + + /// + public new async Task ShowAsync() => ((DialogOption)await base.ShowAsync()).ParseOverlayOption(); + + /// + public void SetView(IViewable viewable) => ViewModel = (SettingsOverlayViewModel)viewable; + + /// + public Task HideAsync() + { + Hide(); + return Task.CompletedTask; + } + + private IViewDesignation GetViewForTag(int tag) + { + return tag switch + { + 0 => ViewModel?.NavigationService.TryGetView() ?? new(), + //1 => ViewModel?.NavigationService.TryGetView() ?? new(), + 2 => ViewModel?.NavigationService.TryGetView() ?? new(), + _ => new GeneralSettingsViewModel() + }; + } + + private async void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) + { + if (ViewModel is null) + return; + + if (!ViewModel.NavigationService.SetupNavigation(Navigation)) + return; + + var tag = Convert.ToInt32((args.SelectedItem as NavigationViewItem)?.Tag); + var target = GetViewForTag(tag); + if (ViewModel.NavigationService.Views.FirstOrDefault(x => target == x) is null && target is IAsyncInitialize asyncInitialize) + _ = asyncInitialize.InitAsync(); + + await ViewModel.NavigationService.NavigateAsync(target); + } + + private void CloseButton_Click(object sender, RoutedEventArgs e) + { + Hide(); + } + + private async void SettingsDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args) + { + if (ViewModel is null) + return; + + if (!ViewModel.NavigationService.SetupNavigation(Navigation)) + return; + + var target = GetViewForTag(0); + await ViewModel.NavigationService.NavigateAsync(target); + } + + private void SettingsDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args) + { + // Remove the reference to the NavigationControl so the dialog can get properly garbage collected + ViewModel?.NavigationService.ResetNavigation(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Extensions/ImagingExtensions.cs b/src/Platforms/ClipboardCanvas.WinUI/Extensions/ImagingExtensions.cs new file mode 100644 index 00000000..c9e1e180 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Extensions/ImagingExtensions.cs @@ -0,0 +1,20 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage.Streams; +using Microsoft.UI.Xaml.Media.Imaging; + +namespace ClipboardCanvas.WinUI.Extensions +{ + public static class ImagingExtensions + { + public static async Task OpenReadAsync(this BitmapImage bitmapImage, CancellationToken cancellationToken) + { + var winrtStreamReference = RandomAccessStreamReference.CreateFromUri(bitmapImage.UriSource); + var winrtStream = await winrtStreamReference.OpenReadAsync().AsTask(cancellationToken); + + return winrtStream.AsStreamForRead(4096); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Helpers/FileTypeHelper.cs b/src/Platforms/ClipboardCanvas.WinUI/Helpers/FileTypeHelper.cs new file mode 100644 index 00000000..e74993ca --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Helpers/FileTypeHelper.cs @@ -0,0 +1,179 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Shared.Enums; +using MimeTypes; +using OwlCore.Storage; +using System; +using System.IO; +using System.Linq; + +namespace ClipboardCanvas.WinUI.Helpers +{ + public static class FileTypeHelper + { + public static TypeClassification GetClassification(IStorable storable) + { + var mimeType = MimeTypeMap.GetMimeType(storable.Id); + var extension = Path.GetExtension(storable.Id); + var typeHint = GetTypeFromMime(mimeType); + typeHint = typeHint == TypeHint.Unclassified ? GetTypeFromExtension(Path.GetExtension(storable.Id)) : typeHint; + + return new(mimeType, typeHint, extension); + } + + public static TypeHint GetType(IStorable storable) + { + var mimeType = MimeTypeMap.GetMimeType(storable.Id); + var typeHint = GetTypeFromMime(mimeType); + + return typeHint == TypeHint.Unclassified ? GetTypeFromExtension(Path.GetExtension(storable.Id)) : typeHint; + } + + public static TypeHint GetTypeFromMime(string mimeType) + { + return Image() + ?? PlainText() + ?? Document() + ?? Media() + // TODO + ?? TypeHint.Unclassified; + + TypeHint? Media() + { + return mimeType.Equals("video/x-msvideo") + || mimeType.Equals("video/mp4") + || mimeType.Equals("video/mpeg") + || mimeType.Equals("video/ogg") + || mimeType.Equals("video/webm") + || mimeType.Equals("video/3gpp") + || mimeType.Equals("video/3gpp2") + + ? TypeHint.Media : null; + } + + TypeHint? Document() + { + return mimeType.Equals("application/pdf") + || mimeType.Equals("text/csv") + || mimeType.Equals("application/msword") + || mimeType.Equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document") + + ? TypeHint.Document : null; + } + + TypeHint? PlainText() + { + return mimeType.StartsWith("text/") + && !mimeType.Equals("text/csv") + //|| mimeType.StartsWith("") + + ? TypeHint.PlainText : null; + } + + TypeHint? Image() + { + return mimeType.StartsWith("image/") + //|| mimeType.StartsWith("") + + ? TypeHint.Image : null; + } + } + + public static TypeHint GetTypeFromExtension(string extension) + { + if (!extension.StartsWith('.')) + extension = $".{extension}"; + + // PlainText (code) + if (CodeExtensions.Contains(extension)) + return TypeHint.PlainText; + + // PlainText (text) + if (TextExtensions.Contains(extension)) + return TypeHint.PlainText; + + // Document + if (DocumentExtensions.Contains(extension)) + return TypeHint.Document; + + // Image + if (ImageExtensions.Contains(extension)) + return TypeHint.Image; + + // Media + if (MediaExtensions.Contains(extension)) + return TypeHint.Media; + + // Audio + if (AudioExtensions.Contains(extension)) + return TypeHint.Audio; + + return TypeHint.Unclassified; + } + + public static string[] CodeExtensions { get; } = + { + // Low level languages + ".cpp", ".c", ".cxx", + ".h", ".def", ".pl", + ".rs", + + // Common languages + ".java", ".cs", ".py", + + // Web languages + ".htm", ".html", ".js", + ".css", ".svelte", ".php", + ".scss", ".ts", + + // Other + ".bat", ".xml", ".json", + ".inc", ".ini" + }; + + public static string[] TextExtensions { get; } = + { + // Text based + ".txt", ".md", ".markdown", ".rtf" + }; + + public static string[] DocumentExtensions { get; } = + { + // Document based + ".doc", ".docx", ".html", + ".odt", ".pdf", ".htm", + + // Sheet based + ".xls", ".xlsx", ".ods", + + // Presentation based + ".ppt", ".pptx" + }; + + public static string[] ImageExtensions { get; } = + { + // Special types + ".apng", ".avif", ".gif", + + // JPEG types + ".jpg", ".jpeg", ".jfif", + ".pjpeg", ".pjp", + + // Other types + ".png", ".svg", ".webp", + ".bmp", ".tif", ".tiff" + }; + + public static string[] MediaExtensions { get; } = + { + ".mp4", ".mov", ".avi", + ".wmv", ".flv", ".webm", + ".mkv", ".avi" + }; + + public static string[] AudioExtensions { get; } = + { + ".3gp", ".flac", ".mp3", + ".ogg", ".wav" + }; + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Helpers/ImagingHelpers.cs b/src/Platforms/ClipboardCanvas.WinUI/Helpers/ImagingHelpers.cs new file mode 100644 index 00000000..e1d1c93c --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Helpers/ImagingHelpers.cs @@ -0,0 +1,35 @@ +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.WinUI.Imaging; +using Microsoft.UI.Xaml.Media.Imaging; +using System; +using System.Threading; +using System.Threading.Tasks; +using Windows.Graphics.Imaging; +using Windows.Storage.Streams; + +namespace ClipboardCanvas.WinUI.Helpers +{ + internal static class ImagingHelpers + { + public static async Task GetBitmapFromStreamAsync(IRandomAccessStream winrtStream, string mimeType, CancellationToken cancellationToken) + { + using var winrtMemStream = new InMemoryRandomAccessStream(); + + var decoderGuid = MimeHelpers.MimeToBitmapDecoder(mimeType); + var encoderGuid = MimeHelpers.MimeToBitmapEncoder(mimeType); + + var decoder = await BitmapDecoder.CreateAsync(decoderGuid, winrtStream); + var encoder = await BitmapEncoder.CreateAsync(encoderGuid, winrtMemStream); + + var softwareBitmap = await decoder.GetSoftwareBitmapAsync().AsTask(cancellationToken); + encoder.SetSoftwareBitmap(softwareBitmap); + + await encoder.FlushAsync().AsTask(cancellationToken); + + var bitmap = new BitmapImage(); + await bitmap.SetSourceAsync(winrtMemStream).AsTask(cancellationToken); + + return new ImageBitmap(bitmap, softwareBitmap); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Helpers/MimeHelpers.cs b/src/Platforms/ClipboardCanvas.WinUI/Helpers/MimeHelpers.cs new file mode 100644 index 00000000..524294d6 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Helpers/MimeHelpers.cs @@ -0,0 +1,42 @@ +using System; +using Windows.Graphics.Imaging; + +namespace ClipboardCanvas.WinUI.Helpers +{ + internal static class MimeHelpers + { + public static Guid MimeToBitmapDecoder(string mimeType) + { + return mimeType switch + { + "image/bmp" => BitmapDecoder.BmpDecoderId, + "image/gif" => BitmapDecoder.GifDecoderId, + "image/heic" => BitmapDecoder.HeifDecoderId, + "image/vnd.microsoft.icon" => BitmapDecoder.IcoDecoderId, + "image/jpeg" => BitmapDecoder.JpegDecoderId, + "image/png" => BitmapDecoder.PngDecoderId, + "image/tiff" => BitmapDecoder.TiffDecoderId, + "image/webp" => BitmapDecoder.WebpDecoderId, + + _ => BitmapDecoder.PngDecoderId + }; + } + + public static Guid MimeToBitmapEncoder(string mimeType) + { + return mimeType switch + { + "image/bmp" => BitmapEncoder.BmpEncoderId, + "image/gif" => BitmapEncoder.GifEncoderId, + "image/heic" => BitmapEncoder.HeifEncoderId, + "image/vnd.microsoft.icon" => BitmapEncoder.PngEncoderId, + "image/jpeg" => BitmapEncoder.JpegEncoderId, + "image/png" => BitmapEncoder.PngEncoderId, + "image/tiff" => BitmapEncoder.TiffEncoderId, + "image/webp" => BitmapEncoder.PngEncoderId, + + _ => BitmapDecoder.PngDecoderId + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Helpers/WindowsLifecycleHelper.cs b/src/Platforms/ClipboardCanvas.WinUI/Helpers/WindowsLifecycleHelper.cs new file mode 100644 index 00000000..aae5fa50 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Helpers/WindowsLifecycleHelper.cs @@ -0,0 +1,74 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels; +using ClipboardCanvas.Sdk.ViewModels.Controls; +using ClipboardCanvas.UI.Helpers; +using ClipboardCanvas.UI.ServiceImplementation; +using ClipboardCanvas.WinUI.ServiceImplementation; +using Microsoft.Extensions.DependencyInjection; +using OwlCore.Storage; +using OwlCore.Storage.System.IO; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; + +namespace ClipboardCanvas.WinUI.Helpers +{ + /// + internal sealed class WindowsLifecycleHelper : BaseLifecycleHelper + { + /// + public override Task ConfigureAsync(CancellationToken cancellationToken = default) + { +#if !DEBUG + try + { + // Start AppCenter + var appCenterKey = ApiKeys.GetAppCenterKey(); + if (!string.IsNullOrEmpty(appCenterKey) || !AppCenter.Configured) + AppCenter.Start(appCenterKey, typeof(Analytics), typeof(Crashes)); + } + catch (Exception) + { + } +#endif + +#if UNPACKAGED + var settingsFolderPath = Path.Combine(Directory.GetCurrentDirectory(), ClipboardCanvas.UI.Constants.FileNames.SETTINGS_FOLDER_NAME); +#else + var settingsFolderPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, UI.Constants.FileNames.SETTINGS_FOLDER_NAME); +#endif + + var settingsFolder = new SystemFolder(Directory.CreateDirectory(settingsFolderPath)); + return Task.FromResult(ConfigureServices(settingsFolder)); + } + + /// + protected override IServiceCollection ConfigureServices(IModifiableFolder settingsFolder) + { + return new ServiceCollection() + + // View models + .AddSingleton() + .AddSingleton() + + // Singleton services + .AddSingleton(_ => new(settingsFolder)) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(_ => new(settingsFolder)) + + // Transient services + .AddTransient() + ; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Helpers/WindowsThemeHelper.cs b/src/Platforms/ClipboardCanvas.WinUI/Helpers/WindowsThemeHelper.cs new file mode 100644 index 00000000..dfe2ceb7 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Helpers/WindowsThemeHelper.cs @@ -0,0 +1,102 @@ +using ClipboardCanvas.UI.Enums; +using ClipboardCanvas.UI.Helpers; +using Microsoft.UI.Dispatching; +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; +using Windows.UI; +using Windows.UI.ViewManagement; + +namespace ClipboardCanvas.WinUI.Helpers +{ + /// + internal sealed class WindowsThemeHelper : ThemeHelper + { + private AppWindow? _appWindow; + private FrameworkElement? _rootContent; + private readonly UISettings _uiSettings; + private readonly DispatcherQueue _dispatcherQueue; + + /// + /// Gets the singleton instance of . + /// + public static WindowsThemeHelper Instance { get; } = new(); + + /// + /// Gets the current theme represented by . + /// + public ElementTheme CurrentElementTheme => (ElementTheme)(uint)CurrentTheme; + + /// + public override ThemeType CurrentTheme + { + get => base.CurrentTheme; + protected set + { + base.CurrentTheme = value; + OnPropertyChanged(nameof(CurrentElementTheme)); + } + } + + private WindowsThemeHelper() + { + _uiSettings = new(); + _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + _uiSettings.ColorValuesChanged += Settings_ColorValuesChanged; + } + + /// + public override void UpdateTheme() + { + if (_rootContent is not null) + { + if (CurrentTheme == ThemeType.Default) + _rootContent.RequestedTheme = Application.Current.RequestedTheme == ApplicationTheme.Dark ? ElementTheme.Dark : ElementTheme.Light; + else + _rootContent.RequestedTheme = (ElementTheme)(uint)CurrentTheme; + } + + if (_appWindow is not null && AppWindowTitleBar.IsCustomizationSupported()) + { + switch (CurrentTheme) + { + case ThemeType.Dark: + _appWindow.TitleBar.ButtonForegroundColor = Color.FromArgb(255, 255, 255, 255); + _appWindow.TitleBar.ButtonHoverBackgroundColor = Color.FromArgb(21, 255, 255, 255); + _appWindow.TitleBar.ButtonHoverForegroundColor = Color.FromArgb(255, 255, 255, 255); + _appWindow.TitleBar.ButtonPressedBackgroundColor = Color.FromArgb(8, 255, 255, 255); + _appWindow.TitleBar.ButtonPressedForegroundColor = Color.FromArgb(255, 255, 255, 255); + break; + + case ThemeType.Light: + _appWindow.TitleBar.ButtonForegroundColor = Color.FromArgb(228, 0, 0, 0); + _appWindow.TitleBar.ButtonHoverBackgroundColor = Color.FromArgb(128, 249, 249, 249); + _appWindow.TitleBar.ButtonHoverForegroundColor = Color.FromArgb(255, 0, 0, 0); + _appWindow.TitleBar.ButtonPressedBackgroundColor = Color.FromArgb(77, 249, 249, 249); + _appWindow.TitleBar.ButtonPressedForegroundColor = Color.FromArgb(255, 0, 0, 0); + break; + + case ThemeType.Default: + default: + _appWindow.TitleBar.ButtonForegroundColor = ((SolidColorBrush?)Application.Current.Resources["ButtonForeground"])?.Color; + _appWindow.TitleBar.ButtonHoverBackgroundColor = ((SolidColorBrush?)Application.Current.Resources["ButtonBackgroundPointerOver"])?.Color; + _appWindow.TitleBar.ButtonHoverForegroundColor = ((SolidColorBrush?)Application.Current.Resources["ButtonForegroundPointerOver"])?.Color; + _appWindow.TitleBar.ButtonPressedBackgroundColor = ((SolidColorBrush?)Application.Current.Resources["ButtonBackgroundPressed"])?.Color; + _appWindow.TitleBar.ButtonPressedForegroundColor = ((SolidColorBrush?)Application.Current.Resources["ButtonForegroundPressed"])?.Color; + break; + } + } + } + + public void RegisterWindowInstance(FrameworkElement? rootContent, AppWindow? appWindow = null) + { + _rootContent = rootContent; + _appWindow = appWindow; + } + + private void Settings_ColorValuesChanged(UISettings sender, object args) + { + _ = _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, UpdateTheme); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Images/TestImage.jpg b/src/Platforms/ClipboardCanvas.WinUI/Images/TestImage.jpg new file mode 100644 index 00000000..9e1a3c82 Binary files /dev/null and b/src/Platforms/ClipboardCanvas.WinUI/Images/TestImage.jpg differ diff --git a/src/Platforms/ClipboardCanvas.WinUI/Imaging/IconImage.cs b/src/Platforms/ClipboardCanvas.WinUI/Imaging/IconImage.cs new file mode 100644 index 00000000..2529787e --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Imaging/IconImage.cs @@ -0,0 +1,20 @@ +using ClipboardCanvas.Shared.ComponentModel; + +namespace ClipboardCanvas.WinUI.Imaging +{ + /// + internal sealed class IconImage : IImage + { + public string IconGlyph { get; } + + public IconImage(string iconGlyph) + { + IconGlyph = iconGlyph; + } + + /// + public void Dispose() + { + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Imaging/ImageBitmap.cs b/src/Platforms/ClipboardCanvas.WinUI/Imaging/ImageBitmap.cs new file mode 100644 index 00000000..1ccfb9be --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Imaging/ImageBitmap.cs @@ -0,0 +1,26 @@ +using ClipboardCanvas.Shared.ComponentModel; +using Microsoft.UI.Xaml.Media.Imaging; +using Windows.Graphics.Imaging; + +namespace ClipboardCanvas.WinUI.Imaging +{ + /// + public sealed class ImageBitmap : IImage + { + public SoftwareBitmap SoftwareBitmap { get; } + + public BitmapImage Source { get; } + + public ImageBitmap(BitmapImage source, SoftwareBitmap softwareBitmap) + { + Source = source; + SoftwareBitmap = softwareBitmap; + } + + /// + public void Dispose() + { + SoftwareBitmap?.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Platforms/ClipboardCanvas.WinUI/Imaging/PdfPageImage.cs b/src/Platforms/ClipboardCanvas.WinUI/Imaging/PdfPageImage.cs new file mode 100644 index 00000000..c9a4e513 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Imaging/PdfPageImage.cs @@ -0,0 +1,27 @@ +using ClipboardCanvas.Shared.ComponentModel; +using Microsoft.UI.Xaml.Media.Imaging; +using Windows.Graphics.Imaging; + +namespace ClipboardCanvas.WinUI.Imaging +{ + /// + internal sealed class PdfPageImage : IImage + { + public SoftwareBitmapSource ImageSource { get; } + + public SoftwareBitmap SoftwareBitmap { get; } + + public PdfPageImage(SoftwareBitmapSource imageSource, SoftwareBitmap softwareBitmap) + { + ImageSource = imageSource; + SoftwareBitmap = softwareBitmap; + } + + /// + public void Dispose() + { + ImageSource.Dispose(); + SoftwareBitmap.Dispose(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Localization/ResourceString.cs b/src/Platforms/ClipboardCanvas.WinUI/Localization/ResourceString.cs new file mode 100644 index 00000000..7ee3a563 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Localization/ResourceString.cs @@ -0,0 +1,29 @@ +using ClipboardCanvas.Sdk.Services; +using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.UI.Xaml.Markup; +using System.ComponentModel; + +namespace ClipboardCanvas.WinUI.Localization +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [MarkupExtensionReturnType(ReturnType = typeof(string))] + internal sealed class ResourceString : MarkupExtension + { + private static ILocalizationService? LocalizationService { get; set; } + + /// + /// Gets or sets the name identifier that is associated with a resource. + /// + public string? Name { get; set; } + + /// + protected override object ProvideValue() + { + LocalizationService ??= Ioc.Default.GetService(); + if (LocalizationService is null) + return $"{{{Name}}}"; + + return LocalizationService.TryGetString(Name ?? string.Empty) ?? $"{{{Name}}}"; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/MainWindow.xaml b/src/Platforms/ClipboardCanvas.WinUI/MainWindow.xaml new file mode 100644 index 00000000..33048931 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/MainWindow.xaml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/MainWindow.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/MainWindow.xaml.cs new file mode 100644 index 00000000..6973cf90 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/MainWindow.xaml.cs @@ -0,0 +1,78 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels; +using ClipboardCanvas.Shared.Extensions; +using ClipboardCanvas.WinUI.Helpers; +using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.UI; +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using WinUIEx; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI +{ + /// + /// An empty window that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainWindow : WindowEx + { + private static MainWindow? _Instance; + public static MainWindow Instance => _Instance ??= new(); + + public MainViewModel MainViewModel { get; } = new(); + + public MainWindow() + { + InitializeComponent(); + EnsureEarlyWindow(); + } + + private async void EnsureEarlyWindow() + { + // Set persistence id + PersistenceId = UI.Constants.Application.MAIN_WINDOW_ID; + + // Set title + AppWindow.Title = "Clipboard Canvas"; + + if (AppWindowTitleBar.IsCustomizationSupported()) + { + // Extend title bar + AppWindow.TitleBar.ExtendsContentIntoTitleBar = true; + + // Set window buttons background to transparent + AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent; + AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; + } + else + { + ExtendsContentIntoTitleBar = true; + SetTitleBar(AppControl.CustomTitleBar); + } + + // Set min size + MinHeight = 572; + MinWidth = 662; + + // Hook up event for window closing + AppWindow.Closing += AppWindow_Closing; + + // Setup ThemeHelper + WindowsThemeHelper.Instance.RegisterWindowInstance(Content as FrameworkElement, AppWindow); + await WindowsThemeHelper.Instance.InitAsync(); + } + + private async void AppControl_Loaded(object sender, RoutedEventArgs e) + { + await MainViewModel.InitAsync(); + } + + private async void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args) + { + var settingsService = Ioc.Default.GetRequiredService(); + await settingsService.TrySaveAsync(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Package.appxmanifest b/src/Platforms/ClipboardCanvas.WinUI/Package.appxmanifest new file mode 100644 index 00000000..c45dfa04 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Package.appxmanifest @@ -0,0 +1,52 @@ + + + + + + + + + + Clipboard Canvas + d2dyno + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Properties/launchSettings.json b/src/Platforms/ClipboardCanvas.WinUI/Properties/launchSettings.json new file mode 100644 index 00000000..169637e4 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "ClipboardCanvas (Package)": { + "commandName": "MsixPackage" + }, + "ClipboardCanvas (Unpackaged)": { + "commandName": "Project" + } + } +} \ No newline at end of file diff --git a/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Brushes.xaml b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Brushes.xaml new file mode 100644 index 00000000..2851763e --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Brushes.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Buttons.xaml b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Buttons.xaml new file mode 100644 index 00000000..3848808d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Buttons.xaml @@ -0,0 +1,100 @@ + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/ListViews.xaml b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/ListViews.xaml new file mode 100644 index 00000000..4959a350 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/ListViews.xaml @@ -0,0 +1,62 @@ + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Texts.xaml b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Texts.xaml new file mode 100644 index 00000000..3843b6c3 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ResourceDictionaries/Texts.xaml @@ -0,0 +1,10 @@ + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/ApplicationService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/ApplicationService.cs new file mode 100644 index 00000000..20524f76 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/ApplicationService.cs @@ -0,0 +1,48 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.UI.ServiceImplementation; +using OwlCore.Storage; +using System; +using System.Threading; +using System.Threading.Tasks; +using Windows.ApplicationModel; +using Windows.System; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class ApplicationService : BaseApplicationService + { + /// + public override string Platform { get; } = "Windows"; + + /// + public override Version AppVersion + { + get + { + var packageVersion = Package.Current.Id.Version; + return new Version(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision); + } + } + + /// + public override async Task OpenUriAsync(Uri uri) + { + await Launcher.LaunchUriAsync(uri); + } + + /// + public override Task TryRestartAsync() + { + Microsoft.Windows.AppLifecycle.AppInstance.Restart("/RestartCalled"); + return Task.CompletedTask; + } + + /// + public override async Task LaunchHandlerAsync(IFile file, CancellationToken cancellationToken) + { + var uri = new Uri(file.Id); + await Launcher.LaunchUriAsync(uri).AsTask(cancellationToken); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/CanvasService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/CanvasService.cs new file mode 100644 index 00000000..d1ffda6e --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/CanvasService.cs @@ -0,0 +1,66 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Canvases; +using ClipboardCanvas.Shared.Enums; +using ClipboardCanvas.WinUI.Helpers; +using OwlCore.Storage; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class CanvasService : ICanvasService + { + /// + public async Task GetCanvasForStorableAsync(IStorableChild storable, IDataSourceModel sourceModel, CancellationToken cancellationToken) + { + var classification = FileTypeHelper.GetClassification(storable); + var viewModel = (storable is IFile file ? classification.TypeHint switch + { + TypeHint.Image => new ImageCanvasViewModel(file, sourceModel), + TypeHint.PlainText => MatchText(file, sourceModel, classification), + TypeHint.Media => new VideoCanvasViewModel(file, sourceModel), + TypeHint.Document => MatchDocument(file, sourceModel, classification), + _ => null, + + } : MatchAlternative(storable, sourceModel, classification)) + + // TODO: Return fallback canvas + ?? throw new ArgumentOutOfRangeException(nameof(classification.TypeHint)); + + // Initialize and return + await viewModel.InitAsync(cancellationToken); + return viewModel; + } + + private static BaseCanvasViewModel? MatchText(IFile file, IDataSourceModel sourceModel, TypeClassification classification) + { + if (classification.Extension is not null && FileTypeHelper.CodeExtensions.Contains(classification.Extension)) + return new CodeCanvasViewModel(file, sourceModel); + + return new TextCanvasViewModel(file, sourceModel); + } + + private static BaseCanvasViewModel? MatchDocument(IFile file, IDataSourceModel sourceModel, TypeClassification classification) + { + if (classification.MimeType == "application/pdf") + return new PdfCanvasViewModel(file, sourceModel); + + return null; + } + + private static BaseCanvasViewModel? MatchAlternative(IStorable storable, IDataSourceModel sourceModel, TypeClassification classification) + { + if (storable is not IFolder folder) + return null; + + // TODO: Maybe match to Infinite Canvas as well? + _ = classification; + return new FolderCanvasViewModel(folder, sourceModel); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/ClipboardService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/ClipboardService.cs new file mode 100644 index 00000000..22619df7 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/ClipboardService.cs @@ -0,0 +1,197 @@ +using ClipboardCanvas.Sdk.AppModels; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Enums; +using ClipboardCanvas.WinUI.Extensions; +using ClipboardCanvas.WinUI.Helpers; +using ClipboardCanvas.WinUI.Imaging; +using ClipboardCanvas.WinUI.Storage; +using OwlCore.Storage; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Windows.ApplicationModel.DataTransfer; +using Windows.Storage; +using Windows.Storage.Streams; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class ClipboardService : IClipboardService + { + /// + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + /// + public Task GetContentAsync(CancellationToken cancellationToken) + { + var data = Clipboard.GetContent(); + if (data == null) + return Task.FromResult(null); + + return Task.FromResult(ClipboardData.Import(data)); + } + + /// + public async Task SetImageAsync(IImage image, CancellationToken cancellationToken) + { + var dataPackage = new DataPackage(); + if (image is ImageBitmap bitmapImage) + { + var stream = await bitmapImage.Source.OpenReadAsync(cancellationToken); + dataPackage.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream.AsRandomAccessStream())); + } + + Clipboard.SetContent(dataPackage); + } + + /// + public Task SetTextAsync(string text, CancellationToken cancellationToken) + { + var dataPackage = new DataPackage(); + dataPackage.SetText(text); + Clipboard.SetContent(dataPackage); + + return Task.CompletedTask; + } + + /// + public Task SetStorageAsync(IEnumerable storage, CancellationToken cancellationToken) + { + if (storage == null) + throw new ArgumentNullException(nameof(storage)); + + var dataPackage = new DataPackage(); + foreach (var item in storage) + { + if (item is WindowsStorageFolder folder) + dataPackage.SetStorageItems(new IStorageItem[] { folder.storage }); + + if (item is WindowsStorageFile file) + dataPackage.SetStorageItems(new IStorageItem[] { file.storage }); + } + + return Task.CompletedTask; + } + } + + /// + internal sealed class ClipboardData : IClipboardData + { + private readonly DataPackageView _dataPackage; + + /// + public TypeClassification Classification { get; } + + public ClipboardData(DataPackageView dataPackage, TypeClassification classification) + { + _dataPackage = dataPackage; + Classification = classification; + } + + public Task GetTextAsync(CancellationToken cancellationToken) + { + if (Classification.TypeHint == TypeHint.PlainText) + return _dataPackage.GetTextAsync().AsTask(cancellationToken); + + return Task.FromResult(string.Empty); + } + + public async Task GetImageAsync(CancellationToken cancellationToken) + { + if (Classification.TypeHint == TypeHint.Image) + { + var winrtStreamReference = await _dataPackage.GetBitmapAsync().AsTask(cancellationToken); + using var winrtStream = await winrtStreamReference.OpenReadAsync().AsTask(cancellationToken); + + var mimeType = winrtStream.ContentType; + return await ImagingHelpers.GetBitmapFromStreamAsync(winrtStream, mimeType, cancellationToken); + } + + throw new InvalidOperationException("Could not retrieve image."); + } + + public async Task OpenReadAsync(CancellationToken cancellationToken) + { + switch (Classification.TypeHint) + { + case TypeHint.Storage: + { + var files = await GetStorageAsync(cancellationToken).ToListAsync(cancellationToken); + var storable = files.FirstOrDefault(); + if (storable is IFile file) + return await file.OpenStreamAsync(FileAccess.Read, cancellationToken); + + throw new InvalidOperationException("The item is not a file."); + } + + case TypeHint.Image: + { + var image = await GetImageAsync(cancellationToken); + if (image is ImageBitmap bitmap) + return await bitmap.Source.OpenReadAsync(cancellationToken); + + throw new FormatException("Could not read the bitmap."); + } + + case TypeHint.PlainText: + case TypeHint.Document: + throw new NotImplementedException(); + + case TypeHint.Media: + case TypeHint.Audio: + throw new NotImplementedException(); + + default: + case TypeHint.Unclassified: + throw new InvalidOperationException("Could not open a stream to clipboard data."); + } + } + + public async IAsyncEnumerable GetStorageAsync(CancellationToken cancellationToken) + { + if (Classification.TypeHint == TypeHint.Storage) + { + var storageItems = await _dataPackage.GetStorageItemsAsync().AsTask(cancellationToken); + foreach (var item in storageItems) + { + yield return item switch + { + StorageFile file => new WindowsStorageFile(file), + StorageFolder folder => new WindowsStorageFolder(folder), + _ => throw new NotSupportedException() + }; + } + } + } + + public static ClipboardData Import(DataPackageView dataPackage) + { + if (dataPackage.Contains(StandardDataFormats.StorageItems)) + return new(dataPackage, new("application/octet-stream", TypeHint.Storage)); + + if (dataPackage.Contains(StandardDataFormats.Bitmap)) + return new(dataPackage, new("image/png", TypeHint.Image)); + + if (dataPackage.Contains(StandardDataFormats.Text)) + return new(dataPackage, new("text/plain", TypeHint.PlainText)); + + if (dataPackage.Contains(StandardDataFormats.Rtf)) + return new(dataPackage, new("application/rtf", TypeHint.Document)); + + if (dataPackage.Contains(StandardDataFormats.WebLink) + || dataPackage.Contains(StandardDataFormats.Uri) + || dataPackage.Contains(StandardDataFormats.ApplicationLink)) + return new(dataPackage, new("text/uri-list", TypeHint.UriLink)); + + if (dataPackage.Contains(StandardDataFormats.Html)) + return new(dataPackage, new("text/html", TypeHint.Document)); + + return new ClipboardData(dataPackage, new("application/octet-stream", TypeHint.Unclassified)); + } + } +} \ No newline at end of file diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/DialogService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/DialogService.cs new file mode 100644 index 00000000..31391f51 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/DialogService.cs @@ -0,0 +1,36 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Views.Overlays; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.UI.ServiceImplementation; +using ClipboardCanvas.UI.Utils; +using ClipboardCanvas.WinUI.Dialogs; +using Microsoft.UI.Xaml.Controls; +using System; +using Windows.Foundation.Metadata; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class DialogService : BaseOverlayService + { + /// + protected override IOverlayControl GetOverlay(IViewable viewable) + { + IOverlayControl overlay = viewable switch + { + SettingsOverlayViewModel => new SettingsDialog(), + SaveConfirmationOverlayViewModel => new SaveConfirmationDialog(), + // TODO: Implement location choosing save dialog + + _ => throw new ArgumentException("Unknown viewable type.", nameof(viewable)) + }; + +#if WINDOWS + if (overlay is ContentDialog contentDialog && ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8)) + contentDialog.XamlRoot = MainWindow.Instance?.Content.XamlRoot; +#endif + + return overlay; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/DocumentService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/DocumentService.cs new file mode 100644 index 00000000..3716363c --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/DocumentService.cs @@ -0,0 +1,22 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.WinUI.AppModels; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Windows.Data.Pdf; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class DocumentService : IDocumentService + { + /// + public async Task ReadPdfAsync(Stream pdfStream, CancellationToken cancellationToken) + { + var document = await PdfDocument.LoadFromStreamAsync(pdfStream.AsRandomAccessStream()).AsTask(cancellationToken); + return new PdfFileDocument(document); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/MediaService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/MediaService.cs new file mode 100644 index 00000000..1c949f52 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/MediaService.cs @@ -0,0 +1,172 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Models; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Enums; +using ClipboardCanvas.WinUI.AppModels; +using ClipboardCanvas.WinUI.Helpers; +using ClipboardCanvas.WinUI.Imaging; +using MimeTypes; +using OwlCore.Storage; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Windows.Graphics.Imaging; +using Windows.Media.Core; +using IMediaSource = ClipboardCanvas.Sdk.Models.IMediaSource; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class MediaService : IMediaService + { + /// + public async Task SaveImageAsync(IImage image, IFile destination, CancellationToken cancellationToken) + { + if (image is not ImageBitmap bitmap) + return; + + await using var stream = await destination.OpenStreamAsync(FileAccess.ReadWrite, cancellationToken); + using var winrtStream = stream.AsRandomAccessStream(); + + var mimeType = MimeTypeMap.GetMimeType(destination.Id); + var encoderGuid = MimeHelpers.MimeToBitmapEncoder(mimeType); + var encoder = await BitmapEncoder.CreateAsync(encoderGuid, winrtStream).AsTask(cancellationToken); + + encoder.SetSoftwareBitmap(bitmap.SoftwareBitmap); + encoder.IsThumbnailGenerated = true; + + try + { + await encoder.FlushAsync(); + } + catch (Exception err) + { + const int WINCODEC_ERR_UNSUPPORTEDOPERATION = unchecked((int)0x88982F81); + switch (err.HResult) + { + case WINCODEC_ERR_UNSUPPORTEDOPERATION: + // If the encoder does not support writing a thumbnail, then try again + // but disable thumbnail generation. + encoder.IsThumbnailGenerated = false; + break; + default: + throw; + } + } + + if (!encoder.IsThumbnailGenerated) + await encoder.FlushAsync(); + } + + /// + public async Task ReadImageAsync(IFile file, CancellationToken cancellationToken) + { + await using var stream = await file.OpenStreamAsync(FileAccess.Read, cancellationToken); + using var winrtStream = stream.AsRandomAccessStream(); + + var mimeType = MimeTypeMap.GetMimeType(file.Id); + return await ImagingHelpers.GetBitmapFromStreamAsync(winrtStream, mimeType, cancellationToken); + } + + /// + public async Task GetCollectionIconAsync(IDataSourceModel collectionModel, CancellationToken cancellationToken) + { + var unclassified = 0u; + var documents = 0u; + var images = 0u; + var media = 0u; + var audio = 0u; + + await foreach (var item in collectionModel.Source.GetItemsAsync(StorableType.All, cancellationToken)) + { + var typeHint = FileTypeHelper.GetType(item); + switch (typeHint) + { + case TypeHint.Unclassified: + unclassified++; + break; + + case TypeHint.Document: + case TypeHint.PlainText: + documents++; + break; + + case TypeHint.Image: + images++; + break; + + case TypeHint.Media: + media++; + break; + + case TypeHint.Audio: + audio++; + break; + } + } + + ulong total = unclassified + documents + images + media + audio; + if (total == 0UL) + return new IconImage("\uF0E2"); + + var unclassified2 = (unclassified * 100f) / total; + var documents2 = (documents * 100f) / total; + var images2 = (images * 100f) / total; + var media2 = (media * 100f) / total; + var audio2 = (audio * 100f) / total; + + string glyph; + if (IsMajority(unclassified2, documents2, images2, media2, audio2)) glyph = "\uF0E2"; + else if (IsMajority(documents2, unclassified2, images2, media2, audio2)) glyph = "\uE8A5"; + else if (IsMajority(images2, unclassified2, documents2, media2, audio2)) glyph = "\uE91B"; + else if (IsMajority(media2, unclassified2, documents2, images2, audio2)) glyph = "\uE714"; + else if (IsMajority(audio2, unclassified2, documents2, images2, media2)) glyph = "\uE8D6"; + else glyph = "\uF0E2"; + + return new IconImage(glyph); + } + + /// + public async Task GetVideoPlaybackAsync(IFile file, CancellationToken cancellationToken) + { + var stream = await file.OpenStreamAsync(FileAccess.Read, cancellationToken); + var mime = MimeTypeMap.GetMimeType(file.Id); + + var mediaSource = MediaSource.CreateFromStream(stream.AsRandomAccessStream(), mime); + return new VideoSource(mediaSource, stream); + } + + /// + public IImage? GetIcon(IconType iconType) + { + var glyph = iconType switch + { + IconType.Share => "\uE72D", + IconType.Edit => "\uE70F", + IconType.Open => "\uE8E5", + _ => null + }; + + if (glyph is null) + return null; + + return new IconImage(glyph); + } + + private static bool IsMajority(float first, params float[] other) + { + if (first >= 50f) + return true; + + foreach (var item in other) + { + if (item > first) + return false; + } + + return true; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/OcrService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/OcrService.cs new file mode 100644 index 00000000..e1a5bc5b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/OcrService.cs @@ -0,0 +1,38 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Controls.Documents; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.WinUI.Imaging; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using Windows.Media.Ocr; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class OcrService : ITextRecognitionService + { + /// + public async IAsyncEnumerable RecognizeAsync(IImage image, [EnumeratorCancellation] CancellationToken cancellationToken) + { + if (image is not PdfPageImage pdfImage) + yield break; + + var ocr = OcrEngine.TryCreateFromUserProfileLanguages(); + if (ocr is null) + yield break; + + var result = await ocr.RecognizeAsync(pdfImage.SoftwareBitmap).AsTask(cancellationToken); + foreach (var line in result.Lines) + { + var firstWord = line.Words.First(); + var rectangle = new Rectangle((int)firstWord.BoundingRect.X, (int)firstWord.BoundingRect.Y, (int)firstWord.BoundingRect.Width, (int)firstWord.BoundingRect.Height); + + yield return new OcrStringViewModel(line.Text, rectangle); + } + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsFileExplorerService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsFileExplorerService.cs new file mode 100644 index 00000000..ebf49954 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsFileExplorerService.cs @@ -0,0 +1,65 @@ +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.WinUI.Storage; +using OwlCore.Storage; +using OwlCore.Storage.System.IO; +using System; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Pickers; +using Windows.System; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class WindowsFileExplorerService : IFileExplorerService + { + /// + public async Task OpenAppFolderAsync(CancellationToken cancellationToken = default) + { + await Launcher.LaunchFolderAsync(ApplicationData.Current.LocalFolder).AsTask(cancellationToken); + } + + /// + public async Task OpenInFileExplorerAsync(IFolder folder, IStorableChild? highlight, CancellationToken cancellationToken = default) + { + var options = new FolderLauncherOptions(); + if (highlight is not null) + { + var windowsStorable = (IStorageItem?)(highlight as WindowsStorageFile)?.storage ?? (highlight as WindowsStorageFolder)?.storage; + windowsStorable ??= highlight is IFile + ? await StorageFile.GetFileFromPathAsync(highlight.Id) + : await StorageFolder.GetFolderFromPathAsync(highlight.Id); + + options.ItemsToSelect.Add(windowsStorable); + } + + await Launcher.LaunchFolderPathAsync(folder.Id, options).AsTask(cancellationToken); + } + + /// + public async Task PickFolderAsync(CancellationToken cancellationToken = default) + { + var folderPicker = new FolderPicker(); + InitializeObject(folderPicker); + + folderPicker.FileTypeFilter.Add("*"); + var folder = await folderPicker.PickSingleFolderAsync().AsTask(cancellationToken); + if (folder is null) + return null; + + // Since we're running natively on Windows we can avoid using Windows.Storage because it's very slow + return new SystemFolder(folder.Path); + //return new Storage.WindowsStorageFolder(folder); + } + + private static void InitializeObject(object obj) + { + _ = obj; +#if WINDOWS + var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(MainWindow.Instance); + WinRT.Interop.InitializeWithWindow.Initialize(obj, hwnd); +#endif + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsLocalizationService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsLocalizationService.cs new file mode 100644 index 00000000..115a15ed --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsLocalizationService.cs @@ -0,0 +1,69 @@ +using ClipboardCanvas.UI.ServiceImplementation; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Windows.Globalization; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + internal sealed class WindowsLocalizationService : ResourceLocalizationService + { + /// + public override Task SetCultureAsync(CultureInfo cultureInfo) + { + ApplicationLanguages.PrimaryLanguageOverride = cultureInfo.Name; + return base.SetCultureAsync(cultureInfo); + } + + /// + protected override CultureInfo GetCurrentCulture() + { + // PrimaryLanguageOverride may return an empty string and thus it is better to use null as the "empty" equivalent + var primaryLanguageOverride = string.IsNullOrEmpty(ApplicationLanguages.PrimaryLanguageOverride) ? null : ApplicationLanguages.PrimaryLanguageOverride; + + // Prefer PrimaryLanguageOverride as the default language identifier here since it provides + // package compliant language identifiers. However, PrimaryLanguageOverride holds less information + // about a specific culture than AppLanguage property. Oftentimes the 'country' identifier + // is removed from the name part of a culture when PrimaryLanguageOverride is used. + // For example: + // PrimaryLanguageOverride may save an identifier as: "uk" + // While AppLanguage may save the fully-qualified identifier: "uk-UA" + var languageString = primaryLanguageOverride ?? AppSettings.AppLanguage; + if (string.IsNullOrEmpty(languageString)) + return DefaultCulture; + + // By getting the identifier from PrimaryLanguageOverride we then check against ManifestLanguages, + // to determine whether that specified language exists. Instead of checking if ManifestLanguages + // contains the specified languageString, we instead need to check whether that languageString starts with + // an item from ManifestLanguages. This is due to the fact, that ManifestLanguages sometimes loses information + // about the 'country' identifier whilst languageString may not (in case AppLanguage was chosen) + // and therefore wouldn't yield any results. + if (!ApplicationLanguages.ManifestLanguages.Aggregate(false, (current, item) => current | languageString.StartsWith(item))) + return DefaultCulture; + + // To get the fully-qualified language identifier, and therefore the most compatible one, + // we need to again perform the null-coalescing expression, however, this time the null-check + // order is swapped and consequently AppLanguage property is more preferred than PrimaryLanguageOverride. + // By doing the swap, we ensure that the most compliant identifier is returned. + languageString = AppSettings.AppLanguage ?? primaryLanguageOverride; + if (string.IsNullOrEmpty(languageString)) + return DefaultCulture; + + return new(languageString); + } + + /// + protected override IEnumerable GetAppLanguages() + { + // We need to deflate the SupportedLanguages list by ManifestLanguages + foreach (var item in ApplicationLanguages.ManifestLanguages) + { + // Instead of returning entries of ManifestLanguages, we return our own + // entries of SupportedLanguages that fully qualify each language + yield return new(SupportedLanguages.First(x => x.Contains(item))); + } + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsNavigationService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsNavigationService.cs new file mode 100644 index 00000000..90969d5d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsNavigationService.cs @@ -0,0 +1,80 @@ +using ClipboardCanvas.Sdk.Enums; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.Shared.Extensions; +using ClipboardCanvas.UI.ServiceImplementation; +using ClipboardCanvas.WinUI.UserControls.Navigation; +using Microsoft.UI.Xaml.Media.Animation; +using System.Linq; +using System.Threading.Tasks; + +namespace ClipboardCanvas.WinUI.ServiceImplementation +{ + /// + public sealed class WindowsNavigationService : BaseNavigationService + { + /// + protected override async Task BeginNavigationAsync(IViewDesignation? view, NavigationType navigationType) + { + if (NavigationControl is null) + return false; + + switch (navigationType) + { + case NavigationType.Backward: + { + if (NavigationControl is not FrameNavigationControl frameNavigation) + return false; + + if (!frameNavigation.ContentFrame.CanGoBack) + return false; + + // Navigate back + frameNavigation.ContentFrame.GoBack(); + + var contentType = frameNavigation.Content?.GetType(); + if (contentType is null) + return false; + + var targetType = frameNavigation.TypeBinding.GetByKeyOrValue(contentType); + var backTarget = Views.FirstOrDefault(x => x.GetType() == targetType); + if (backTarget is not null) + CurrentView = backTarget; + + return true; + } + + case NavigationType.Forward: + { + if (NavigationControl is not FrameNavigationControl frameNavigation) + return false; + + if (!frameNavigation.ContentFrame.CanGoForward) + return false; + + // Navigate forward + frameNavigation.ContentFrame.GoForward(); + + var contentType = frameNavigation.ContentFrame.Content?.GetType(); + if (contentType is null) + return false; + + var targetType = frameNavigation.TypeBinding.GetByKeyOrValue(contentType); + var forwardTarget = Views.FirstOrDefault(x => x.GetType() == targetType); + if (forwardTarget is not null) + CurrentView = forwardTarget; + return true; + } + + default: + case NavigationType.Chained: + { + if (view is null) + return false; + + return await NavigationControl.NavigateAsync(view, (NavigationTransitionInfo?)null); + } + } + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsStorageService.cs b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsStorageService.cs new file mode 100644 index 00000000..566c0146 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ServiceImplementation/WindowsStorageService.cs @@ -0,0 +1,45 @@ +using ClipboardCanvas.Sdk.Services; +using OwlCore.Storage; +using OwlCore.Storage.System.IO; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; + +namespace ClipboardCanvas.UI.ServiceImplementation +{ + /// + public sealed class WindowsStorageService : IStorageService + { + /// + public Task GetAppFolderAsync(CancellationToken cancellationToken = default) + { + return Task.FromResult(new SystemFolder(ApplicationData.Current.LocalFolder.Path)); + } + + /// + public Task GetFromBookmarkAsync(string id, CancellationToken cancellationToken = default) + { + if (IsFile(id)) + return Task.FromResult(new SystemFile(id)); + + if (IsFolder(id)) + return Task.FromResult(new SystemFolder(id)); + + throw new ArgumentException("The path is not a file nor a folder.", nameof(id)); + + static bool IsFolder(string path) + => Directory.Exists(path); + + static bool IsFile(string path) + => Path.GetFileName(path) is { } str && str != string.Empty && File.Exists(path); + } + + /// + public Task RemoveBookmark(IStorable storable, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorable.cs b/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorable.cs new file mode 100644 index 00000000..5a2cf0f9 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorable.cs @@ -0,0 +1,30 @@ +using OwlCore.Storage; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; + +namespace ClipboardCanvas.WinUI.Storage +{ + /// + internal abstract class WindowsStorable : IStorableChild + where TStorage : class, IStorageItem + { + internal readonly TStorage storage; + + /// + public string Name { get; protected set; } + + /// + public virtual string Id { get; } + + protected WindowsStorable(TStorage storage) + { + this.storage = storage; + this.Id = storage.Path; + this.Name = storage.Name; + } + + /// + public abstract Task GetParentAsync(CancellationToken cancellationToken = default); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorageFile.cs b/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorageFile.cs new file mode 100644 index 00000000..a383bfb0 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorageFile.cs @@ -0,0 +1,67 @@ +using ClipboardCanvas.Sdk.Storage; +using OwlCore.Storage; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; + +namespace ClipboardCanvas.WinUI.Storage +{ + /// + internal sealed class WindowsStorageFile : WindowsStorable, IChildFile, IFileExtended + { + public WindowsStorageFile(StorageFile storageFile) + : base(storageFile) + { + } + + /// + public Task OpenStreamAsync(FileAccess access, CancellationToken cancellationToken = default) + { + return OpenStreamAsync(access, FileShare.None, cancellationToken); + } + + /// + public async Task OpenStreamAsync(FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default) + { + var fileAccessMode = GetFileAccessMode(access); + var storageOpenOptions = GetStorageOpenOptions(share); + var winrtStream = await storage.OpenAsync(fileAccessMode, storageOpenOptions).AsTask(cancellationToken); + + return winrtStream.AsStream(); + } + + /// + public override async Task GetParentAsync(CancellationToken cancellationToken = default) + { + var parentFolder = await storage.GetParentAsync().AsTask(cancellationToken); + return new WindowsStorageFolder(parentFolder); + } + + private static FileAccessMode GetFileAccessMode(FileAccess access) + { + return access switch + { + FileAccess.Read => FileAccessMode.Read, + FileAccess.Write => FileAccessMode.ReadWrite, + FileAccess.ReadWrite => FileAccessMode.ReadWrite, + _ => throw new ArgumentOutOfRangeException(nameof(access)) + }; + } + + private static StorageOpenOptions GetStorageOpenOptions(FileShare share) + { + return share switch + { + FileShare.Read => StorageOpenOptions.AllowOnlyReaders, + FileShare.Write => StorageOpenOptions.AllowReadersAndWriters, + FileShare.ReadWrite => StorageOpenOptions.AllowReadersAndWriters, + FileShare.Inheritable => StorageOpenOptions.None, + FileShare.Delete => StorageOpenOptions.None, + FileShare.None => StorageOpenOptions.None, + _ => throw new ArgumentOutOfRangeException(nameof(share)) + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorageFolder.cs b/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorageFolder.cs new file mode 100644 index 00000000..498bcae1 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Storage/WindowsStorageFolder.cs @@ -0,0 +1,164 @@ +using ClipboardCanvas.Sdk.Storage; +using OwlCore.Storage; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; + +namespace ClipboardCanvas.WinUI.Storage +{ + /// + internal sealed class WindowsStorageFolder : WindowsStorable, IChildFolder, IDirectCopy, IDirectMove, IGetFirstByName + { + // TODO: Implement IMutableFolder + + public WindowsStorageFolder(StorageFolder storageFolder) + : base(storageFolder) + { + } + + /// + public async Task GetFirstByNameAsync(string name, CancellationToken cancellationToken = default) + { + return await storage.GetItemAsync(name).AsTask(cancellationToken) switch + { + StorageFile storageFile => new WindowsStorageFile(storageFile), + StorageFolder storageFolder => new WindowsStorageFolder(storageFolder) + }; + } + + /// + public async IAsyncEnumerable GetItemsAsync(StorableType type = StorableType.All, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + switch (type) + { + case StorableType.File: + { + var files = await storage.GetFilesAsync().AsTask(cancellationToken); + foreach (var item in files) + { + yield return new WindowsStorageFile(item); + } + + break; + } + + case StorableType.Folder: + { + var folders = await storage.GetFoldersAsync().AsTask(cancellationToken); + foreach (var item in folders) + { + yield return new WindowsStorageFolder(item); + } + + break; + } + + case StorableType.All: + { + var items = await storage.GetItemsAsync().AsTask(cancellationToken); + foreach (var item in items) + { + if (item is StorageFile storageFile) + yield return new WindowsStorageFile(storageFile); + + if (item is StorageFolder storageFolder) + yield return new WindowsStorageFolder(storageFolder); + } + + break; + } + + case StorableType.None: + default: + yield break; + } + } + + /// + public Task DeleteAsync(IStorableChild item, CancellationToken cancellationToken = default) + { + return item switch + { + WindowsStorable storageFile => storageFile.storage + .DeleteAsync(GetWindowsStorageDeleteOption(false)) + .AsTask(cancellationToken), + + WindowsStorable storageFolder => storageFolder.storage + .DeleteAsync(GetWindowsStorageDeleteOption(false)) + .AsTask(cancellationToken), + + _ => throw new NotImplementedException() + }; + } + + /// + public async Task CreateCopyOfAsync(IStorableChild itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default) + { + if (itemToCopy is WindowsStorable sourceFile) + { + var copiedFile = await sourceFile.storage.CopyAsync(storage, itemToCopy.Name, GetWindowsNameCollisionOption(overwrite)).AsTask(cancellationToken); + return new WindowsStorageFile(copiedFile); + } + + throw new ArgumentException($"Could not copy type {itemToCopy.GetType()}"); + } + + /// + public async Task MoveFromAsync(IStorableChild itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default) + { + if (itemToMove is WindowsStorable sourceFile) + { + await sourceFile.storage.MoveAsync(storage, itemToMove.Name, GetWindowsNameCollisionOption(overwrite)).AsTask(cancellationToken); + return new WindowsStorageFile(sourceFile.storage); + } + + throw new ArgumentException($"Could not copy type {itemToMove.GetType()}"); + } + + /// + public async Task CreateFileAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default) + { + var file = await storage.CreateFileAsync(desiredName, GetWindowsCreationCollisionOption(overwrite)).AsTask(cancellationToken); + return new WindowsStorageFile(file); + } + + /// + public async Task CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default) + { + var folder = await storage.CreateFolderAsync(desiredName, GetWindowsCreationCollisionOption(overwrite)).AsTask(cancellationToken); + return new WindowsStorageFolder(folder); + } + + /// + public override async Task GetParentAsync(CancellationToken cancellationToken = default) + { + var parentFolder = await storage.GetParentAsync().AsTask(cancellationToken); + return new WindowsStorageFolder(parentFolder); + } + + /// + public Task GetFolderWatcherAsync(CancellationToken cancellationToken = default) + { + // TODO: Implement windows watcher + throw new NotImplementedException(); + } + + private static StorageDeleteOption GetWindowsStorageDeleteOption(bool permanently) + { + return permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default; + } + + private static NameCollisionOption GetWindowsNameCollisionOption(bool overwrite) + { + return overwrite ? NameCollisionOption.ReplaceExisting : NameCollisionOption.GenerateUniqueName; + } + + private static CreationCollisionOption GetWindowsCreationCollisionOption(bool overwrite) + { + return overwrite ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.OpenIfExists; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/BaseTemplateSelector.cs b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/BaseTemplateSelector.cs new file mode 100644 index 00000000..339f173b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/BaseTemplateSelector.cs @@ -0,0 +1,40 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace ClipboardCanvas.WinUI.TemplateSelectors +{ + /// + /// A generic template selector wrapper for . + /// + /// The type of item. + internal abstract class BaseTemplateSelector : DataTemplateSelector + { + /// + protected sealed override DataTemplate? SelectTemplateCore(object item) + { + if (item is not TItem typedItem) + return SelectTemplateCore(default); + + return SelectTemplateCore(typedItem); + } + + /// + protected sealed override DataTemplate? SelectTemplateCore(object item, DependencyObject container) + { + if (item is not TItem typedItem) + return SelectTemplateCore(default, container); + + return SelectTemplateCore(typedItem, container); + } + + protected virtual DataTemplate? SelectTemplateCore(TItem? item) + { + return base.SelectTemplateCore(item); + } + + protected virtual DataTemplate? SelectTemplateCore(TItem? item, DependencyObject container) + { + return base.SelectTemplateCore(item, container); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/CanvasTemplateSelector.cs b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/CanvasTemplateSelector.cs new file mode 100644 index 00000000..626a2b5c --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/CanvasTemplateSelector.cs @@ -0,0 +1,35 @@ +using ClipboardCanvas.Sdk.ViewModels.Controls.Canvases; +using Microsoft.UI.Xaml; + +namespace ClipboardCanvas.WinUI.TemplateSelectors +{ + internal sealed class CanvasTemplateSelector : BaseTemplateSelector + { + public DataTemplate? TextCanvasTemplate { get; set; } + + public DataTemplate? ImageCanvasTemplate { get; set; } + + public DataTemplate? PdfCanvasTemplate { get; set; } + + public DataTemplate? VideoCanvasTemplate { get; set; } + + public DataTemplate? CodeCanvasTemplate { get; set; } + + public DataTemplate? FolderCanvasTemplate { get; set; } + + /// + protected override DataTemplate? SelectTemplateCore(BaseCanvasViewModel? item, DependencyObject container) + { + return item switch + { + TextCanvasViewModel => TextCanvasTemplate, + ImageCanvasViewModel => ImageCanvasTemplate, + PdfCanvasViewModel => PdfCanvasTemplate, + VideoCanvasViewModel => VideoCanvasTemplate, + CodeCanvasViewModel => CodeCanvasTemplate, + FolderCanvasViewModel => FolderCanvasTemplate, + _ => base.SelectTemplateCore(item, container) + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/ExplorerTemplateSelector.cs b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/ExplorerTemplateSelector.cs new file mode 100644 index 00000000..3f112381 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/ExplorerTemplateSelector.cs @@ -0,0 +1,27 @@ +using ClipboardCanvas.Sdk.ViewModels.Views.Browser; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace ClipboardCanvas.WinUI.TemplateSelectors +{ + internal sealed class ExplorerTemplateSelector : BaseTemplateSelector + { + public DataTemplate? FileTemplate { get; set; } + + public DataTemplate? FolderTemplate { get; set; } + + /// + protected override DataTemplate? SelectTemplateCore(BrowserItemViewModel? item, DependencyObject container) + { + if (container is TreeViewItem tvi) + tvi.IsExpanded = true; + + return item switch + { + FileViewModel => FileTemplate, + FolderViewModel => FolderTemplate, + _ => base.SelectTemplateCore(item, container) + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/ImageTemplateSelector.cs b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/ImageTemplateSelector.cs new file mode 100644 index 00000000..05015ab7 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/ImageTemplateSelector.cs @@ -0,0 +1,26 @@ +using ClipboardCanvas.Shared.ComponentModel; +using ClipboardCanvas.WinUI.Imaging; +using Microsoft.UI.Xaml; + +namespace ClipboardCanvas.WinUI.TemplateSelectors +{ + internal sealed class ImageTemplateSelector : BaseTemplateSelector + { + public DataTemplate? IconImageDataTemplate { get; set; } + + public DataTemplate? ImageBitmapDataTemplate { get; set; } + + public DataTemplate? PdfPageImageDataTemplate { get; set; } + + protected override DataTemplate? SelectTemplateCore(IImage? item, DependencyObject container) + { + return item switch + { + IconImage => IconImageDataTemplate, + ImageBitmap => ImageBitmapDataTemplate, + PdfPageImage => PdfPageImageDataTemplate, + _ => base.SelectTemplateCore(item, container) + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/WidgetsTemplateSelector.cs b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/WidgetsTemplateSelector.cs new file mode 100644 index 00000000..a56f3383 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/TemplateSelectors/WidgetsTemplateSelector.cs @@ -0,0 +1,19 @@ +using ClipboardCanvas.Sdk.ViewModels.Widgets; +using Microsoft.UI.Xaml; + +namespace ClipboardCanvas.WinUI.TemplateSelectors +{ + internal sealed class WidgetsTemplateSelector : BaseTemplateSelector + { + public DataTemplate? CollectionsWidgetDataTemplate { get; set; } + + protected override DataTemplate? SelectTemplateCore(BaseWidgetViewModel? item, DependencyObject container) + { + return item switch + { + CollectionsWidgetViewModel => CollectionsWidgetDataTemplate, + _ => base.SelectTemplateCore(item, container) + }; + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/AnimatedCornerRadiusControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/AnimatedCornerRadiusControl.xaml new file mode 100644 index 00000000..84d07f2d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/AnimatedCornerRadiusControl.xaml @@ -0,0 +1,14 @@ + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/AnimatedCornerRadiusControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/AnimatedCornerRadiusControl.xaml.cs new file mode 100644 index 00000000..9d1bfd7e --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/AnimatedCornerRadiusControl.xaml.cs @@ -0,0 +1,88 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + public sealed partial class AnimatedCornerRadiusControl : UserControl + { + public AnimatedCornerRadiusControl() + { + InitializeComponent(); + } + + public object? ControlContent + { + get => (object?)GetValue(ControlContentProperty); + set => SetValue(ControlContentProperty, value); + } + public static readonly DependencyProperty ControlContentProperty = + DependencyProperty.Register(nameof(ControlContent), typeof(object), typeof(AnimatedCornerRadiusControl), new PropertyMetadata(null)); + + public int TopLeftCorner + { + get => (int)GetValue(TopLeftCornerProperty); + set => SetValue(TopLeftCornerProperty, value); + } + public static readonly DependencyProperty TopLeftCornerProperty = + DependencyProperty.Register(nameof(TopLeftCorner), typeof(int), typeof(AnimatedCornerRadiusControl), + new PropertyMetadata(0, (s, e) => + { + ((AnimatedCornerRadiusControl)s).MainContent.CornerRadius = new CornerRadius( + double.Parse(e.NewValue.ToString()), + ((AnimatedCornerRadiusControl)s).CornerRadius.TopRight, + ((AnimatedCornerRadiusControl)s).CornerRadius.BottomRight, + ((AnimatedCornerRadiusControl)s).CornerRadius.BottomLeft); + })); + + public int TopRightCorner + { + get => (int)GetValue(TopRightCornerProperty); + set => SetValue(TopRightCornerProperty, value); + } + public static readonly DependencyProperty TopRightCornerProperty = + DependencyProperty.Register(nameof(TopRightCorner), typeof(int), typeof(AnimatedCornerRadiusControl), + new PropertyMetadata(0, (s, e) => + { + ((AnimatedCornerRadiusControl)s).MainContent.CornerRadius = new CornerRadius( + ((AnimatedCornerRadiusControl)s).CornerRadius.TopLeft, + double.Parse(e.NewValue.ToString()), + ((AnimatedCornerRadiusControl)s).CornerRadius.BottomRight, + ((AnimatedCornerRadiusControl)s).CornerRadius.BottomLeft); + })); + + public int BottomRightCorner + { + get => (int)GetValue(BottomRightCornerProperty); + set => SetValue(BottomRightCornerProperty, value); + } + public static readonly DependencyProperty BottomRightCornerProperty = + DependencyProperty.Register(nameof(BottomRightCorner), typeof(int), typeof(AnimatedCornerRadiusControl), + new PropertyMetadata(0, (s, e) => + { + ((AnimatedCornerRadiusControl)s).MainContent.CornerRadius = new CornerRadius( + ((AnimatedCornerRadiusControl)s).CornerRadius.TopLeft, + ((AnimatedCornerRadiusControl)s).CornerRadius.TopRight, + double.Parse(e.NewValue.ToString()), + ((AnimatedCornerRadiusControl)s).CornerRadius.BottomLeft); + })); + + public int BottomLeftCorner + { + get => (int)GetValue(BottomLeftCornerProperty); + set => SetValue(BottomLeftCornerProperty, value); + } + public static readonly DependencyProperty BottomLeftCornerProperty = + DependencyProperty.Register(nameof(BottomLeftCorner), typeof(int), typeof(AnimatedCornerRadiusControl), + new PropertyMetadata(0, (s, e) => + { + ((AnimatedCornerRadiusControl)s).MainContent.CornerRadius = new CornerRadius( + ((AnimatedCornerRadiusControl)s).CornerRadius.TopLeft, + ((AnimatedCornerRadiusControl)s).CornerRadius.TopRight, + ((AnimatedCornerRadiusControl)s).CornerRadius.BottomRight, + double.Parse(e.NewValue.ToString())); + })); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/CanvasDisplayControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/CanvasDisplayControl.xaml new file mode 100644 index 00000000..198de528 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/CanvasDisplayControl.xaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/CanvasDisplayControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/CanvasDisplayControl.xaml.cs new file mode 100644 index 00000000..e14cfe4e --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/CanvasDisplayControl.xaml.cs @@ -0,0 +1,48 @@ +using ClipboardCanvas.Sdk.ViewModels.Controls.Canvases; +using ClipboardCanvas.Shared.ComponentModel; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Windows.System; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + public sealed partial class CanvasDisplayControl : UserControl + { + public CanvasDisplayControl() + { + InitializeComponent(); + } + + private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) + { + var key = args.KeyboardAccelerator.Key; + var control = args.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); + + switch ((key, control)) + { + case (VirtualKey.S, true): + if (!CanvasViewModel?.IsEditing ?? true) + break; + + if (CanvasViewModel is IPersistable persistable) + { + args.Handled = true; + await persistable.SaveAsync(); + } + break; + } + } + + public BaseCanvasViewModel? CanvasViewModel + { + get => (BaseCanvasViewModel?)GetValue(CanvasViewModelProperty); + set => SetValue(CanvasViewModelProperty, value); + } + public static readonly DependencyProperty CanvasViewModelProperty = + DependencyProperty.Register(nameof(CanvasViewModel), typeof(BaseCanvasViewModel), typeof(CanvasDisplayControl), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/CodeCanvasControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/CodeCanvasControl.xaml new file mode 100644 index 00000000..97e5c317 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/CodeCanvasControl.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/CodeCanvasControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/CodeCanvasControl.xaml.cs new file mode 100644 index 00000000..3d89a52d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/CodeCanvasControl.xaml.cs @@ -0,0 +1,119 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using WinUIEditor; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Canvases +{ + public sealed partial class CodeCanvasControl : UserControl + { + public CodeCanvasControl() + { + InitializeComponent(); + } + + private void CodeEditor_Tapped(object sender, TappedRoutedEventArgs e) + { + e.Handled = true; + } + + private void CodeEditor_Loaded(object sender, RoutedEventArgs e) + { + // TODO: Memory leak + this event only accounts for when a character is added + CodeEditor.Editor.CharAdded += Editor_CharAdded; + CodeEditor.Editor.ReadOnly = !IsEditing; + } + + private void Editor_CharAdded(Editor sender, CharAddedEventArgs args) + { + CodeEditor.Editor.CharAdded -= Editor_CharAdded; + WasAltered = true; + } + + public bool IsEditing + { + get => (bool)GetValue(IsEditingProperty); + set => SetValue(IsEditingProperty, value); + } + public static readonly DependencyProperty IsEditingProperty = + DependencyProperty.Register(nameof(IsEditing), typeof(bool), typeof(CodeCanvasControl), new PropertyMetadata(false, (s, e) => + { + if (s is not CodeCanvasControl control) + return; + + control.CodeEditor.Editor.ReadOnly = !(bool)e.NewValue; + if ((bool)e.NewValue) + control.CodeEditor.Focus(FocusState.Programmatic); + })); + + public bool WasAltered + { + get => (bool)GetValue(WasAlteredProperty); + set => SetValue(WasAlteredProperty, value); + } + public static readonly DependencyProperty WasAlteredProperty = + DependencyProperty.Register(nameof(WasAltered), typeof(bool), typeof(CodeCanvasControl), new PropertyMetadata(false, (s, e) => + { + if (s is not CodeCanvasControl control) + return; + + if ((bool)e.OldValue && !(bool)e.NewValue && control.IsEditing) + control.Text = control.CodeEditor.Editor.GetText(control.CodeEditor.Editor.TextLength); + })); + + public string? Text + { + get => CodeEditor.Editor.GetText(CodeEditor.Editor.Length); + set => SetValue(TextProperty, value); + } + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register(nameof(Text), typeof(string), typeof(CodeCanvasControl), new PropertyMetadata(null, + (s, e) => + { + if (s is not CodeCanvasControl control) + return; + + var newText = (string?)e.NewValue ?? string.Empty; + control.CodeEditor.Editor.SetText(newText); + + // Clear entire undo history if the text has been reset + if (e.OldValue is null) + control.CodeEditor.Editor.EmptyUndoBuffer(); + })); + + public string? LanguageHint + { + get => (string?)GetValue(LanguageHintProperty); + set => SetValue(LanguageHintProperty, value); + } + public static readonly DependencyProperty LanguageHintProperty = + DependencyProperty.Register(nameof(LanguageHint), typeof(string), typeof(CodeCanvasControl), new PropertyMetadata(null, + (s, e) => + { + if (s is not CodeCanvasControl control) + return; + + if (e.NewValue is not string extension) + return; + + var highlightingLanguage = extension switch + { + ".cpp" => "cpp", + ".cs" => "csharp", + ".js" or ".ts" or ".svelte" or ".jsx" => "javascript", + ".html" or ".htm" => "html", + ".json" => "json", + ".xml" or ".xaml" => "xml", + + _ => null + }; + + // TODO: Apply custom styles based on the extension + // For now, set to plaintext + control.CodeEditor.HighlightingLanguage = highlightingLanguage ?? "plaintext"; + })); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/FolderCanvasControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/FolderCanvasControl.xaml new file mode 100644 index 00000000..34f07a8c --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/FolderCanvasControl.xaml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/FolderCanvasControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/FolderCanvasControl.xaml.cs new file mode 100644 index 00000000..1b67645a --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/FolderCanvasControl.xaml.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using ClipboardCanvas.Sdk.Services; +using ClipboardCanvas.Sdk.ViewModels.Views.Browser; +using ClipboardCanvas.Shared.Extensions; +using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using OwlCore.Storage; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Canvases +{ + public sealed partial class FolderCanvasControl : UserControl + { + public FolderCanvasControl() + { + InitializeComponent(); + } + + private IApplicationService ApplicationService { get; } = Ioc.Default.GetRequiredService(); + + private async void TreeItem_Tapped(object sender, TappedRoutedEventArgs e) + { + e.Handled = true; + if (sender is not TreeViewItem { DataContext: BrowserItemViewModel itemViewModel } treeItem) + return; + + if (itemViewModel is FolderViewModel folderViewModel) + { + if (folderViewModel.Items.IsEmpty()) + await folderViewModel.InitAsync(); + + //treeItem.IsExpanded = !treeItem.IsExpanded; + } + else if (itemViewModel is FileViewModel { Inner: IFile file }) + await ApplicationService.LaunchHandlerAsync(file, default); + + } + + public IList? ItemsSource + { + get => (IList?)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + public static readonly DependencyProperty ItemsSourceProperty = + DependencyProperty.Register(nameof(ItemsSource), typeof(IList), typeof(FolderCanvasControl), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/ImageCanvasControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/ImageCanvasControl.xaml new file mode 100644 index 00000000..106c6bd1 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/ImageCanvasControl.xaml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/ImageCanvasControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/ImageCanvasControl.xaml.cs new file mode 100644 index 00000000..a8833059 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/ImageCanvasControl.xaml.cs @@ -0,0 +1,112 @@ +using ClipboardCanvas.Shared.ComponentModel; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Windows.Foundation; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Canvases +{ + public sealed partial class ImageCanvasControl : UserControl + { + private Point _lastPoint; + private bool _isDragging; + + public ImageCanvasControl() + { + InitializeComponent(); + IsEditing = false; + } + + private void Scroller_PointerPressed(object sender, PointerRoutedEventArgs e) + { + Scroller.CapturePointer(e.Pointer); + _isDragging = IsZoomingEnabled; + _lastPoint = e.GetCurrentPoint((UIElement)sender).Position; + } + + private void Image_PointerReleased(object sender, PointerRoutedEventArgs e) + { + _isDragging = false; + } + + private void Scroller_PointerCaptureLost(object sender, PointerRoutedEventArgs e) + { + _isDragging = false; + Scroller.ReleasePointerCapture(e.Pointer); + } + + private void Scroller_PointerMoved(object sender, PointerRoutedEventArgs e) + { + if (!IsZoomingEnabled) + return; + + if (!_isDragging) + return; + + var currentPoint = e.GetCurrentPoint((UIElement)sender).Position; + var dx = (currentPoint.X - _lastPoint.X) * 3.0f; + var dy = (currentPoint.Y - _lastPoint.Y) * 3.0f; + + Scroller.ChangeView( + Scroller.HorizontalOffset - dx, + Scroller.VerticalOffset - dy, + null); + + _lastPoint = currentPoint; + } + + private void Scroller_Loaded(object sender, RoutedEventArgs e) + { + ControlImage.Height = Scroller.ViewportHeight; + ControlImage.Width = Scroller.ViewportWidth; + } + + public IImage? Image + { + get => (IImage?)GetValue(ImageProperty); + set => SetValue(ImageProperty, value); + } + public static readonly DependencyProperty ImageProperty = + DependencyProperty.Register(nameof(Image), typeof(IImage), typeof(ImageCanvasControl), new PropertyMetadata(null, (s, e) => + { + if (s is not ImageCanvasControl control) + return; + + control.ControlImage.Height = control.Scroller.ViewportHeight; + control.ControlImage.Width = control.Scroller.ViewportWidth; + })); + + public bool IsEditing + { + get => (bool)GetValue(IsEditingProperty); + set => SetValue(IsEditingProperty, value); + } + public static readonly DependencyProperty IsEditingProperty = + DependencyProperty.Register(nameof(IsEditing), typeof(bool), typeof(ImageCanvasControl), new PropertyMetadata(false)); + + public bool WasAltered + { + get => (bool)GetValue(WasAlteredProperty); + set => SetValue(WasAlteredProperty, value); + } + public static readonly DependencyProperty WasAlteredProperty = + DependencyProperty.Register(nameof(WasAltered), typeof(bool), typeof(ImageCanvasControl), new PropertyMetadata(false)); + + public bool IsZoomingEnabled + { + get => (bool)GetValue(IsZoomingEnabledProperty); + set => SetValue(IsZoomingEnabledProperty, value); + } + public static readonly DependencyProperty IsZoomingEnabledProperty = + DependencyProperty.Register(nameof(IsZoomingEnabled), typeof(bool), typeof(ImageCanvasControl), new PropertyMetadata(false, (s, e) => + { + if (s is not ImageCanvasControl control) + return; + + control.Scroller.ZoomMode = (bool)e.NewValue ? ZoomMode.Enabled : ZoomMode.Disabled; + })); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/PdfCanvasControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/PdfCanvasControl.xaml new file mode 100644 index 00000000..6c701c3a --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/PdfCanvasControl.xaml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/PdfCanvasControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/PdfCanvasControl.xaml.cs new file mode 100644 index 00000000..b28c6e1b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/PdfCanvasControl.xaml.cs @@ -0,0 +1,26 @@ +using ClipboardCanvas.Sdk.ViewModels.Controls.Documents; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System.Collections.Generic; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Canvases +{ + public sealed partial class PdfCanvasControl : UserControl + { + public PdfCanvasControl() + { + InitializeComponent(); + } + + public IList? PagesSource + { + get => (IList?)GetValue(PagesSourceProperty); + set => SetValue(PagesSourceProperty, value); + } + public static readonly DependencyProperty PagesSourceProperty = + DependencyProperty.Register(nameof(PagesSource), typeof(IList), typeof(PdfCanvasControl), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/TextCanvasControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/TextCanvasControl.xaml new file mode 100644 index 00000000..8399cb3f --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/TextCanvasControl.xaml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/TextCanvasControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/TextCanvasControl.xaml.cs new file mode 100644 index 00000000..3501fe32 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/TextCanvasControl.xaml.cs @@ -0,0 +1,73 @@ +using Microsoft.UI.Text; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Canvases +{ + public sealed partial class TextCanvasControl : UserControl + { + private int _surpressTextChanged; + + public TextCanvasControl() + { + InitializeComponent(); + } + + private void EditingBox_Loaded(object sender, RoutedEventArgs e) + { + // When the RichEditBox is loaded, the TextChanged event will be fired twice + _surpressTextChanged = 2; + + EditingBox.Document.SetText(TextSetOptions.None, Text); + EditingBox.Focus(FocusState.Programmatic); + } + + private void EditingBox_TextChanged(object sender, RoutedEventArgs e) + { + if (_surpressTextChanged > 0) + { + _surpressTextChanged--; + return; + } + + WasAltered = true; + } + + public string? Text + { + get => (string?)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register(nameof(Text), typeof(string), typeof(TextCanvasControl), new PropertyMetadata(null)); + + public bool IsEditing + { + get => (bool)GetValue(IsEditingProperty); + set => SetValue(IsEditingProperty, value); + } + public static readonly DependencyProperty IsEditingProperty = + DependencyProperty.Register(nameof(IsEditing), typeof(bool), typeof(TextCanvasControl), new PropertyMetadata(false)); + + public bool WasAltered + { + get => (bool)GetValue(WasAlteredProperty); + set => SetValue(WasAlteredProperty, value); + } + public static readonly DependencyProperty WasAlteredProperty = + DependencyProperty.Register(nameof(WasAltered), typeof(bool), typeof(TextCanvasControl), new PropertyMetadata(false, (s, e) => + { + if (s is not TextCanvasControl control) + return; + + if ((bool)e.OldValue && !(bool)e.NewValue && control.IsEditing) + { + control.EditingBox.Document.GetText(TextGetOptions.None, out var text); + control.Text = text; + } + })); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/VideoCanvasControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/VideoCanvasControl.xaml new file mode 100644 index 00000000..7d103ab5 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/VideoCanvasControl.xaml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/VideoCanvasControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/VideoCanvasControl.xaml.cs new file mode 100644 index 00000000..5a9d28ca --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Canvases/VideoCanvasControl.xaml.cs @@ -0,0 +1,39 @@ +using ClipboardCanvas.Sdk.Models; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Canvases +{ + public sealed partial class VideoCanvasControl : UserControl + { + public VideoCanvasControl() + { + InitializeComponent(); + } + + private void TransportControls_Tapped(object sender, TappedRoutedEventArgs e) + { + e.Handled = true; + } + + public bool IsImmersed + { + get => (bool)GetValue(IsImmersedProperty); + set => SetValue(IsImmersedProperty, value); + } + public static readonly DependencyProperty IsImmersedProperty = + DependencyProperty.Register(nameof(IsImmersed), typeof(bool), typeof(VideoCanvasControl), new PropertyMetadata(false)); + + public IMediaSource? MediaSource + { + get => (IMediaSource?)GetValue(MediaSourceProperty); + set => SetValue(MediaSourceProperty, value); + } + public static readonly DependencyProperty MediaSourceProperty = + DependencyProperty.Register(nameof(MediaSource), typeof(IMediaSource), typeof(VideoCanvasControl), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/DynamicRibbon.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/DynamicRibbon.xaml new file mode 100644 index 00000000..febd8b76 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/DynamicRibbon.xaml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/DynamicRibbon.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/DynamicRibbon.xaml.cs new file mode 100644 index 00000000..ec6cd352 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/DynamicRibbon.xaml.cs @@ -0,0 +1,161 @@ +using ClipboardCanvas.Sdk.ViewModels.Controls.Menu; +using ClipboardCanvas.WinUI.Imaging; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Data; +using OwlCore.Storage; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Windows.Input; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + public sealed partial class DynamicRibbon : UserControl + { + public DynamicRibbon() + { + InitializeComponent(); + } + + private static async void ParseCommands(IList? items, IList destination) + { + destination.Clear(); + if (items is null) + return; + + foreach (var item in items) + { + switch (item) + { + case MenuToggleViewModel toggle: + { + var element = new AppBarToggleButton + { + Icon = new FontIcon() { Glyph = (toggle.Icon as IconImage)?.IconGlyph }, + Label = toggle.Name, + Command = toggle.Command, + CommandParameter = toggle + }; + + // Binding for IsChecked property (epic fail) + BindingOperations.SetBinding(element, AppBarToggleButton.IsCheckedProperty, new Binding() + { + Source = toggle, + Mode = BindingMode.TwoWay, + Path = new PropertyPath(nameof(MenuToggleViewModel.IsToggled)) + }); + + destination.Add(element); + break; + } + + case MenuActionViewModel action: + { + destination.Add(new AppBarButton() + { + Icon = new FontIcon() { Glyph = (action.Icon as IconImage)?.IconGlyph }, + Label = action.Name, + Command = action.Command, + CommandParameter = action + }); + break; + } + } + } + } + + private void PrimaryItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + ParseCommands(PrimaryActions, Commands.PrimaryCommands); + } + + private void SecondaryItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + ParseCommands(SecondaryActions, Commands.SecondaryCommands); + } + + private void MenuFlyout_Opening(object sender, object e) + { + if (sender is not MenuFlyout menuFlyout) + return; + + if (RenameCommand is null && CopyPathCommand is null && ShowInExplorerCommand is null) + menuFlyout.Hide(); + } + + public ICommand? RenameCommand + { + get => (ICommand?)GetValue(RenameCommandProperty); + set => SetValue(RenameCommandProperty, value); + } + public static readonly DependencyProperty RenameCommandProperty = + DependencyProperty.Register(nameof(RenameCommand), typeof(IStorableChild), typeof(DynamicRibbon), new PropertyMetadata(null)); + + public ICommand? CopyPathCommand + { + get => (ICommand?)GetValue(CopyPathCommandProperty); + set => SetValue(CopyPathCommandProperty, value); + } + public static readonly DependencyProperty CopyPathCommandProperty = + DependencyProperty.Register(nameof(CopyPathCommand), typeof(IStorableChild), typeof(DynamicRibbon), new PropertyMetadata(null)); + + public ICommand? ShowInExplorerCommand + { + get => (ICommand?)GetValue(ShowInExplorerCommandProperty); + set => SetValue(ShowInExplorerCommandProperty, value); + } + public static readonly DependencyProperty ShowInExplorerCommandProperty = + DependencyProperty.Register(nameof(ShowInExplorerCommand), typeof(IStorableChild), typeof(DynamicRibbon), new PropertyMetadata(null)); + + public string? ToolBarTitle + { + get => (string?)GetValue(ToolBarTitleProperty); + set => SetValue(ToolBarTitleProperty, value); + } + public static readonly DependencyProperty ToolBarTitleProperty = + DependencyProperty.Register(nameof(ToolBarTitle), typeof(string), typeof(DynamicRibbon), new PropertyMetadata(null)); + + public IList? PrimaryActions + { + get => (IList?)GetValue(PrimaryActionsProperty); + set => SetValue(PrimaryActionsProperty, value); + } + public static readonly DependencyProperty PrimaryActionsProperty = + DependencyProperty.Register(nameof(PrimaryActions), typeof(IList), typeof(DynamicRibbon), new PropertyMetadata(null, (s, e) => + { + if (s is not DynamicRibbon ribbon) + return; + + if (e.OldValue is INotifyCollectionChanged notifiableOld) + notifiableOld.CollectionChanged -= ribbon.PrimaryItems_CollectionChanged; + + if (e.NewValue is INotifyCollectionChanged notifiableNew) + notifiableNew.CollectionChanged += ribbon.PrimaryItems_CollectionChanged; + + ParseCommands((IList?)e.NewValue, ribbon.Commands.PrimaryCommands); + })); + + public IList? SecondaryActions + { + get => (IList?)GetValue(SecondaryActionsProperty); + set => SetValue(SecondaryActionsProperty, value); + } + public static readonly DependencyProperty SecondaryActionsProperty = + DependencyProperty.Register(nameof(SecondaryActions), typeof(IList), typeof(DynamicRibbon), new PropertyMetadata(null, (s, e) => + { + if (s is not DynamicRibbon ribbon) + return; + + if (e.OldValue is INotifyCollectionChanged notifiableOld) + notifiableOld.CollectionChanged -= ribbon.PrimaryItems_CollectionChanged; + + if (e.NewValue is INotifyCollectionChanged notifiableNew) + notifiableNew.CollectionChanged += ribbon.PrimaryItems_CollectionChanged; + + ParseCommands((IList?)e.NewValue, ribbon.Commands.SecondaryCommands); + })); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/FloatingCardControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/FloatingCardControl.xaml new file mode 100644 index 00000000..7568f993 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/FloatingCardControl.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/FloatingCardControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/FloatingCardControl.xaml.cs new file mode 100644 index 00000000..a53f5378 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/FloatingCardControl.xaml.cs @@ -0,0 +1,26 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Markup; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + [ContentProperty(Name = nameof(CardContent))] + public sealed partial class FloatingCardControl : UserControl + { + public FloatingCardControl() + { + InitializeComponent(); + } + + public object? CardContent + { + get => (object?)GetValue(CardContentProperty); + set => SetValue(CardContentProperty, value); + } + public static readonly DependencyProperty CardContentProperty = + DependencyProperty.Register(nameof(CardContent), typeof(object), typeof(FloatingCardControl), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Host/MainAppHost.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Host/MainAppHost.xaml new file mode 100644 index 00000000..7f0598ac --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Host/MainAppHost.xaml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Host/MainAppHost.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Host/MainAppHost.xaml.cs new file mode 100644 index 00000000..d3a19083 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Host/MainAppHost.xaml.cs @@ -0,0 +1,43 @@ +using ClipboardCanvas.Sdk.ViewModels.Views; +using ClipboardCanvas.UI.Helpers; +using ClipboardCanvas.UI.Utils; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Windows.System; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Host +{ + public sealed partial class MainAppHost : UserControl + { + public MainAppHost() + { + InitializeComponent(); + + OpenSettingsItem.KeyboardAccelerators.Add(new KeyboardAccelerator() + { + Key = (VirtualKey)188, + Modifiers = VirtualKeyModifiers.Control + }); + } + + private void Navigation_Loaded(object sender, RoutedEventArgs e) + { + if (sender is not INavigationControl navigationControl) + return; + + ViewModel.NavigationService.SetupNavigation(navigationControl); + } + + public MainAppViewModel ViewModel + { + get => (MainAppViewModel)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + public static readonly DependencyProperty ViewModelProperty = + DependencyProperty.Register(nameof(ViewModel), typeof(MainAppViewModel), typeof(MainAppHost), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/ImageControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/ImageControl.xaml new file mode 100644 index 00000000..f770a32b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/ImageControl.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/ImageControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/ImageControl.xaml.cs new file mode 100644 index 00000000..d4c06118 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/ImageControl.xaml.cs @@ -0,0 +1,41 @@ +using ClipboardCanvas.Shared.ComponentModel; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + public sealed partial class ImageControl : UserControl + { + public ImageControl() + { + InitializeComponent(); + } + + public IImage? Image + { + get => (IImage?)GetValue(ImageProperty); + set => SetValue(ImageProperty, value); + } + public static readonly DependencyProperty ImageProperty = + DependencyProperty.Register(nameof(Image), typeof(IImage), typeof(ImageControl), new PropertyMetadata(null)); + + public double HeightHint + { + get => (double)GetValue(HeightHintProperty); + set => SetValue(HeightHintProperty, value); + } + public static readonly DependencyProperty HeightHintProperty = + DependencyProperty.Register(nameof(HeightHint), typeof(double), typeof(ImageControl), new PropertyMetadata(16d)); + + public double WidthHint + { + get => (double)GetValue(WidthHintProperty); + set => SetValue(WidthHintProperty, value); + } + public static readonly DependencyProperty WidthHintProperty = + DependencyProperty.Register(nameof(WidthHint), typeof(double), typeof(ImageControl), new PropertyMetadata(16d)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/FrameNavigationControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/FrameNavigationControl.xaml new file mode 100644 index 00000000..27cfdadd --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/FrameNavigationControl.xaml @@ -0,0 +1,11 @@ + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/FrameNavigationControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/FrameNavigationControl.xaml.cs new file mode 100644 index 00000000..3a91a4f4 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/FrameNavigationControl.xaml.cs @@ -0,0 +1,71 @@ +using ClipboardCanvas.Shared.Extensions; +using ClipboardCanvas.UI.Utils; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media.Animation; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Navigation +{ + /// + /// The base class that manages UI navigation using . + /// + public abstract partial class FrameNavigationControl : UserControl, INavigationControl + { + /// + /// Gets a dictionary of types that bind view models and pages together. + /// + public abstract Dictionary TypeBinding { get; } + + public FrameNavigationControl() + { + InitializeComponent(); + } + + /// + public virtual Task NavigateAsync(TTarget? target, TTransition? transition = default) + where TTransition : class + { + if (target is null) + { + ContentFrame.Content = null; + return Task.FromResult(true); + } + + var pageType = TypeBinding.GetByKeyOrValue(target.GetType()); + if (pageType is null) + return Task.FromResult(false); + + var result = NavigateFrame(pageType, target, transition as NavigationTransitionInfo); + return Task.FromResult(result); + } + + /// + /// Resets the current content of the . + /// + public virtual void ClearContent() + { + ContentFrame.Content = null; + } + + /// + /// Navigates a frame to specified . + /// + /// The type of page to navigate to. + /// The parameter to pass to the page. + /// The transition to use when navigating. + /// If successful, returns true; otherwise false. + protected abstract bool NavigateFrame(Type pageType, object parameter, NavigationTransitionInfo? transitionInfo); + + /// + public virtual void Dispose() + { + ClearContent(); + (ContentFrame.Content as IDisposable)?.Dispose(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/MainNavigationControl.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/MainNavigationControl.cs new file mode 100644 index 00000000..b51938b8 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/MainNavigationControl.cs @@ -0,0 +1,25 @@ +using ClipboardCanvas.Sdk.ViewModels.Views; +using ClipboardCanvas.WinUI.Views; +using Microsoft.UI.Xaml.Media.Animation; +using System; +using System.Collections.Generic; + +namespace ClipboardCanvas.WinUI.UserControls.Navigation +{ + /// + internal sealed partial class MainNavigationControl : FrameNavigationControl + { + /// + public override Dictionary TypeBinding { get; } = new() + { + { typeof(HomeViewModel), typeof(HomeView) }, + { typeof(CanvasViewModel), typeof(CanvasView) } + }; + + /// + protected override bool NavigateFrame(Type pageType, object parameter, NavigationTransitionInfo? transitionInfo) + { + return ContentFrame.Navigate(pageType, parameter, transitionInfo); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/SettingsNavigationControl.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/SettingsNavigationControl.cs new file mode 100644 index 00000000..e553104d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Navigation/SettingsNavigationControl.cs @@ -0,0 +1,27 @@ +using ClipboardCanvas.Sdk.ViewModels.Views.Settings; +using ClipboardCanvas.WinUI.Views.Settings; +using Microsoft.UI.Xaml.Media.Animation; +using System; +using System.Collections.Generic; + +namespace ClipboardCanvas.WinUI.UserControls.Navigation +{ + /// + internal sealed partial class SettingsNavigationControl : FrameNavigationControl + { + /// + public override Dictionary TypeBinding { get; } = new() + { + { typeof(GeneralSettingsViewModel), typeof(GeneralSettingsPage) }, + //{ typeof(PreferencesSettingsViewModel), typeof(PreferencesSettingsPage) }, + { typeof(AboutSettingsViewModel), typeof(AboutSettingsPage) } + }; + + /// + protected override bool NavigateFrame(Type pageType, object parameter, NavigationTransitionInfo? transitionInfo) + { + transitionInfo ??= new EntranceNavigationTransitionInfo(); + return ContentFrame.Navigate(pageType, parameter, transitionInfo); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/NavigationSurfaceControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/NavigationSurfaceControl.xaml new file mode 100644 index 00000000..445d4f14 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/NavigationSurfaceControl.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/NavigationSurfaceControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/NavigationSurfaceControl.xaml.cs new file mode 100644 index 00000000..a7cb89be --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/NavigationSurfaceControl.xaml.cs @@ -0,0 +1,93 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using System.Windows.Input; +using Windows.System; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + public sealed partial class NavigationSurfaceControl : UserControl + { + public NavigationSurfaceControl() + { + InitializeComponent(); + } + + private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) + { + if (!EnableAccelerators) + return; + + args.Handled = true; + switch (args.KeyboardAccelerator.Key) + { + case VirtualKey.Left: + BackCommand?.Execute(null); + break; + + case VirtualKey.Right: + ForwardCommand?.Execute(null); + break; + + case VirtualKey.Home: + HomeCommand?.Execute(null); + break; + + default: + args.Handled = false; + break; + } + } + + public ICommand? BackCommand + { + get => (ICommand?)GetValue(BackCommandProperty); + set => SetValue(BackCommandProperty, value); + } + public static readonly DependencyProperty BackCommandProperty = + DependencyProperty.Register(nameof(BackCommand), typeof(ICommand), typeof(NavigationSurfaceControl), new PropertyMetadata(null)); + + public ICommand? ForwardCommand + { + get => (ICommand?)GetValue(ForwardCommandProperty); + set => SetValue(ForwardCommandProperty, value); + } + public static readonly DependencyProperty ForwardCommandProperty = + DependencyProperty.Register(nameof(ForwardCommand), typeof(ICommand), typeof(NavigationSurfaceControl), new PropertyMetadata(null)); + + public ICommand? HomeCommand + { + get => (ICommand?)GetValue(HomeCommandProperty); + set => SetValue(HomeCommandProperty, value); + } + public static readonly DependencyProperty HomeCommandProperty = + DependencyProperty.Register(nameof(HomeCommand), typeof(ICommand), typeof(NavigationSurfaceControl), new PropertyMetadata(null)); + + public bool IsForwardEnabled + { + get => (bool)GetValue(IsForwardEnabledProperty); + set => SetValue(IsForwardEnabledProperty, value); + } + public static readonly DependencyProperty IsForwardEnabledProperty = + DependencyProperty.Register(nameof(IsForwardEnabled), typeof(bool), typeof(NavigationSurfaceControl), new PropertyMetadata(true)); + + public bool IsBackEnabled + { + get => (bool)GetValue(IsBackEnabledProperty); + set => SetValue(IsBackEnabledProperty, value); + } + public static readonly DependencyProperty IsBackEnabledProperty = + DependencyProperty.Register(nameof(IsBackEnabled), typeof(bool), typeof(NavigationSurfaceControl), new PropertyMetadata(true)); + + public bool EnableAccelerators + { + get => (bool)GetValue(EnableAcceleratorsProperty); + set => SetValue(EnableAcceleratorsProperty, value); + } + public static readonly DependencyProperty EnableAcceleratorsProperty = + DependencyProperty.Register(nameof(EnableAccelerators), typeof(bool), typeof(NavigationSurfaceControl), new PropertyMetadata(true)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/TitleBarControl.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/TitleBarControl.xaml new file mode 100644 index 00000000..598536c4 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/TitleBarControl.xaml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/TitleBarControl.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/TitleBarControl.xaml.cs new file mode 100644 index 00000000..7da2c447 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/TitleBarControl.xaml.cs @@ -0,0 +1,24 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls +{ + public sealed partial class TitleBarControl : UserControl + { + public TitleBarControl() + { + InitializeComponent(); + } + + public string? Title + { + get => (string?)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register(nameof(Title), typeof(string), typeof(TitleBarControl), new PropertyMetadata(null)); + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Widgets/CollectionsWidget.xaml b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Widgets/CollectionsWidget.xaml new file mode 100644 index 00000000..589cfb2d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Widgets/CollectionsWidget.xaml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/UserControls/Widgets/CollectionsWidget.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Widgets/CollectionsWidget.xaml.cs new file mode 100644 index 00000000..f5acb9d4 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/UserControls/Widgets/CollectionsWidget.xaml.cs @@ -0,0 +1,92 @@ +using ClipboardCanvas.Sdk.ViewModels.Widgets; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Input; +using Windows.System; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.UserControls.Widgets +{ + public sealed partial class CollectionsWidget : UserControl + { + public CollectionsWidget() + { + InitializeComponent(); + } + + private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) + { + if (args.KeyboardAccelerator.Modifiers != VirtualKeyModifiers.Control) + return; + + var keyCode = (int)args.KeyboardAccelerator.Key; + if (keyCode < 49 || keyCode > 57) + return; + + var index = keyCode - 49; + if (ItemsSource?.ElementAtOrDefault(index) is CollectionViewModel collection) + await collection.OpenCollectionCommand.ExecuteAsync(null); + } + + private void CollectionItem_PointerEntered(object sender, PointerRoutedEventArgs e) + { + if (sender is not Border control) + return; + + control.Background = (Brush)Resources["ButtonBackgroundPointerOver"]; + control.BorderBrush = (Brush)Resources["ButtonBorderBrushPointerOver"]; + } + + private void CollectionItem_PointerExited(object sender, PointerRoutedEventArgs e) + { + if (sender is not Border control) + return; + + control.Background = (Brush)Resources["ButtonBackground"]; + control.BorderBrush = (Brush)Resources["ButtonBorderBrush"]; + } + + private void CollectionItem_PointerPressed(object sender, PointerRoutedEventArgs e) + { + if (sender is not Border control) + return; + + control.Background = (Brush)Resources["ButtonBackgroundPressed"]; + control.BorderBrush = (Brush)Resources["ButtonBorderBrushPressed"]; + } + + private async void CollectionItem_Tapped(object sender, TappedRoutedEventArgs e) + { + if (sender is not Border control) + return; + + control.Background = (Brush)Resources["ButtonBackgroundPointerOver"]; + control.BorderBrush = (Brush)Resources["ButtonBorderBrushPointerOver"]; + + if (control.DataContext is CollectionViewModel viewModel) + await viewModel.OpenCollectionCommand.ExecuteAsync(null); + } + + public IList? ItemsSource + { + get => (IList?)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + public static readonly DependencyProperty ItemsSourceProperty = + DependencyProperty.Register(nameof(ItemsSource), typeof(IList), typeof(CollectionsWidget), new PropertyMetadata(null)); + + public ICommand? AddCollectionCommand + { + get => (ICommand?)GetValue(AddCollectionCommandProperty); + set => SetValue(AddCollectionCommandProperty, value); + } + public static readonly DependencyProperty AddCollectionCommandProperty = + DependencyProperty.Register(nameof(AddCollectionCommand), typeof(ICommand), typeof(CollectionsWidget), new PropertyMetadata(null)); + } +} diff --git a/ClipboardCanvas/ValueConverters/BooleanInvertConverter.cs b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/BoolInvertConverter.cs similarity index 71% rename from ClipboardCanvas/ValueConverters/BooleanInvertConverter.cs rename to src/Platforms/ClipboardCanvas.WinUI/ValueConverters/BoolInvertConverter.cs index 60253616..90b91d65 100644 --- a/ClipboardCanvas/ValueConverters/BooleanInvertConverter.cs +++ b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/BoolInvertConverter.cs @@ -1,25 +1,23 @@ -using System; -using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Data; +using System; -namespace ClipboardCanvas.ValueConverters +namespace ClipboardCanvas.WinUI.ValueConverters { - public class BooleanInvertConverter : IValueConverter + internal sealed class BoolInvertConverter : IValueConverter { + /// public object Convert(object value, Type targetType, object parameter, string language) { if (value is not bool boolVal) - { return false; - } if (parameter is string strParam && strParam.ToLower() == "invert") - { return boolVal; - } return !boolVal; } + /// public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); diff --git a/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/GenericEnumConverter.cs b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/GenericEnumConverter.cs new file mode 100644 index 00000000..e5b5feaf --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/GenericEnumConverter.cs @@ -0,0 +1,22 @@ +using ClipboardCanvas.UI.ValueConverters; +using Microsoft.UI.Xaml.Data; +using System; + +namespace ClipboardCanvas.WinUI.ValueConverters +{ + /// + internal sealed class GenericEnumConverter : BaseGenericEnumConverter, IValueConverter + { + /// + public object? Convert(object value, Type targetType, object parameter, string language) + { + return TryConvert(value, targetType, parameter); + } + + /// + public object? ConvertBack(object value, Type targetType, object parameter, string language) + { + return TryConvertBack(value, targetType, parameter); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/MediaSourceConverter.cs b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/MediaSourceConverter.cs new file mode 100644 index 00000000..746403af --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/MediaSourceConverter.cs @@ -0,0 +1,25 @@ +using ClipboardCanvas.WinUI.AppModels; +using Microsoft.UI.Xaml.Data; +using System; + +namespace ClipboardCanvas.WinUI.ValueConverters +{ + internal sealed class MediaSourceConverter : IValueConverter + { + /// + public object? Convert(object value, Type targetType, object parameter, string language) + { + return value switch + { + VideoSource source => source.MediaSource, + _ => null + }; + } + + /// + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/NullToBoolConverter.cs b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/NullToBoolConverter.cs new file mode 100644 index 00000000..fda45fe7 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/ValueConverters/NullToBoolConverter.cs @@ -0,0 +1,22 @@ +using ClipboardCanvas.UI.ValueConverters; +using Microsoft.UI.Xaml.Data; +using System; + +namespace ClipboardCanvas.WinUI.ValueConverters +{ + /// + internal sealed class NullToBoolConverter : BaseNullToBoolConverter, IValueConverter + { + /// + public object? Convert(object value, Type targetType, object parameter, string language) + { + return TryConvert(value, targetType, parameter); + } + + /// + public object? ConvertBack(object value, Type targetType, object parameter, string language) + { + return TryConvert(value, targetType, parameter); + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Views/CanvasView.xaml b/src/Platforms/ClipboardCanvas.WinUI/Views/CanvasView.xaml new file mode 100644 index 00000000..12fae106 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/CanvasView.xaml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Views/CanvasView.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/Views/CanvasView.xaml.cs new file mode 100644 index 00000000..5945f57d --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/CanvasView.xaml.cs @@ -0,0 +1,66 @@ +using ClipboardCanvas.Sdk.ViewModels.Views; +using ClipboardCanvas.Shared.Extensions; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Navigation; +using Windows.System; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class CanvasView : Page + { + private bool _isImmersed; + + public CanvasViewModel? ViewModel + { + get => DataContext.TryCast(); + set => DataContext = value; + } + + public CanvasView() + { + InitializeComponent(); + } + + /// + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (e.Parameter is CanvasViewModel viewModel) + ViewModel = viewModel; + + base.OnNavigatedTo(e); + } + + private void Root_Tapped(object sender, TappedRoutedEventArgs e) + { + if (ViewModel?.CurrentCanvasViewModel is null) + return; + + _isImmersed = !_isImmersed; + ViewModel?.ChangeImmersion(_isImmersed); + } + + private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) + { + var key = args.KeyboardAccelerator.Key; + var control = args.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control); + + switch ((key, control)) + { + case (VirtualKey.V, true): + if (ViewModel is null) + break; + + args.Handled = true; + await ViewModel.PasteFromClipboardCommand.ExecuteAsync(null); + break; + } + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/Views/HomeView.xaml b/src/Platforms/ClipboardCanvas.WinUI/Views/HomeView.xaml new file mode 100644 index 00000000..8014421b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/HomeView.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Views/HomeView.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/Views/HomeView.xaml.cs new file mode 100644 index 00000000..580a1d5b --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/HomeView.xaml.cs @@ -0,0 +1,36 @@ +using ClipboardCanvas.Sdk.ViewModels.Views; +using ClipboardCanvas.Shared.Extensions; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.Views +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class HomeView : Page + { + public HomeViewModel? ViewModel + { + get => DataContext.TryCast(); + set => DataContext = value; + } + + public HomeView() + { + InitializeComponent(); + } + + /// + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (e.Parameter is HomeViewModel viewModel) + ViewModel = viewModel; + + base.OnNavigatedTo(e); + } + } +} diff --git a/ClipboardCanvas/MainWindow.xaml b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/AboutSettingsPage.xaml similarity index 59% rename from ClipboardCanvas/MainWindow.xaml rename to src/Platforms/ClipboardCanvas.WinUI/Views/Settings/AboutSettingsPage.xaml index 0d0ed6a1..8a142ce8 100644 --- a/ClipboardCanvas/MainWindow.xaml +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/AboutSettingsPage.xaml @@ -1,13 +1,12 @@ - - - - + + + + diff --git a/ClipboardCanvas.Package/ClipboardCanvas.Package/MainWindow.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/AboutSettingsPage.xaml.cs similarity index 64% rename from ClipboardCanvas.Package/ClipboardCanvas.Package/MainWindow.xaml.cs rename to src/Platforms/ClipboardCanvas.WinUI/Views/Settings/AboutSettingsPage.xaml.cs index f8ac2a72..48c2ffe5 100644 --- a/ClipboardCanvas.Package/ClipboardCanvas.Package/MainWindow.xaml.cs +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/AboutSettingsPage.xaml.cs @@ -1,10 +1,3 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; using System; using System.Collections.Generic; using System.IO; @@ -12,25 +5,27 @@ using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Foundation.Collections; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. -namespace ClipboardCanvas.Package +namespace ClipboardCanvas.WinUI.Views.Settings { /// - /// An empty window that can be used on its own or navigated to within a Frame. + /// An empty page that can be used on its own or navigated to within a Frame. /// - public sealed partial class MainWindow : Window + public sealed partial class AboutSettingsPage : Page { - public MainWindow() + public AboutSettingsPage() { this.InitializeComponent(); } - - private void myButton_Click(object sender, RoutedEventArgs e) - { - myButton.Content = "Clicked"; - } } } diff --git a/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/GeneralSettingsPage.xaml b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/GeneralSettingsPage.xaml new file mode 100644 index 00000000..04359726 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/GeneralSettingsPage.xaml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/GeneralSettingsPage.xaml.cs b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/GeneralSettingsPage.xaml.cs new file mode 100644 index 00000000..84599d20 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/Views/Settings/GeneralSettingsPage.xaml.cs @@ -0,0 +1,67 @@ +using ClipboardCanvas.Sdk.ViewModels.Views.Settings; +using ClipboardCanvas.Shared.Extensions; +using ClipboardCanvas.UI.Enums; +using ClipboardCanvas.WinUI.Helpers; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media.Animation; +using Microsoft.UI.Xaml.Navigation; +using System.Threading.Tasks; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace ClipboardCanvas.WinUI.Views.Settings +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class GeneralSettingsPage : Page + { + private bool _isFirstTime = true; + + public GeneralSettingsViewModel? ViewModel + { + get => DataContext.TryCast(); + set => DataContext = value; + } + + public int SelectedThemeIndex => (int)WindowsThemeHelper.Instance.CurrentTheme; + + public GeneralSettingsPage() + { + InitializeComponent(); + } + + /// + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (e.Parameter is GeneralSettingsViewModel viewModel) + ViewModel = viewModel; + + base.OnNavigatedTo(e); + } + + private async void AppThemeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (_isFirstTime) + { + _isFirstTime = false; + return; + } + + await WindowsThemeHelper.Instance.SetThemeAsync((ThemeType)AppThemeComboBox.SelectedIndex); + } + + private void Root_Loaded(object sender, RoutedEventArgs e) + { + _ = AddTransitionsAsync(); + async Task AddTransitionsAsync() + { + // Await a short delay for page navigation transition to complete and set ReorderThemeTransition to animate items when layout changes. + await Task.Delay(400); + (sender as Panel)?.ChildrenTransitions?.Add(new AddDeleteThemeTransition()); + } + } + } +} diff --git a/src/Platforms/ClipboardCanvas.WinUI/app.manifest b/src/Platforms/ClipboardCanvas.WinUI/app.manifest new file mode 100644 index 00000000..32f13293 --- /dev/null +++ b/src/Platforms/ClipboardCanvas.WinUI/app.manifest @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + PerMonitorV2 + + + \ No newline at end of file