├── CloudKeyboard.Wpf
├── configs.fkv
├── App.config
├── App.xaml.cs
├── App.xaml
├── Walterlv.CloudKeyboard.Wpf.csproj
├── Program.cs
├── Utils
│ └── EmptyStringToVisibilityConverter.cs
├── MainWindow.xaml.cs
└── MainWindow.xaml
├── .DS_Store
├── CloudKeyboard.Package
├── icon.png
├── icon.afdesign
├── Images
│ ├── StoreLogo.backup.png
│ ├── LargeTile.scale-100.png
│ ├── LargeTile.scale-125.png
│ ├── LargeTile.scale-150.png
│ ├── LargeTile.scale-200.png
│ ├── LargeTile.scale-400.png
│ ├── SmallTile.scale-100.png
│ ├── SmallTile.scale-125.png
│ ├── SmallTile.scale-150.png
│ ├── SmallTile.scale-200.png
│ ├── SmallTile.scale-400.png
│ ├── StoreLogo.scale-100.png
│ ├── StoreLogo.scale-125.png
│ ├── StoreLogo.scale-150.png
│ ├── StoreLogo.scale-200.png
│ ├── StoreLogo.scale-400.png
│ ├── SplashScreen.scale-100.png
│ ├── SplashScreen.scale-125.png
│ ├── SplashScreen.scale-150.png
│ ├── SplashScreen.scale-200.png
│ ├── SplashScreen.scale-400.png
│ ├── LockScreenLogo.scale-200.png
│ ├── Square44x44Logo.scale-100.png
│ ├── Square44x44Logo.scale-125.png
│ ├── Square44x44Logo.scale-150.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.scale-400.png
│ ├── Wide310x150Logo.scale-100.png
│ ├── Wide310x150Logo.scale-125.png
│ ├── Wide310x150Logo.scale-150.png
│ ├── Wide310x150Logo.scale-200.png
│ ├── Wide310x150Logo.scale-400.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-125.png
│ ├── Square150x150Logo.scale-150.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.targetsize-24.png
│ ├── Square44x44Logo.targetsize-256.png
│ ├── Square44x44Logo.targetsize-32.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── Square44x44Logo.altform-unplated_targetsize-32.png
│ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ └── Square44x44Logo.targetsize-24_altform-unplated.png
├── Package.appxmanifest
└── Walterlv.CloudKeyboard.Package.wapproj
├── CloudKeyboard.iOS
├── Resources
│ ├── Default.png
│ ├── Default@2x.png
│ ├── Default-568h@2x.png
│ ├── Default-Portrait.png
│ ├── Default-Portrait@2x.png
│ └── LaunchScreen.storyboard
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Icon20.png
│ │ ├── Icon29.png
│ │ ├── Icon40.png
│ │ ├── Icon58.png
│ │ ├── Icon60.png
│ │ ├── Icon76.png
│ │ ├── Icon80.png
│ │ ├── Icon87.png
│ │ ├── Icon1024.png
│ │ ├── Icon120.png
│ │ ├── Icon152.png
│ │ ├── Icon167.png
│ │ ├── Icon180.png
│ │ └── Contents.json
├── Entitlements.plist
├── Main.cs
├── AppDelegate.cs
├── Info.plist
├── Properties
│ └── AssemblyInfo.cs
└── Walterlv.CloudKeyboard.iOS.csproj
├── CloudKeyboard.Windows
├── Assets
│ ├── StoreLogo.png
│ ├── SplashScreen.scale-200.png
│ ├── LockScreenLogo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Wide310x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ └── Square44x44Logo.targetsize-24_altform-unplated.png
├── App.xaml
├── MainPage.xaml
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── MainPage.xaml.cs
├── Package.appxmanifest
├── App.xaml.cs
└── Walterlv.CloudKeyboard.Windows.csproj
├── 75fc04d2-b524-43c2-b7c1-f21230eb7056.mobileprovision
├── 8b50129c-bc44-4eb4-a330-7884c3c8bb63.mobileprovision
├── CloudKeyboard.WebApi
├── .config
│ └── dotnet-tools.json
├── appsettings.Development.json
├── appsettings.json
├── Models
│ ├── TypingChange.cs
│ ├── Keyboard.cs
│ ├── KeyboardContext.cs
│ └── TypingText.cs
├── Walterlv.CloudKeyboard.WebApi.csproj
├── Program.cs
├── Properties
│ ├── launchSettings.json
│ └── PublishProfiles
│ │ └── FolderProfile.pubxml
├── Startup.cs
├── Utils_
│ └── TypingAsyncTracker.cs
└── Controllers
│ └── KeyboardController.cs
├── CloudKeyboard.iOS.Extension
├── Entitlements.plist
├── packages.config
├── KeyboardViewController.designer.cs
├── Info.plist
├── Walterlv.CloudKeyboard.iOS.Extension.csproj
└── KeyboardViewController.cs
├── CloudKeyboard.Xaml
├── App.xaml
├── MainPage.xaml.cs
├── MainPage.xaml
├── App.xaml.cs
└── Walterlv.CloudKeyboard.Xaml.csproj
├── CloudKeyboard.Core
├── Client
│ ├── TypingTextEventArgs.cs
│ ├── ExceptionEventArgs.cs
│ ├── DelayRunner.cs
│ ├── CloudKeyboardReceiver.cs
│ └── CloudKeyboardSender.cs
├── TypingResponse.cs
├── HostInfo.cs
├── Walterlv.CloudKeyboard.Core.csproj
├── FileConfigurationRepo.cs
├── TypingText.cs
└── CloudKeyboard.cs
├── CloudKeybaord.Cli
├── Walterlv.CloudKeybaord.Cli.csproj
├── ConsoleLineReader.cs
└── Program.cs
├── README.md
├── .gitattributes
├── .gitignore
└── Walterlv.CloudKeyboard.sln
/CloudKeyboard.Wpf/configs.fkv:
--------------------------------------------------------------------------------
1 | Token
2 | walterlv
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/.DS_Store
--------------------------------------------------------------------------------
/CloudKeyboard.Package/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/icon.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/icon.afdesign:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/icon.afdesign
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Resources/Default.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/StoreLogo.backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/StoreLogo.backup.png
--------------------------------------------------------------------------------
/75fc04d2-b524-43c2-b7c1-f21230eb7056.mobileprovision:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/75fc04d2-b524-43c2-b7c1-f21230eb7056.mobileprovision
--------------------------------------------------------------------------------
/8b50129c-bc44-4eb4-a330-7884c3c8bb63.mobileprovision:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/8b50129c-bc44-4eb4-a330-7884c3c8bb63.mobileprovision
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/LargeTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/LargeTile.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/LargeTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/LargeTile.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SmallTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SmallTile.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SmallTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SmallTile.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/StoreLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/StoreLogo.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/StoreLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/StoreLogo.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SplashScreen.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SplashScreen.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SplashScreen.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SplashScreen.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Wide310x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Wide310x150Logo.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Wide310x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Wide310x150Logo.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Wide310x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Wide310x150Logo.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square150x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square150x150Logo.scale-125.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square150x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square150x150Logo.scale-150.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-32.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/HEAD/CloudKeyboard.Windows/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-ef": {
6 | "version": "3.1.2",
7 | "commands": [
8 | "dotnet-ef"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS.Extension/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace Walterlv.CloudTyping
4 | {
5 | ///
6 | /// Interaction logic for App.xaml
7 | ///
8 | public partial class App : Application
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/CloudKeyboard.Xaml/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Models/TypingChange.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace Walterlv.CloudTyping.Models
4 | {
5 | public class TypingChange
6 | {
7 | [Key]
8 | public string Token { get; set; }
9 | public long PopVersion { get; set; }
10 | public long PushVersion { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/CloudKeyboard.iOS.Extension/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/Client/TypingTextEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Walterlv.CloudTyping.Client
4 | {
5 | public class TypingTextEventArgs : EventArgs
6 | {
7 | public TypingTextEventArgs(TypingText typing)
8 | {
9 | Typing = typing;
10 | }
11 |
12 | public TypingText Typing { get; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/Client/ExceptionEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Walterlv.CloudTyping.Client
4 | {
5 | public class ExceptionEventArgs : EventArgs
6 | {
7 | public ExceptionEventArgs(Exception exception)
8 | {
9 | Exception = exception;
10 | }
11 |
12 | public Exception Exception { get; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/TypingResponse.cs:
--------------------------------------------------------------------------------
1 | namespace Walterlv.CloudTyping
2 | {
3 | public readonly struct TypingResponse
4 | {
5 | public TypingResponse(bool success, string message)
6 | {
7 | Success = success;
8 | Message = message;
9 | }
10 |
11 | public bool Success { get; }
12 |
13 | public string Message { get; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/CloudKeyboard.Xaml/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xamarin.Forms;
7 |
8 | namespace Walterlv.CloudTyping
9 | {
10 | public partial class MainPage : ContentPage
11 | {
12 | public MainPage()
13 | {
14 | InitializeComponent();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/HostInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Walterlv.CloudTyping
2 | {
3 | public static class HostInfo
4 | {
5 | #if DEBUG
6 | // DEBUG 下使用本地调试地址。
7 | public const string BaseUrl = "https://cloud-keyboard.walterlv.com:4096/api/keyboard";
8 | #else
9 | // RELEASE 下使用正式环境地址。
10 | public const string BaseUrl = "https://cloud-keyboard.walterlv.com:4096/api/keyboard";
11 | #endif
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/Walterlv.CloudKeyboard.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | Walterlv.CloudTyping
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Models/Keyboard.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 | using TypingTextModel = Walterlv.CloudTyping.Models.TypingText;
4 |
5 | namespace Walterlv.CloudTyping.Models
6 | {
7 | public class Keyboard
8 | {
9 | [Key]
10 | public string Token { get; set; }
11 |
12 | public virtual IList Typings { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/CloudKeybaord.Cli/Walterlv.CloudKeybaord.Cli.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 | Walterlv.CloudTyping
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Walterlv CloudKeyboard
2 |
3 | 这是一款运行在 iOS 上的云输入法。我不是在炒概念,这可是真真正正的云输入法!因为所有输入的文字都不是在手机键盘上按的,而是从云端发来的。那么云端哪里来?嗯,从你的电脑上打字过来的。
4 |
5 | 所以,这是一款你可以在电脑上打字,在手机上输出文字的输入法。它就是为了解决你有时必须使用手机 App,但手机打字又慢的问题。
6 |
7 | ## Roadmap
8 |
9 | ### 云服务器
10 |
11 | * [x] 支持多人同时输入互不干扰
12 | * [ ] 不能直接访问其他人输入的信息
13 |
14 | ### 手机端键盘
15 |
16 | * [x] 基本的文字输入
17 | * [x] 可以确认文字
18 | * [ ] 一个还算过得去的 UI
19 |
20 | ### 电脑端键盘
21 |
22 | * [x] Windows 端
23 | * [ ] Mac 端
24 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace Walterlv.CloudTyping
4 | {
5 | public class Application
6 | {
7 | // This is the main entry point of the application.
8 | static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, "AppDelegate");
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS.Extension/KeyboardViewController.designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // This file has been generated automatically by MonoDevelop to store outlets and
3 | // actions made in the Xcode designer. If it is removed, they will be lost.
4 | // Manual changes to this file may not be handled correctly.
5 | //
6 |
7 | using Foundation;
8 |
9 | namespace Walterlv.CloudTyping
10 | {
11 | [Register("KeyboardViewController")]
12 | partial class KeyboardViewController
13 | {
14 | void ReleaseDesignerOutlets()
15 | {
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/CloudKeyboard.Xaml/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Walterlv.CloudKeyboard.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | Walterlv.CloudTyping
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Models/KeyboardContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 |
3 | namespace Walterlv.CloudTyping.Models
4 | {
5 | public class KeyboardContext : DbContext
6 | {
7 | public KeyboardContext(DbContextOptions options) : base(options)
8 | {
9 | }
10 |
11 | public DbSet Keyboards { get; set; }
12 | public DbSet Typings { get; set; }
13 | public DbSet Changes { get; set; }
14 |
15 | protected override void OnModelCreating(ModelBuilder modelBuilder)
16 | {
17 | modelBuilder.Entity()
18 | .HasMany(k => k.Typings);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/CloudKeyboard.Xaml/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using Xamarin.Forms.Xaml;
4 |
5 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)]
6 | namespace Walterlv.CloudTyping
7 | {
8 | public partial class App : Application
9 | {
10 | public App()
11 | {
12 | InitializeComponent();
13 |
14 | MainPage = new MainPage();
15 | }
16 |
17 | protected override void OnStart()
18 | {
19 | // Handle when your app starts
20 | }
21 |
22 | protected override void OnSleep()
23 | {
24 | // Handle when your app sleeps
25 | }
26 |
27 | protected override void OnResume()
28 | {
29 | // Handle when your app resumes
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace Walterlv.CloudTyping
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:55315",
8 | "sslPort": 0
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/keyboard",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "CloudKeyboard.WebApi": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/keyboard",
24 | "applicationUrl": "http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CloudKeyboard.Xaml/Walterlv.CloudKeyboard.Xaml.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | Walterlv.CloudTyping
6 |
7 |
8 |
9 | pdbonly
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | MSBuild:Compile
24 |
25 |
26 | MSBuild:Compile
27 |
28 |
29 |
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/Walterlv.CloudKeyboard.Wpf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net48
6 | Latest
7 | true
8 | win-x86
9 | Walterlv.CloudTyping.Program
10 | Walterlv.CloudTyping
11 | Walterlv.CloudKeyboard
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | all
21 | runtime; build; native; contentfiles; analyzers; buildtransitive
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Properties/PublishProfiles/FolderProfile.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | FileSystem
9 | FileSystem
10 | Release
11 | Any CPU
12 |
13 | True
14 | False
15 | netcoreapp3.1
16 | 3862980d-169c-4736-89cc-8744d15f3cfe
17 | false
18 | D:\Services\cloud-keyboard.walterlv.com
19 | True
20 |
21 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 |
4 | namespace Walterlv.CloudTyping
5 | {
6 | // The UIApplicationDelegate for the application. This class is responsible for launching the
7 | // User Interface of the application, as well as listening (and optionally responding) to
8 | // application events from iOS.
9 | [Register("AppDelegate")]
10 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
11 | {
12 | //
13 | // This method is invoked when the application has loaded and is ready to run. In this
14 | // method you should instantiate the window, load the UI into it and then make the window
15 | // visible.
16 | //
17 | // You have 17 seconds to return from this method, or iOS will terminate your application.
18 | //
19 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
20 | {
21 | global::Xamarin.Forms.Forms.Init();
22 | LoadApplication(new App());
23 |
24 | return base.FinishedLaunching(app, options);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Walterlv.CloudKeyboard.Windows")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Walterlv.CloudKeyboard.Windows")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.UI.Xaml;
3 | using Windows.UI.Xaml.Controls;
4 |
5 | namespace Walterlv.CloudTyping
6 | {
7 | public sealed partial class MainPage : Page
8 | {
9 | private CloudKeyboard _keyboard;
10 |
11 | public MainPage()
12 | {
13 | InitializeComponent();
14 | _keyboard = new CloudKeyboard(HostInfo.BaseUrl, "0");
15 | }
16 |
17 | private void TypingTextBox_TextChanged(object sender, TextChangedEventArgs e)
18 | {
19 | Send();
20 | }
21 |
22 | private void TypingTextBox_SelectionChanged(object sender, RoutedEventArgs e)
23 | {
24 | Send();
25 | }
26 |
27 | private async void Send()
28 | {
29 | try
30 | {
31 | //await _keyboard.PutTextAsync(TypingTextBox.Text,
32 | // TypingTextBox.SelectionStart, TypingTextBox.SelectionStart + TypingTextBox.SelectionLength);
33 |
34 | var typingText = await _keyboard.FetchTextAsync();
35 | }
36 | catch (Exception ex)
37 | {
38 | ErrorTipTextBlock.Visibility = Visibility;
39 | ErrorTipTextBlock.Text = ex.ToString();
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace Walterlv.CloudTyping
7 | {
8 | public class Program
9 | {
10 | [STAThread]
11 | static void Main(string[] args)
12 | {
13 | // 启动前一个进程实例。
14 | try
15 | {
16 | var current = Process.GetCurrentProcess();
17 | var process = Process.GetProcessesByName(current.ProcessName).FirstOrDefault(x => x.Id != current.Id);
18 | if (process != null)
19 | {
20 | var hwnd = process.MainWindowHandle;
21 | ShowWindow(hwnd, 9);
22 | SetForegroundWindow(hwnd);
23 | return;
24 | }
25 | }
26 | catch (Exception)
27 | {
28 | // 忽略任何异常
29 | }
30 |
31 | // 启动自己。
32 | var app = new App();
33 | app.InitializeComponent();
34 | app.Run();
35 | }
36 |
37 | [DllImport("user32.dll")]
38 | private static extern int ShowWindow(IntPtr hwnd, uint nCmdShow);
39 |
40 | [DllImport("USER32.DLL")]
41 | public static extern bool SetForegroundWindow(IntPtr hWnd);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/Utils/EmptyStringToVisibilityConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows;
4 | using System.Windows.Data;
5 | using System.Windows.Markup;
6 |
7 | namespace Walterlv.CloudTyping.Utils
8 | {
9 | public class EmptyStringToVisibilityConverter : MarkupExtension, IValueConverter
10 | {
11 | public EmptyStringToVisibilityConverter() => IsVisibleWhenEmpty = false;
12 |
13 | public EmptyStringToVisibilityConverter(bool isVisibleWhenEmpty) => IsVisibleWhenEmpty = isVisibleWhenEmpty;
14 |
15 | [ConstructorArgument("isVisibleWhenEmpty")]
16 | public bool IsVisibleWhenEmpty { get; set; }
17 |
18 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
19 | {
20 | var whenEmpty = IsVisibleWhenEmpty ? Visibility.Visible : Visibility.Collapsed;
21 | var whenNotEmpty = IsVisibleWhenEmpty ? Visibility.Collapsed : Visibility.Visible;
22 | return string.IsNullOrEmpty(value as string)
23 | ? whenEmpty
24 | : whenNotEmpty;
25 | }
26 |
27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => null;
28 |
29 | public override object ProvideValue(IServiceProvider serviceProvider) => this;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIDeviceFamily
6 |
7 | 1
8 | 2
9 |
10 | UISupportedInterfaceOrientations
11 |
12 | UIInterfaceOrientationPortrait
13 | UIInterfaceOrientationLandscapeLeft
14 | UIInterfaceOrientationLandscapeRight
15 |
16 | UISupportedInterfaceOrientations~ipad
17 |
18 | UIInterfaceOrientationPortrait
19 | UIInterfaceOrientationPortraitUpsideDown
20 | UIInterfaceOrientationLandscapeLeft
21 | UIInterfaceOrientationLandscapeRight
22 |
23 | MinimumOSVersion
24 | 10.2.1
25 | CFBundleDisplayName
26 | CloudKeyboard
27 | CFBundleIdentifier
28 | com.walterlv.CloudKeyboard
29 | CFBundleVersion
30 | 1.0
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | CFBundleName
34 | CloudKeyboard
35 | XSAppIconAssets
36 | Assets.xcassets/AppIcon.appiconset
37 | CFBundleShortVersionString
38 | 1.0
39 |
40 |
41 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Walterlv.CloudKeyboard.iOS.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Walterlv.CloudKeyboard.iOS.iOS")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Models/TypingText.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations.Schema;
3 |
4 | namespace Walterlv.CloudTyping.Models
5 | {
6 | public class TypingText
7 | {
8 | public TypingText()
9 | {
10 | Timestamp = DateTimeOffset.UtcNow.UtcTicks;
11 | }
12 |
13 | public TypingText(string keyboardToken, CloudTyping.TypingText typing) : this()
14 | {
15 | KeyboardToken = keyboardToken;
16 | Text = typing.Text;
17 | CaretStartIndex = typing.CaretStartIndex;
18 | CaretEndIndex = typing.CaretEndIndex;
19 | Enter = typing.Enter;
20 | }
21 |
22 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
23 | public int Id { get; set; }
24 |
25 | [ForeignKey(nameof(Keyboard.Token))]
26 | public string KeyboardToken { get; set; }
27 |
28 | public long Timestamp { get; set; }
29 |
30 | public string Text { get; set; }
31 | public int CaretStartIndex { get; set; }
32 | public int CaretEndIndex { get; set; }
33 | public bool Enter { get; set; }
34 |
35 | public CloudTyping.TypingText AsClient()
36 | {
37 | return new CloudTyping.TypingText(Text, CaretStartIndex, CaretEndIndex, Enter);
38 | }
39 |
40 | public void UpdateFrom(CloudTyping.TypingText value)
41 | {
42 | Text = value.Text;
43 | CaretStartIndex = value.CaretStartIndex;
44 | CaretEndIndex = value.CaretEndIndex;
45 | Enter = value.Enter;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/CloudKeyboard.Core/FileConfigurationRepo.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace Walterlv.CloudTyping
5 | {
6 | public class FileConfigurationRepo
7 | {
8 | public static Dictionary Deserialize(string fileName)
9 | {
10 | var keyValue = new Dictionary();
11 | if (!File.Exists(fileName))
12 | {
13 | return keyValue;
14 | }
15 |
16 | var lines = File.ReadAllLines(fileName);
17 |
18 | string currentKey = null;
19 | string currentValue = null;
20 | foreach (var line in lines)
21 | {
22 | if (line.StartsWith(">"))
23 | {
24 | if (currentKey != null)
25 | {
26 | keyValue[currentKey] = currentValue ?? "";
27 | }
28 |
29 | currentKey = null;
30 | currentValue = null;
31 | continue;
32 | }
33 |
34 | if (currentKey == null)
35 | {
36 | currentKey = line.Trim();
37 | }
38 | else
39 | {
40 | currentValue = currentValue == null
41 | ? line.Trim()
42 | : $@"{currentValue}
43 | {line.Trim()}";
44 | }
45 | }
46 |
47 | if (currentKey != null)
48 | {
49 | keyValue[currentKey] = currentValue ?? "";
50 | }
51 |
52 | return keyValue;
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/CloudKeyboard.iOS.Extension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleName
6 | CloudKeyboard.Keyboard
7 | CFBundleIdentifier
8 | com.walterlv.CloudKeyboard.Keyboard
9 | CFBundleDevelopmentRegion
10 | en
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | XPC!
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleVersion
18 | 1.0
19 | MinimumOSVersion
20 | 10.2.1
21 | NSExtension
22 |
23 | NSExtensionAttributes
24 |
25 | IsASCIICapable
26 |
27 | PrefersRightToLeft
28 |
29 | PrimaryLanguage
30 | en-US
31 | RequestsOpenAccess
32 |
33 |
34 | NSExtensionPointIdentifier
35 | com.apple.keyboard-service
36 | NSExtensionPrincipalClass
37 | KeyboardViewController
38 |
39 | CFBundleDisplayName
40 | Cloud
41 | NSAppTransportSecurity
42 |
43 | NSAllowsArbitraryLoads
44 |
45 | NSExceptionDomains
46 |
47 | walterlv.xyz
48 |
49 | NSExceptionAllowsInsecureHTTPLoads
50 |
51 | NSIncludesSubdomains
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.AspNetCore.Mvc;
8 | using Microsoft.EntityFrameworkCore;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Hosting;
12 | using Microsoft.Extensions.Logging;
13 | using Walterlv.CloudTyping.Models;
14 |
15 | namespace Walterlv.CloudTyping
16 | {
17 | public class Startup
18 | {
19 | public Startup(IConfiguration configuration)
20 | {
21 | Configuration = configuration;
22 | }
23 |
24 | public IConfiguration Configuration { get; }
25 |
26 | // This method gets called by the runtime. Use this method to add services to the container.
27 | public void ConfigureServices(IServiceCollection services)
28 | {
29 | services.AddControllers();
30 | services.AddDbContext(options =>
31 | options.UseInMemoryDatabase("keyboard"));
32 | }
33 |
34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
36 | {
37 | if (env.IsDevelopment())
38 | {
39 | app.UseDeveloperExceptionPage();
40 | }
41 |
42 | app.UseRouting();
43 |
44 | app.UseAuthorization();
45 |
46 | app.UseEndpoints(endpoints =>
47 | {
48 | endpoints.MapControllers();
49 | });
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Walterlv.CloudKeyboard.Windows
7 | lvyi
8 | Assets\StoreLogo.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Utils_/TypingAsyncTracker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Threading.Tasks;
4 |
5 | namespace Walterlv.CloudTyping
6 | {
7 | public class TypingAsyncTracker
8 | {
9 | private readonly string _token;
10 | private long _currentVersion;
11 | private TaskCompletionSource<(long, TypingText)> _source;
12 |
13 | private TypingAsyncTracker(string token)
14 | {
15 | _token = token;
16 | }
17 |
18 | public void PushChanges(long version, TypingText typing)
19 | {
20 | var source = _source;
21 | _source = null;
22 | source?.SetResult((version, typing));
23 | }
24 |
25 | public Task<(long, TypingText)> WaitForChangesAsync(long currentVersion, TimeSpan timeout)
26 | {
27 | if (currentVersion > _currentVersion)
28 | {
29 | // 在请求时已经发生了更新,那么直接推送新的修改。
30 | _currentVersion = currentVersion;
31 | return Task.FromResult<(long, TypingText)>((currentVersion, null));
32 | }
33 | else
34 | {
35 | _currentVersion = currentVersion;
36 | _source = _source ?? new TaskCompletionSource<(long, TypingText)>();
37 | return _source.Task;
38 | }
39 | }
40 |
41 | private static readonly ConcurrentDictionary Trackers
42 | = new ConcurrentDictionary();
43 |
44 | public static TypingAsyncTracker From(string token) => Trackers.GetOrAdd(token, CreateNewTracker);
45 |
46 | private static TypingAsyncTracker CreateNewTracker(string token) => new TypingAsyncTracker(token);
47 | }
48 | }
--------------------------------------------------------------------------------
/CloudKeyboard.Core/TypingText.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 |
4 | namespace Walterlv.CloudTyping
5 | {
6 | public sealed class TypingText
7 | {
8 | private string _text;
9 | private int _caretStartIndex;
10 | private int _caretEndIndex;
11 |
12 | public TypingText()
13 | {
14 | }
15 |
16 | [JsonConstructor]
17 | public TypingText(string text, int caretStartIndex = -1, int caretEndIndex = -1, bool enter = false)
18 | {
19 | _text = text ?? "";
20 | _caretStartIndex = caretStartIndex < 0 || caretStartIndex > _text.Length ? _text.Length : caretStartIndex;
21 | _caretEndIndex = caretEndIndex < 0 || caretEndIndex > _text.Length ? _text.Length : caretEndIndex;
22 | Enter = enter;
23 | }
24 |
25 | public string Text
26 | {
27 | get => _text;
28 | set
29 | {
30 | VerifyFreezing();
31 | _text = value;
32 | }
33 | }
34 |
35 | public int CaretStartIndex
36 | {
37 | get => _caretStartIndex;
38 | set
39 | {
40 | VerifyFreezing();
41 | _caretStartIndex = value;
42 | }
43 | }
44 |
45 | public int CaretEndIndex
46 | {
47 | get => _caretEndIndex;
48 | set
49 | {
50 | VerifyFreezing();
51 | _caretEndIndex = value;
52 | }
53 | }
54 |
55 | public bool Enter { get; set; }
56 |
57 | public void Freeze()
58 | {
59 | Enter = true;
60 | }
61 |
62 | private void VerifyFreezing()
63 | {
64 | if (Enter) throw new InvalidOperationException("在消息确认后,不可修改。");
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/CloudKeybaord.Cli/ConsoleLineReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace Walterlv.CloudTyping
5 | {
6 | public sealed class ConsoleLineReader
7 | {
8 | public event EventHandler TextChanged;
9 |
10 | public string ReadLine()
11 | {
12 | var builder = new StringBuilder();
13 | while (true)
14 | {
15 | var i = Console.ReadKey(true);
16 |
17 | if (i.Key == ConsoleKey.Enter)
18 | {
19 | var line = builder.ToString();
20 | OnTextChanged(line, i.Key);
21 | Console.WriteLine();
22 | return line;
23 | }
24 |
25 | if (i.Key == ConsoleKey.Backspace)
26 | {
27 | if (builder.Length > 0)
28 | {
29 | var lastChar = builder[builder.Length - 1];
30 | Console.Write(lastChar > 0xA0 ? "\b\b \b\b" : "\b \b");
31 | builder.Remove(builder.Length - 1, 1);
32 | }
33 | }
34 | else
35 | {
36 | builder.Append(i.KeyChar);
37 | Console.Write(i.KeyChar);
38 | }
39 |
40 | OnTextChanged(builder.ToString(), i.Key);
41 | }
42 | }
43 |
44 | private void OnTextChanged(string line, ConsoleKey key)
45 | {
46 | TextChanged?.Invoke(this, new ConsoleTextChangedEventArgs(line, key));
47 | }
48 | }
49 |
50 | public class ConsoleTextChangedEventArgs : EventArgs
51 | {
52 | public ConsoleTextChangedEventArgs(string line, ConsoleKey consoleKey)
53 | {
54 | Line = line;
55 | ConsoleKey = consoleKey;
56 | }
57 |
58 | public string Line { get; }
59 | public ConsoleKey ConsoleKey { get; }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/Client/DelayRunner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace Walterlv.CloudTyping.Client
5 | {
6 | public class DelayRunner
7 | {
8 | private readonly Func _asyncAction;
9 | private readonly TimeSpan _delay;
10 | private bool _isRequired;
11 | private bool _isRunning;
12 | private bool _isInterrupted;
13 | private TRunningState _runningState;
14 |
15 | public DelayRunner(TimeSpan delay, Func asyncAction)
16 | {
17 | _delay = delay;
18 | _asyncAction = asyncAction;
19 | }
20 |
21 | public async void Run(TRunningState runningState, bool immediately = false)
22 | {
23 | _runningState = runningState;
24 |
25 | // 如果这是一个里程碑事件,那么立即执行此任务。
26 | if (immediately)
27 | {
28 | // 并同时标记此前的任务全部丢弃。
29 | _isInterrupted = true;
30 | _isRequired = false;
31 | await _asyncAction(_runningState).ConfigureAwait(false);
32 | return;
33 | }
34 |
35 | // 如果正在执行任务,那么只是标记需要执行任务。
36 | if (_isRunning)
37 | {
38 | _isRequired = true;
39 | return;
40 | }
41 |
42 | while (_isRequired || !_isRunning)
43 | {
44 | _isRequired = false;
45 | _isRunning = true;
46 | await Task.Delay(_delay).ConfigureAwait(false);
47 |
48 | // 如果任务被全部放弃,而且放弃之后中途也没有插入新的任务,那么就直接结束。
49 | if (_isInterrupted && !_isRequired)
50 | {
51 | _isInterrupted = false;
52 | break;
53 | }
54 |
55 | // 如果有新的插入任务,那么就重新等待。
56 | if (_isRequired)
57 | {
58 | continue;
59 | }
60 |
61 | // 如果任务保留,而且也没有新插入的任务,那么就执行这个任务。
62 | await _asyncAction(_runningState).ConfigureAwait(false);
63 | }
64 |
65 | _isRunning = false;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 | 云键盘
16 | walterlv
17 | Images\StoreLogo.png
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/Client/CloudKeyboardReceiver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace Walterlv.CloudTyping.Client
5 | {
6 | public class CloudKeyboardReceiver
7 | {
8 | public CloudKeyboardReceiver(string baseUrl, string token)
9 | {
10 | _baseUrl = baseUrl;
11 | Token = token;
12 | }
13 |
14 | public event EventHandler Typing;
15 | public event EventHandler Confirmed;
16 | public event EventHandler ExceptionOccurred;
17 |
18 | public async void Start()
19 | {
20 | if (_isRunning)
21 | {
22 | return;
23 | }
24 |
25 | _isRunning = true;
26 |
27 | while (_isRunning)
28 | {
29 | try
30 | {
31 | var typing = await _keyboard.FetchTextAsync();
32 |
33 | if (typing.Enter)
34 | {
35 | _lastTyping = typing;
36 | Confirmed?.Invoke(this, new TypingTextEventArgs(typing));
37 | }
38 | else
39 | {
40 | var isEqual = _lastTyping != null && _lastTyping.Text == typing.Text
41 | && _lastTyping.CaretStartIndex == typing.CaretStartIndex
42 | && _lastTyping.CaretEndIndex == typing.CaretEndIndex;
43 | _lastTyping = typing;
44 | if (!isEqual)
45 | {
46 | Typing?.Invoke(this, new TypingTextEventArgs(typing));
47 | }
48 | }
49 | }
50 | catch (Exception ex)
51 | {
52 | ExceptionOccurred?.Invoke(this, new ExceptionEventArgs(ex));
53 | }
54 |
55 | await Task.Delay(20);
56 | }
57 | }
58 |
59 | public void Stop()
60 | {
61 | _isRunning = false;
62 | }
63 |
64 | public string Token
65 | {
66 | get => _keyboard.Token;
67 | set => _keyboard = new CloudKeyboard(_baseUrl, value);
68 | }
69 |
70 | private TypingText _lastTyping;
71 | private CloudKeyboard _keyboard;
72 | private bool _isRunning;
73 | private readonly string _baseUrl;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Resources/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/CloudKeyboard.Core/CloudKeyboard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Http;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using Newtonsoft.Json;
6 |
7 | namespace Walterlv.CloudTyping
8 | {
9 | public class CloudKeyboard
10 | {
11 | public CloudKeyboard(string baseUrl, string token)
12 | {
13 | Token = token ?? throw new ArgumentNullException(nameof(token));
14 | _url = $"{baseUrl}/{Token}";
15 | }
16 |
17 | public string Token { get; }
18 |
19 | public async Task PeekTextAsync()
20 | {
21 | // 发送请求。
22 | using var client = GetHttpClient();
23 | var responseMessage = await client.GetAsync(_url).ConfigureAwait(false);
24 | var response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
25 |
26 | // 返回响应。
27 | var result = JsonConvert.DeserializeObject(response);
28 | return result;
29 | }
30 |
31 | public async Task FetchTextAsync()
32 | {
33 | // 发送请求。
34 | using var client = GetHttpClient();
35 | var content = new StringContent("", Encoding.UTF8, "application/json");
36 | var responseMessage = await client.PostAsync(_url, content).ConfigureAwait(false);
37 | var response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
38 |
39 | // 返回响应。
40 | var result = JsonConvert.DeserializeObject(response);
41 | return result;
42 | }
43 |
44 | public async Task PutTextAsync(string text,
45 | int caretStartIndex = -1, int caretEndIndex = -1, bool enter = false)
46 | {
47 | // 准备数据。
48 | var typingText = JsonConvert.SerializeObject(new TypingText(text, caretStartIndex, caretEndIndex, enter));
49 |
50 | // 发送请求。
51 | using var client = GetHttpClient();
52 | var content = new StringContent(typingText, Encoding.UTF8, "application/json");
53 | var responseMessage = await client.PutAsync(_url, content).ConfigureAwait(false);
54 | var response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
55 |
56 | // 返回响应。
57 | var result = JsonConvert.DeserializeObject(response);
58 | return result;
59 | }
60 |
61 | private HttpClient GetHttpClient()
62 | {
63 | HttpClient client = new HttpClient()
64 | {
65 | Timeout = TimeSpan.FromSeconds(3),
66 | };
67 |
68 | return client;
69 | }
70 |
71 | private readonly string _url;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "scale": "2x",
5 | "size": "20x20",
6 | "idiom": "iphone",
7 | "filename": "Icon40.png"
8 | },
9 | {
10 | "scale": "3x",
11 | "size": "20x20",
12 | "idiom": "iphone",
13 | "filename": "Icon60.png"
14 | },
15 | {
16 | "scale": "2x",
17 | "size": "29x29",
18 | "idiom": "iphone",
19 | "filename": "Icon58.png"
20 | },
21 | {
22 | "scale": "3x",
23 | "size": "29x29",
24 | "idiom": "iphone",
25 | "filename": "Icon87.png"
26 | },
27 | {
28 | "scale": "2x",
29 | "size": "40x40",
30 | "idiom": "iphone",
31 | "filename": "Icon80.png"
32 | },
33 | {
34 | "scale": "3x",
35 | "size": "40x40",
36 | "idiom": "iphone",
37 | "filename": "Icon120.png"
38 | },
39 | {
40 | "scale": "2x",
41 | "size": "60x60",
42 | "idiom": "iphone",
43 | "filename": "Icon120.png"
44 | },
45 | {
46 | "scale": "3x",
47 | "size": "60x60",
48 | "idiom": "iphone",
49 | "filename": "Icon180.png"
50 | },
51 | {
52 | "scale": "1x",
53 | "size": "20x20",
54 | "idiom": "ipad",
55 | "filename": "Icon20.png"
56 | },
57 | {
58 | "scale": "2x",
59 | "size": "20x20",
60 | "idiom": "ipad",
61 | "filename": "Icon40.png"
62 | },
63 | {
64 | "scale": "1x",
65 | "size": "29x29",
66 | "idiom": "ipad",
67 | "filename": "Icon29.png"
68 | },
69 | {
70 | "scale": "2x",
71 | "size": "29x29",
72 | "idiom": "ipad",
73 | "filename": "Icon58.png"
74 | },
75 | {
76 | "scale": "1x",
77 | "size": "40x40",
78 | "idiom": "ipad",
79 | "filename": "Icon40.png"
80 | },
81 | {
82 | "scale": "2x",
83 | "size": "40x40",
84 | "idiom": "ipad",
85 | "filename": "Icon80.png"
86 | },
87 | {
88 | "scale": "1x",
89 | "size": "76x76",
90 | "idiom": "ipad",
91 | "filename": "Icon76.png"
92 | },
93 | {
94 | "scale": "2x",
95 | "size": "76x76",
96 | "idiom": "ipad",
97 | "filename": "Icon152.png"
98 | },
99 | {
100 | "scale": "2x",
101 | "size": "83.5x83.5",
102 | "idiom": "ipad",
103 | "filename": "Icon167.png"
104 | },
105 | {
106 | "scale": "1x",
107 | "size": "1024x1024",
108 | "idiom": "ios-marketing",
109 | "filename": "Icon1024.png"
110 | }
111 | ],
112 | "properties": {},
113 | "info": {
114 | "version": 1,
115 | "author": "xcode"
116 | }
117 | }
--------------------------------------------------------------------------------
/CloudKeyboard.Core/Client/CloudKeyboardSender.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace Walterlv.CloudTyping.Client
5 | {
6 | public class CloudKeyboardSender
7 | {
8 | public CloudKeyboardSender(string baseUrl, string token, Func typingGetter)
9 | {
10 | _typingGetter = typingGetter;
11 | _baseUrl = baseUrl;
12 | _runner = new DelayRunner(TimeSpan.FromSeconds(0.1), SendCore);
13 | Token = token;
14 | }
15 |
16 | public string Token
17 | {
18 | get => _keyboard.Token;
19 | set => _keyboard = new CloudKeyboard(_baseUrl, value);
20 | }
21 |
22 | public event EventHandler TargetUpdated;
23 | public event EventHandler ExceptionOccurred;
24 |
25 | public async void Reload()
26 | {
27 | TypingText text;
28 |
29 | try
30 | {
31 | text = await _keyboard.PeekTextAsync();
32 | }
33 | catch
34 | {
35 | text = new TypingText("");
36 | }
37 |
38 | if (!text.Enter)
39 | {
40 | TargetUpdated?.Invoke(this, new TypingTextEventArgs(text));
41 | }
42 | }
43 |
44 | public void Send(bool enter = false)
45 | {
46 | var typing = _typingGetter();
47 | typing.Text = typing.Text.Replace("\r\n", "\n");
48 |
49 | if (enter)
50 | {
51 | typing.Freeze();
52 | _runner.Run(typing, true);
53 | }
54 | else if (_lastTyping != null)
55 | {
56 | var isEqual = _lastTyping.Text == typing.Text
57 | && _lastTyping.CaretStartIndex == typing.CaretStartIndex
58 | && _lastTyping.CaretEndIndex == typing.CaretEndIndex;
59 | _lastTyping = typing;
60 | if (!isEqual)
61 | {
62 | _runner.Run(typing);
63 | }
64 | }
65 | else
66 | {
67 | _lastTyping = typing;
68 | }
69 | }
70 |
71 | private async Task SendCore(TypingText state)
72 | {
73 | try
74 | {
75 | await _keyboard.PutTextAsync(state.Text, state.CaretStartIndex, state.CaretEndIndex, state.Enter);
76 | }
77 | catch (Exception ex)
78 | {
79 | ExceptionOccurred?.Invoke(this, new ExceptionEventArgs(ex));
80 | }
81 | }
82 |
83 | private TypingText _lastTyping;
84 | private CloudKeyboard _keyboard;
85 | private readonly string _baseUrl;
86 | private readonly Func _typingGetter;
87 | private readonly DelayRunner _runner;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/CloudKeybaord.Cli/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Walterlv.CloudTyping.Client;
3 |
4 | namespace Walterlv.CloudTyping
5 | {
6 | class Program
7 | {
8 | static void Main(string[] args)
9 | {
10 | RunAsMobileEnd();
11 | }
12 |
13 | private static void RunAsPcEnd()
14 | {
15 | Console.Title = "Walterlv Cloud Keyboard - PC";
16 | var token = ReadSingleLineText("Input a token: ");
17 |
18 | var keyboard = new CloudKeyboard(HostInfo.BaseUrl, token);
19 | var reader = new ConsoleLineReader();
20 | reader.TextChanged += async (sender, args) =>
21 | {
22 | await keyboard.PutTextAsync(args.Line, args.Line.Length - 1, args.Line.Length);
23 | };
24 |
25 | while (true)
26 | {
27 | reader.ReadLine();
28 | }
29 |
30 | string ReadSingleLineText(string tip)
31 | {
32 | string result;
33 |
34 | do
35 | {
36 | Console.Write(tip);
37 | result = Console.ReadLine()?.Trim().ToLowerInvariant();
38 | } while (string.IsNullOrWhiteSpace(result));
39 |
40 | return result;
41 | }
42 | }
43 |
44 | private static void RunAsMobileEnd()
45 | {
46 | Console.Title = "Walterlv Cloud Keyboard - Mobile";
47 | var inScreenCount = 0;
48 |
49 | // 模拟构造函数。
50 | var receiver = new CloudKeyboardReceiver(HostInfo.BaseUrl, "0");
51 | receiver.Typing += OnReceived;
52 | receiver.Confirmed += OnConfirmed;
53 | receiver.Start();
54 |
55 | // 模拟消息循环。
56 | ConsoleKeyInfo key;
57 | do
58 | {
59 | key = Console.ReadKey(true);
60 | } while (key.Key != ConsoleKey.Escape);
61 |
62 | receiver.Stop();
63 |
64 | void OnReceived(object sender, TypingTextEventArgs e)
65 | {
66 | ClearCurrentDocument();
67 | SetDocument(e.Typing);
68 | }
69 |
70 | void OnConfirmed(object sender, TypingTextEventArgs e)
71 | {
72 | ClearCurrentDocument();
73 |
74 | inScreenCount++;
75 | Console.ForegroundColor = ConsoleColor.Gray;
76 | Console.Write("[上屏] ");
77 | Console.Write(e.Typing.Text);
78 | Console.ResetColor();
79 | Console.WriteLine();
80 | }
81 |
82 | void SetDocument(TypingText typing)
83 | {
84 | for (var i = 0; i < typing.Text.Length; i++)
85 | {
86 | var c = typing.Text[i];
87 | if (typing.CaretStartIndex <= i && typing.CaretEndIndex > i)
88 | {
89 | Console.ForegroundColor = ConsoleColor.Green;
90 | Console.Write(c);
91 | Console.ResetColor();
92 | }
93 | else
94 | {
95 | Console.Write(c);
96 | }
97 | }
98 | }
99 |
100 | void ClearCurrentDocument()
101 | {
102 | Console.CursorTop = inScreenCount;
103 | Console.CursorLeft = 0;
104 | for (var i = 0; i < 320; i++)
105 | {
106 | Console.Write(' ');
107 | }
108 |
109 | Console.CursorTop = inScreenCount;
110 | Console.CursorLeft = 0;
111 | }
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.ApplicationModel;
3 | using Windows.ApplicationModel.Activation;
4 | using Windows.UI.Xaml;
5 | using Windows.UI.Xaml.Controls;
6 | using Windows.UI.Xaml.Navigation;
7 |
8 | namespace Walterlv.CloudTyping
9 | {
10 | ///
11 | /// Provides application-specific behavior to supplement the default Application class.
12 | ///
13 | sealed partial class App : Application
14 | {
15 | ///
16 | /// Initializes the singleton application object. This is the first line of authored code
17 | /// executed, and as such is the logical equivalent of main() or WinMain().
18 | ///
19 | public App()
20 | {
21 | this.InitializeComponent();
22 | this.Suspending += OnSuspending;
23 | }
24 |
25 | ///
26 | /// Invoked when the application is launched normally by the end user. Other entry points
27 | /// will be used such as when the application is launched to open a specific file.
28 | ///
29 | /// Details about the launch request and process.
30 | protected override void OnLaunched(LaunchActivatedEventArgs e)
31 | {
32 | Frame rootFrame = Window.Current.Content as Frame;
33 |
34 | // Do not repeat app initialization when the Window already has content,
35 | // just ensure that the window is active
36 | if (rootFrame == null)
37 | {
38 | // Create a Frame to act as the navigation context and navigate to the first page
39 | rootFrame = new Frame();
40 |
41 | rootFrame.NavigationFailed += OnNavigationFailed;
42 |
43 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
44 | {
45 | //TODO: Load state from previously suspended application
46 | }
47 |
48 | // Place the frame in the current Window
49 | Window.Current.Content = rootFrame;
50 | }
51 |
52 | if (e.PrelaunchActivated == false)
53 | {
54 | if (rootFrame.Content == null)
55 | {
56 | // When the navigation stack isn't restored navigate to the first page,
57 | // configuring the new page by passing required information as a navigation
58 | // parameter
59 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
60 | }
61 | // Ensure the current window is active
62 | Window.Current.Activate();
63 | }
64 | }
65 |
66 | ///
67 | /// Invoked when Navigation to a certain page fails
68 | ///
69 | /// The Frame which failed navigation
70 | /// Details about the navigation failure
71 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
72 | {
73 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
74 | }
75 |
76 | ///
77 | /// Invoked when application execution is being suspended. Application state is saved
78 | /// without knowing whether the application will be terminated or resumed with the contents
79 | /// of memory still intact.
80 | ///
81 | /// The source of the suspend request.
82 | /// Details about the suspend request.
83 | private void OnSuspending(object sender, SuspendingEventArgs e)
84 | {
85 | var deferral = e.SuspendingOperation.GetDeferral();
86 | //TODO: Save application state and stop any background activity
87 | deferral.Complete();
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Input;
8 | using Walterlv.CloudTyping.Client;
9 |
10 | namespace Walterlv.CloudTyping
11 | {
12 | public partial class MainWindow : Window
13 | {
14 | private readonly CloudKeyboardSender _sender;
15 | private readonly string _configFile;
16 |
17 | public MainWindow()
18 | {
19 | InitializeComponent();
20 | Loaded += OnLoaded;
21 | _configFile = File.Exists("configs.fkv")
22 | ? "configs.fkv"
23 | : Path.Combine(
24 | Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
25 | "Walterlv.CloudKeyboard", "configs.fkv");
26 |
27 | var token = GetTokenFromConfigs();
28 | TokenTextBox.Text = token;
29 | _sender = new CloudKeyboardSender(HostInfo.BaseUrl, token, () => new TypingText(
30 | TypingTextBox.Text, TypingTextBox.SelectionStart,
31 | TypingTextBox.SelectionStart + TypingTextBox.SelectionLength));
32 | _sender.TargetUpdated += OnTargetUpdated;
33 | _sender.ExceptionOccurred += OnExceptionOccurred;
34 | }
35 |
36 | private void OnLoaded(object sender, RoutedEventArgs e)
37 | {
38 | TypingTextBox.Focus();
39 | }
40 |
41 | private void TypingTextBox_TextChanged(object sender, TextChangedEventArgs e)
42 | {
43 | _sender.Send();
44 | UpdateCharacterInputLeftInfo();
45 | }
46 |
47 | private void TypingTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
48 | {
49 | if (e.Key == Key.Enter && !e.IsRepeat)
50 | {
51 | e.Handled = true;
52 | if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
53 | {
54 | InsertNewLine();
55 | }
56 | else
57 | {
58 | _sender.Send(true);
59 | TypingTextBox.Text = "";
60 | }
61 | }
62 |
63 | void InsertNewLine()
64 | {
65 | var characterInputLeft = TypingTextBox.MaxLength - TypingTextBox.Text.Length;
66 | if (characterInputLeft < 2)
67 | {
68 | return;
69 | }
70 |
71 | var oldText = TypingTextBox.Text;
72 | var selectionStart = TypingTextBox.SelectionStart;
73 |
74 | var builder = new StringBuilder();
75 | builder.Append(oldText.Substring(0, selectionStart));
76 | builder.AppendLine();
77 | builder.Append(oldText.Substring(selectionStart + TypingTextBox.SelectionLength));
78 | TypingTextBox.Text = builder.ToString();
79 |
80 | TypingTextBox.SelectionStart = selectionStart + Environment.NewLine.Length;
81 | TypingTextBox.SelectionLength = 0;
82 | }
83 | }
84 |
85 | private void TypingTextBox_SelectionChanged(object sender, RoutedEventArgs e) => _sender.Send();
86 |
87 | private void EnterButton_Click(object sender, RoutedEventArgs e)
88 | {
89 | if (TypingTextBox.IsFocused)
90 | {
91 | _sender.Send(true);
92 | TypingTextBox.Text = "";
93 | }
94 | else if (TokenTextBox.IsFocused)
95 | {
96 | TypingTextBox.Focus();
97 | }
98 | }
99 |
100 | private void OnActivated(object sender, EventArgs e) => _sender.Reload();
101 |
102 | private void OnTargetUpdated(object sender, TypingTextEventArgs e)
103 | {
104 | var typing = e.Typing;
105 | TypingTextBox.Text = typing.Text;
106 | TypingTextBox.SelectionStart = typing.CaretStartIndex;
107 | TypingTextBox.SelectionLength = typing.CaretEndIndex - typing.CaretStartIndex;
108 | }
109 |
110 | private void OnExceptionOccurred(object sender, ExceptionEventArgs e)
111 | => TypingTextBox.Dispatcher.InvokeAsync(async () =>
112 | {
113 | ErrorTipTextBlock.Text = e.Exception.ToString();
114 | await Task.Delay(5000);
115 | ErrorTipTextBlock.Text = "";
116 | });
117 |
118 | private void TokenTextBox_LostFocus(object sender, RoutedEventArgs e)
119 | {
120 | var editedToken = TokenTextBox.Text;
121 | if (string.IsNullOrWhiteSpace(editedToken))
122 | {
123 | TokenTextBox.Text = _sender.Token;
124 | }
125 | else
126 | {
127 | _sender.Token = editedToken;
128 | SetTokenToConfigs(editedToken);
129 | }
130 | }
131 |
132 | private void UpdateCharacterInputLeftInfo()
133 | {
134 | var characterInputLeft = TypingTextBox.MaxLength - TypingTextBox.Text.Length;
135 | if (characterInputLeft <= 0)
136 | {
137 | WarningTextBlock.Text = "你输入的字已经够多了……";
138 | }
139 | else if (characterInputLeft <= 200)
140 | {
141 | WarningTextBlock.Text = $"你还可以再输入 {characterInputLeft.ToString()} 个字……";
142 | }
143 | else
144 | {
145 | WarningTextBlock.Text = "";
146 | }
147 | }
148 |
149 | private string GetTokenFromConfigs()
150 | {
151 | string token;
152 |
153 | try
154 | {
155 | token = FileConfigurationRepo.Deserialize(_configFile)["Token"];
156 | }
157 | catch
158 | {
159 | token = "0";
160 | }
161 |
162 | return token;
163 | }
164 |
165 | private void SetTokenToConfigs(string token)
166 | {
167 | if (!File.Exists(_configFile))
168 | {
169 | var name = Path.GetDirectoryName(_configFile);
170 | if (name != null)
171 | {
172 | Directory.CreateDirectory(name);
173 | }
174 | }
175 |
176 | File.WriteAllText(_configFile, $@"Token
177 | {token}");
178 | }
179 | }
180 | }
--------------------------------------------------------------------------------
/CloudKeyboard.WebApi/Controllers/KeyboardController.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.Extensions.Logging;
5 | using Walterlv.CloudTyping.Models;
6 |
7 | namespace Walterlv.CloudTyping.Controllers
8 | {
9 | [Route("api/[controller]")]
10 | [ApiController]
11 | public class KeyboardController : ControllerBase
12 | {
13 | private readonly KeyboardContext _context;
14 | private readonly ILogger _logger;
15 |
16 | public KeyboardController(KeyboardContext context, ILogger logger)
17 | {
18 | _context = context;
19 | _logger = logger;
20 | }
21 |
22 | // GET api/keyboard
23 | ///
24 | /// 获取默认页面。
25 | ///
26 | [HttpGet]
27 | public ActionResult Get()
28 | {
29 | _logger.LogInformation("Get");
30 | return Get("0");
31 | }
32 |
33 | // GET api/keyboard/5
34 | ///
35 | /// 获取指定 下正在输入的文本。
36 | /// 为了保持幂等性,即使输入操作结束并开始输入下一条文本,此操作也不会得到下一条输入的文本。
37 | /// 这样,即使不断在浏览器中访问网址,也不会导致 App 中的获取失效。
38 | /// 在 App 中请使用 POST 方法以便在消息上屏后可以清除上屏的消息并获取到下一条新消息。
39 | ///
40 | [HttpGet("{token}")]
41 | public ActionResult Get(string token)
42 | {
43 | _logger.LogInformation("Get Token={0}", token);
44 | var keyboard = _context.Keyboards.Find(token);
45 | if (keyboard == null)
46 | {
47 | return NotFound(new TypingResponse(false, $"Token {token} not found."));
48 | }
49 |
50 | var value = _context.Typings.FirstOrDefault(x => x.KeyboardToken == token);
51 |
52 | if (value == null)
53 | {
54 | return NotFound(new TypingResponse(false, $"Token {token} has no texts."));
55 | }
56 |
57 | return value.AsClient();
58 | }
59 |
60 | // GET api/keyboard/5
61 | ///
62 | /// 获取指定 下特定 的文本。
63 | /// 有可能这是一条早已用过的文本。
64 | ///
65 | [HttpGet("{token}/{typingId}")]
66 | public ActionResult Get(string token, int typingId)
67 | {
68 | var keyboard = _context.Keyboards.Find(token);
69 | if (keyboard == null)
70 | {
71 | return NotFound(new TypingResponse(false, $"Token {token} not found. CurrentToken={string.Join(";", _context.Keyboards.Select(temp => temp.Token))}"));
72 | }
73 |
74 | var value = _context.Typings.Find(typingId);
75 |
76 | if (value == null)
77 | {
78 | return NotFound(new TypingResponse(false, $"Text {typingId} not found."));
79 | }
80 |
81 | if (value.KeyboardToken != token)
82 | {
83 | return NotFound(new TypingResponse(false, $"Accessing to text {typingId} is denied."));
84 | }
85 |
86 | return value.AsClient();
87 | }
88 |
89 | // GET api/keyboard/5
90 | ///
91 | /// 获取指定 下正在输入的文本。
92 | /// 如果此 不存在,将创建 Token。
93 | /// 在获取此消息之后,如果此消息已经上屏,那么此条消息将会被删除,下次访问将返回新输入的一条消息。
94 | ///
95 | [HttpPost("{token}")]
96 | public ActionResult Post(string token)
97 | {
98 | _logger.LogInformation("Post token={0}", token);
99 |
100 | var keyboard = _context.Keyboards.Find(token);
101 | if (keyboard == null)
102 | {
103 | _context.Keyboards.Add(new Keyboard { Token = token });
104 | _context.SaveChanges();
105 | return new TypingText("");
106 | }
107 |
108 | var value = _context.Typings.FirstOrDefault(x => x.KeyboardToken == token);
109 | if (value == null)
110 | {
111 | return new TypingText("");
112 | }
113 |
114 | if (value.Enter)
115 | {
116 | _context.Typings.Remove(value);
117 | _context.SaveChanges();
118 | }
119 |
120 | return value.AsClient();
121 | }
122 |
123 | // PUT api/keyboard/5
124 | ///
125 | /// 使用指定的 替换指定 下的输入文本。
126 | ///
127 | [HttpPut("{token}")]
128 | public ActionResult Put(string token, [FromBody] TypingText value)
129 | {
130 | _logger.LogInformation("Put token={0} TypingText={1} Enter={2}", token, value.Text, value.Enter);
131 |
132 | var keyboard = _context.Keyboards.Find(token);
133 | if (keyboard == null)
134 | {
135 | return NotFound(new TypingResponse(false, $"Token {token} not found."));
136 | }
137 |
138 | var lastValue = _context.Typings.LastOrDefault(x => x.KeyboardToken == token);
139 | if (lastValue == null || lastValue.Enter)
140 | {
141 | if (!string.IsNullOrEmpty(value.Text) || value.Enter)
142 | {
143 | _context.Typings.Add(new Models.TypingText(token, value));
144 | _context.SaveChanges();
145 | return new TypingResponse(true, "A new text message has been created.");
146 | }
147 | else
148 | {
149 | return new TypingResponse(true, "There is no need to update text message.");
150 | }
151 | }
152 | else
153 | {
154 | lastValue.UpdateFrom(value);
155 | _context.Entry(lastValue).State = EntityState.Modified;
156 | _context.SaveChanges();
157 | return new TypingResponse(true, "The message has been updated.");
158 | }
159 | }
160 |
161 | // DELETE api/keyboard/5
162 | ///
163 | /// 删除指定的 ,这样就 GET 不到了。
164 | ///
165 | [HttpDelete("{token}")]
166 | public void Delete(string token)
167 | {
168 | _logger.LogInformation("Delete Token={0}", token);
169 |
170 | var keyboard = _context.Keyboards.Find(token);
171 | if (keyboard != null)
172 | {
173 | _context.Keyboards.Remove(keyboard);
174 | _context.Typings.RemoveRange(_context.Typings.Where(x => x.KeyboardToken == token).ToArray());
175 | }
176 | }
177 | }
178 | }
--------------------------------------------------------------------------------
/CloudKeyboard.iOS/Walterlv.CloudKeyboard.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | 8.0.30703
7 | 2.0
8 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}
9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | {6143fdea-f3c2-4a09-aafa-6e230626515e}
11 | Exe
12 | Walterlv.CloudTyping
13 | Resources
14 | Walterlv.CloudKeyboard
15 | NSUrlSessionHandler
16 |
17 |
18 |
19 |
20 | true
21 | full
22 | false
23 | bin\iPhoneSimulator\Debug
24 | DEBUG
25 | prompt
26 | 4
27 | false
28 | x86_64
29 | None
30 | true
31 |
32 |
33 | none
34 | true
35 | bin\iPhoneSimulator\Release
36 | prompt
37 | 4
38 | None
39 | x86_64
40 | false
41 |
42 |
43 | true
44 | full
45 | false
46 | bin\iPhone\Debug
47 | DEBUG
48 | prompt
49 | 4
50 | false
51 | ARM64
52 | iPhone Developer: walterlv@icloud.com (F53JH45N57)
53 | true
54 | Entitlements.plist
55 | iOS Team Provisioning Profile: com.walterlv.CloudKeyboard
56 |
57 |
58 | none
59 | true
60 | bin\iPhone\Release
61 | prompt
62 | 4
63 | ARM64
64 | false
65 | iPhone Developer
66 | Entitlements.plist
67 |
68 |
69 | none
70 | True
71 | bin\iPhone\Ad-Hoc
72 | prompt
73 | 4
74 | False
75 | ARM64
76 | True
77 | Automatic:AdHoc
78 | iPhone Distribution
79 | Entitlements.plist
80 |
81 |
82 | none
83 | True
84 | bin\iPhone\AppStore
85 | prompt
86 | 4
87 | False
88 | ARM64
89 | Automatic:AppStore
90 | iPhone Distribution
91 | Entitlements.plist
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | false
104 |
105 |
106 | false
107 |
108 |
109 | false
110 |
111 |
112 | false
113 |
114 |
115 | false
116 |
117 |
118 | false
119 |
120 |
121 | false
122 |
123 |
124 | false
125 |
126 |
127 | false
128 |
129 |
130 | false
131 |
132 |
133 | false
134 |
135 |
136 | false
137 |
138 |
139 | false
140 |
141 |
142 | false
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | true
157 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}
158 | Walterlv.CloudKeyboard.iOS.Extension
159 |
160 |
161 | {a2182b4a-a700-47be-8905-65e8c258b87e}
162 | Walterlv.CloudKeyboard.Xaml
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/CloudKeyboard.Windows/Walterlv.CloudKeyboard.Windows.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}
8 | AppContainerExe
9 | Properties
10 | Walterlv.CloudTyping
11 | Walterlv.CloudKeyboard.Windows
12 | en-US
13 | UAP
14 | 10.0.17763.0
15 | 10.0.17763.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | true
20 | Walterlv.CloudKeyboard.Windows_TemporaryKey.pfx
21 |
22 |
23 | true
24 | bin\x86\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | x86
29 | false
30 | prompt
31 | true
32 |
33 |
34 | bin\x86\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | true
37 | ;2008
38 | pdbonly
39 | x86
40 | false
41 | prompt
42 | true
43 | true
44 |
45 |
46 | true
47 | bin\ARM\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
49 | ;2008
50 | full
51 | ARM
52 | false
53 | prompt
54 | true
55 |
56 |
57 | bin\ARM\Release\
58 | TRACE;NETFX_CORE;WINDOWS_UWP
59 | true
60 | ;2008
61 | pdbonly
62 | ARM
63 | false
64 | prompt
65 | true
66 | true
67 |
68 |
69 | true
70 | bin\ARM64\Debug\
71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
72 | ;2008
73 | full
74 | ARM64
75 | false
76 | prompt
77 | true
78 | true
79 |
80 |
81 | bin\ARM64\Release\
82 | TRACE;NETFX_CORE;WINDOWS_UWP
83 | true
84 | ;2008
85 | pdbonly
86 | ARM64
87 | false
88 | prompt
89 | true
90 | true
91 |
92 |
93 | true
94 | bin\x64\Debug\
95 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
96 | ;2008
97 | full
98 | x64
99 | false
100 | prompt
101 | true
102 |
103 |
104 | bin\x64\Release\
105 | TRACE;NETFX_CORE;WINDOWS_UWP
106 | true
107 | ;2008
108 | pdbonly
109 | x64
110 | false
111 | prompt
112 | true
113 | true
114 |
115 |
116 | PackageReference
117 |
118 |
119 |
120 | App.xaml
121 |
122 |
123 | MainPage.xaml
124 |
125 |
126 |
127 |
128 |
129 | Designer
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | MSBuild:Compile
146 | Designer
147 |
148 |
149 | MSBuild:Compile
150 | Designer
151 |
152 |
153 |
154 |
155 | 6.2.3
156 |
157 |
158 |
159 |
160 | {ece91eb2-2dd8-41f7-be7f-fb57484807b1}
161 | Walterlv.CloudKeyboard.Core
162 |
163 |
164 |
165 | 14.0
166 |
167 |
168 |
175 |
--------------------------------------------------------------------------------
/CloudKeyboard.Package/Walterlv.CloudKeyboard.Package.wapproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 15.0
5 |
6 |
7 |
8 | Debug
9 | x86
10 |
11 |
12 | Release
13 | x86
14 |
15 |
16 | Debug
17 | x64
18 |
19 |
20 | Release
21 | x64
22 |
23 |
24 | Debug
25 | ARM
26 |
27 |
28 | Release
29 | ARM
30 |
31 |
32 | Debug
33 | ARM64
34 |
35 |
36 | Release
37 | ARM64
38 |
39 |
40 | Debug
41 | AnyCPU
42 |
43 |
44 | Release
45 | AnyCPU
46 |
47 |
48 |
49 | $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\
50 |
51 |
52 |
53 | 18bf7e9a-d417-4673-9cf2-d23c130036e6
54 | 10.0.17763.0
55 | 10.0.16299.0
56 | zh-CN
57 | Walterlv.CloudKeyboard.Package_StoreKey.pfx
58 | ..\CloudKeyboard.Wpf\Walterlv.CloudKeyboard.Wpf.csproj
59 | 4A6586663EC478A8EA474115B7B518755EE87EA6
60 | False
61 | True
62 | x86
63 | 1
64 | OnApplicationRun
65 |
66 |
67 | Always
68 |
69 |
70 | Always
71 |
72 |
73 | Always
74 |
75 |
76 | Always
77 |
78 |
79 | Always
80 |
81 |
82 | Always
83 |
84 |
85 | Always
86 |
87 |
88 | Always
89 |
90 |
91 | Always
92 |
93 |
94 | Always
95 |
96 |
97 |
98 | Designer
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | True
155 | $(DesktopBridgeRuntimeIdentifier)
156 | SelfContained=%(DesktopBridgeSelfContained);RuntimeIdentifier=%(DesktopBridgeIdentifier)
157 | True
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS.Extension/Walterlv.CloudKeyboard.iOS.Extension.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | iPhoneSimulator
7 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}
8 | {EE2C853D-36AF-4FDB-B1AD-8E90477E2198};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
9 | Library
10 | Walterlv.CloudTyping
11 | Walterlv.CloudKeyboard.Keyboard
12 | Resources
13 |
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\iPhoneSimulator\Debug
21 | DEBUG;
22 | prompt
23 | 4
24 | iPhone Developer
25 | true
26 | true
27 | true
28 | 23103
29 | None
30 | x86_64
31 | NSUrlSessionHandler
32 | false
33 |
34 |
35 | latest
36 |
37 |
38 | pdbonly
39 | true
40 | bin\iPhone\Release
41 |
42 |
43 | prompt
44 | 4
45 | iPhone Developer
46 | true
47 | true
48 | Entitlements.plist
49 | SdkOnly
50 | ARM64
51 | NSUrlSessionHandler
52 |
53 |
54 | latest
55 |
56 |
57 | pdbonly
58 | true
59 | bin\iPhoneSimulator\Release
60 |
61 |
62 | prompt
63 | 4
64 | iPhone Developer
65 | true
66 | None
67 | x86_64
68 | NSUrlSessionHandler
69 |
70 |
71 | latest
72 |
73 |
74 | true
75 | full
76 | false
77 | bin\iPhone\Debug
78 | DEBUG;
79 | prompt
80 | 4
81 | iPhone Developer: walterlv@icloud.com (F53JH45N57)
82 | true
83 | true
84 | true
85 | true
86 | true
87 | Entitlements.plist
88 | 50412
89 | SdkOnly
90 | ARM64
91 | NSUrlSessionHandler
92 |
93 |
94 | iOS Team Provisioning Profile: com.walterlv.CloudKeyboard.Keyboard
95 | latest
96 |
97 |
98 |
99 | ..\packages\Newtonsoft.Json.12.0.1\lib\netstandard2.0\Newtonsoft.Json.dll
100 |
101 |
102 |
103 |
104 |
105 |
106 | ..\packages\Xamarin.Forms.3.4.0.1009999\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
107 |
108 |
109 | ..\packages\Xamarin.Forms.3.4.0.1009999\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
110 |
111 |
112 | ..\packages\Xamarin.Forms.3.4.0.1009999\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
113 |
114 |
115 | ..\packages\Xamarin.Forms.3.4.0.1009999\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | Core\Client\CloudKeyboardReceiver.cs
127 |
128 |
129 | Core\Client\DelayRunner.cs
130 |
131 |
132 | Core\Client\ExceptionEventArgs.cs
133 |
134 |
135 | Core\Client\TypingTextEventArgs.cs
136 |
137 |
138 | Core\CloudKeyboard.cs
139 |
140 |
141 | Core\HostInfo.cs
142 |
143 |
144 | Core\TypingResponse.cs
145 |
146 |
147 | Core\TypingText.cs
148 |
149 |
150 |
151 | KeyboardViewController.cs
152 |
153 |
154 |
155 |
156 |
157 |
158 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
159 |
160 |
161 |
162 |
163 |
164 |
--------------------------------------------------------------------------------
/CloudKeyboard.Wpf/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
20 |
21 |
22 |
35 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
96 |
100 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
125 |
126 |
127 |
128 |
129 |
133 |
135 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
147 |
149 |
151 |
152 |
161 |
162 |
163 |
164 |
--------------------------------------------------------------------------------
/CloudKeyboard.iOS.Extension/KeyboardViewController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using ObjCRuntime;
6 | using UIKit;
7 | using Walterlv.CloudTyping.Client;
8 |
9 | namespace Walterlv.CloudTyping
10 | {
11 | public partial class KeyboardViewController : UIInputViewController
12 | {
13 | private UIButton _nextKeyboardButton;
14 | private UIButton _debugButton;
15 | private UIButton _tokenButton;
16 | private UIButton _returnButton;
17 | private static int _staticLoadedCount;
18 | private int _loadedCount;
19 | private static int _unloadedCount;
20 | private int _receivedCount;
21 | private int _totalReceivedCount;
22 | private int _changedCount;
23 | private CloudKeyboardReceiver _receiver;
24 | private bool IsLoaded => _nextKeyboardButton != null;
25 |
26 | protected KeyboardViewController(IntPtr handle) : base(handle)
27 | {
28 | // Note: this .ctor should not contain any initialization logic.
29 | }
30 |
31 | public override void DidReceiveMemoryWarning()
32 | {
33 | // Releases the view if it doesn't have a superview.
34 | base.DidReceiveMemoryWarning();
35 |
36 | // Release any cached data, images, etc that aren't in use.
37 | }
38 |
39 | public override void UpdateViewConstraints()
40 | {
41 | base.UpdateViewConstraints();
42 |
43 | // Add custom view sizing constraints here
44 | }
45 |
46 | public override void ViewDidLoad()
47 | {
48 | base.ViewDidLoad();
49 |
50 | var token = UIDevice.CurrentDevice.Name;
51 |
52 | try
53 | {
54 | // 调试按钮
55 | _debugButton = CreateButtonToView(View, "...",
56 | NSLayoutAttribute.CenterX, NSLayoutAttribute.Top);
57 | }
58 | catch (Exception ex)
59 | {
60 | }
61 |
62 | try
63 | {
64 | // Token 按钮
65 | _tokenButton = CreateButtonToView(View, $"使用此文本设置你的 PC 键盘:{token}",
66 | NSLayoutAttribute.CenterX, NSLayoutAttribute.CenterY);
67 | }
68 | catch (Exception ex)
69 | {
70 | Debug(ex);
71 | }
72 |
73 | try
74 | {
75 | // 切换输入法按钮
76 | _nextKeyboardButton = CreateButtonToView(View, "Next Keyboard",
77 | NSLayoutAttribute.Left, NSLayoutAttribute.Bottom);
78 | _nextKeyboardButton.AddTarget(this, new Selector("advanceToNextInputMode"), UIControlEvent.TouchUpInside);
79 | }
80 | catch (Exception ex)
81 | {
82 | Debug(ex);
83 | }
84 |
85 | try
86 | {
87 | // 确认按钮
88 | _returnButton = CreateButtonToView(View, TextDocumentProxy.ReturnKeyType.ToString(),
89 | NSLayoutAttribute.Right, NSLayoutAttribute.Bottom);
90 | }
91 | catch (Exception ex)
92 | {
93 | Debug(ex);
94 | }
95 |
96 | // 初始化打字。
97 | if (_receiver == null)
98 | {
99 | _receiver = new CloudKeyboardReceiver(HostInfo.BaseUrl, token);
100 | _receiver.Typing += DidReceive;
101 | _receiver.Confirmed += DidConfirm;
102 | _receiver.ExceptionOccurred += ExceptionDidOccur;
103 | }
104 | }
105 |
106 | public override void ViewDidAppear(bool animated)
107 | {
108 | base.ViewDidAppear(animated);
109 | _receiver?.Start();
110 | _staticLoadedCount++;
111 | _loadedCount++;
112 | }
113 |
114 | public override void ViewWillDisappear(bool animated)
115 | {
116 | _unloadedCount++;
117 | _receiver?.Stop();
118 | base.ViewWillDisappear(animated);
119 | }
120 |
121 | public override void TextWillChange(IUITextInput textInput)
122 | {
123 | // The app is about to change the document's contents. Perform any preparation here.
124 | }
125 |
126 | public override void TextDidChange(IUITextInput textInput)
127 | {
128 | // The app has just changed the document's contents, the document context has been updated.
129 | UIColor textColor = null;
130 |
131 | try
132 | {
133 | if (TextDocumentProxy.KeyboardAppearance == UIKeyboardAppearance.Dark)
134 | {
135 | textColor = UIColor.White;
136 | }
137 | else
138 | {
139 | textColor = UIColor.Black;
140 | }
141 |
142 | _nextKeyboardButton.SetTitleColor(textColor, UIControlState.Normal);
143 | _tokenButton.SetTitleColor(textColor, UIControlState.Normal);
144 | _debugButton.SetTitleColor(textColor, UIControlState.Normal);
145 |
146 | _returnButton.SetTitle(TextDocumentProxy.ReturnKeyType.ToString(), UIControlState.Normal);
147 | _returnButton.SizeToFit();
148 | _returnButton.TranslatesAutoresizingMaskIntoConstraints = false;
149 | }
150 | catch (Exception e)
151 | {
152 | Debug(e);
153 | }
154 | }
155 |
156 | private void DidReceive(object sender, TypingTextEventArgs e)
157 | {
158 | BeginInvokeOnMainThread(() =>
159 | {
160 | try
161 | {
162 | _receivedCount++;
163 | _totalReceivedCount++;
164 |
165 | Input(e.Typing.Text);
166 |
167 | // 阻止屏幕黑屏 https://github.com/walterlv/Walterlv.CloudKeyboard/issues/3
168 | UIApplication.SharedApplication.IdleTimerDisabled = true;
169 | UpdateCounts();
170 | }
171 | catch (Exception ex)
172 | {
173 | Debug(ex);
174 | }
175 | });
176 | }
177 |
178 | private void DidConfirm(object sender, TypingTextEventArgs e)
179 | {
180 | BeginInvokeOnMainThread(() =>
181 | {
182 | try
183 | {
184 | _receivedCount = 0;
185 | _totalReceivedCount++;
186 |
187 | Input(e.Typing.Text);
188 | Input("\n");
189 |
190 | UpdateCounts();
191 | }
192 | catch (Exception ex)
193 | {
194 | Debug(ex);
195 | }
196 | });
197 | }
198 |
199 | private void ExceptionDidOccur(object sender, ExceptionEventArgs e)
200 | {
201 | Debug(e.Exception);
202 | }
203 |
204 | private UIButton CreateButtonToView(UIView view, string title,
205 | NSLayoutAttribute horizontalAlignment, NSLayoutAttribute verticalAlignment)
206 | {
207 | var button = new UIButton(UIButtonType.System);
208 |
209 | button.SetTitle(title, UIControlState.Normal);
210 | button.SizeToFit();
211 | button.TranslatesAutoresizingMaskIntoConstraints = false;
212 |
213 | view.AddSubview(button);
214 |
215 | var okButtonCenterXConstraint = NSLayoutConstraint.Create(button,
216 | horizontalAlignment, NSLayoutRelation.Equal, view, horizontalAlignment, 1.0f, 0.0f);
217 | var okButtonCenterYConstraint = NSLayoutConstraint.Create(button,
218 | verticalAlignment, NSLayoutRelation.Equal, view, verticalAlignment, 1.0f, 0.0f);
219 | view.AddConstraints(new[] { okButtonCenterXConstraint, okButtonCenterYConstraint });
220 |
221 | return button;
222 | }
223 |
224 | private void UpdateCounts()
225 | {
226 | Debug($"{_staticLoadedCount}-{_loadedCount}-{_unloadedCount} -- {_totalReceivedCount}-{_receivedCount}-{_changedCount}");
227 | }
228 |
229 | private string _lastText;
230 | private readonly Queue _inputingTexts = new Queue();
231 |
232 | private void Input(string text)
233 | {
234 | BeginInvokeOnMainThread(()=>
235 | {
236 | try
237 | {
238 | InputInner();
239 | }
240 | catch (Exception ex)
241 | {
242 | Debug(ex);
243 | }
244 | });
245 |
246 | async void InputInner()
247 | {
248 | if (!IsLoaded)
249 | {
250 | return;
251 | }
252 |
253 | if (text == _lastText)
254 | {
255 | return;
256 | }
257 |
258 | _lastText = text;
259 |
260 | if (_inputingTexts.Any())
261 | {
262 | _inputingTexts.Enqueue(text);
263 | return;
264 | }
265 |
266 | _inputingTexts.Enqueue(text);
267 |
268 | while (_inputingTexts.Any())
269 | {
270 | var current = _inputingTexts.Dequeue();
271 | if (_inputingTexts.Any())
272 | {
273 | var next = _inputingTexts.Peek();
274 | if (current == "\n")
275 | {
276 | TextDocumentProxy.InsertText("\n");
277 | await Task.Delay(100);
278 | }
279 | else if (next == "\n")
280 | {
281 | SetText(current);
282 | await Task.Delay(100);
283 | }
284 | else
285 | {
286 | continue;
287 | }
288 | }
289 | else
290 | {
291 | SetText(current);
292 | await Task.Delay(100);
293 | }
294 | }
295 |
296 | UpdateCounts();
297 | }
298 | }
299 |
300 | private void SetText(string text)
301 | {
302 | BeginInvokeOnMainThread(SetTextInner);
303 |
304 | void SetTextInner()
305 | {
306 | try
307 | {
308 | _changedCount++;
309 | while (TextDocumentProxy.HasText)
310 | {
311 | TextDocumentProxy.DeleteBackward();
312 | }
313 |
314 | TextDocumentProxy.InsertText(text);
315 | }
316 | catch (Exception ex)
317 | {
318 | Debug(ex);
319 | }
320 | }
321 | }
322 |
323 | private void Debug(Exception exception)
324 | {
325 | if (!IsLoaded)
326 | {
327 | return;
328 | }
329 |
330 | string info;
331 | if (exception is NullReferenceException nre)
332 | {
333 | info = $"null:{nre.StackTrace}";
334 | }
335 | else
336 | {
337 | info = $"{exception.GetType().Name.Replace("Exception", "")}:{exception.StackTrace}";
338 | }
339 |
340 | Debug(info);
341 | }
342 |
343 | private void Debug(string info)
344 | {
345 | BeginInvokeOnMainThread(() =>
346 | {
347 | _debugButton.SetTitle(info, UIControlState.Normal);
348 | _debugButton.SizeToFit();
349 | });
350 | }
351 | }
352 | }
353 |
--------------------------------------------------------------------------------
/Walterlv.CloudKeyboard.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28721.148
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Walterlv.CloudKeyboard.Core", "CloudKeyboard.Core\Walterlv.CloudKeyboard.Core.csproj", "{ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Walterlv.CloudKeybaord.Cli", "CloudKeybaord.Cli\Walterlv.CloudKeybaord.Cli.csproj", "{EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Walterlv.CloudKeyboard.Windows", "CloudKeyboard.Windows\Walterlv.CloudKeyboard.Windows.csproj", "{9A511A00-B27F-42FC-B398-5ABE4D60C2E1}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Walterlv.CloudKeyboard.Wpf", "CloudKeyboard.Wpf\Walterlv.CloudKeyboard.Wpf.csproj", "{83D719E9-3D7B-4266-BE47-0FDEB92FECCB}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Walterlv.CloudKeyboard.iOS.Extension", "CloudKeyboard.iOS.Extension\Walterlv.CloudKeyboard.iOS.Extension.csproj", "{F70F519C-49D8-4178-B05B-C4A0391D7C91}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{B3A6F801-0997-4EAE-8F7C-41D90B224B61}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{4175E5A0-1B5A-47E4-A9EA-0FC421148938}"
19 | EndProject
20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Windows", "Windows", "{3120DFA2-0946-4259-833C-7A704CF00ECC}"
21 | EndProject
22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{3B434268-93DE-49AD-83B0-069B50CB6891}"
23 | EndProject
24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Walterlv.CloudKeyboard.Xaml", "CloudKeyboard.Xaml\Walterlv.CloudKeyboard.Xaml.csproj", "{A2182B4A-A700-47BE-8905-65E8C258B87E}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Walterlv.CloudKeyboard.iOS", "CloudKeyboard.iOS\Walterlv.CloudKeyboard.iOS.csproj", "{EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}"
27 | EndProject
28 | Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Walterlv.CloudKeyboard.Package", "CloudKeyboard.Package\Walterlv.CloudKeyboard.Package.wapproj", "{18BF7E9A-D417-4673-9CF2-D23C130036E6}"
29 | EndProject
30 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Walterlv.CloudKeyboard.WebApi", "CloudKeyboard.WebApi\Walterlv.CloudKeyboard.WebApi.csproj", "{3862980D-169C-4736-89CC-8744D15F3CFE}"
31 | EndProject
32 | Global
33 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
34 | Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
35 | Ad-Hoc|ARM = Ad-Hoc|ARM
36 | Ad-Hoc|ARM64 = Ad-Hoc|ARM64
37 | Ad-Hoc|iPhone = Ad-Hoc|iPhone
38 | Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
39 | Ad-Hoc|x64 = Ad-Hoc|x64
40 | Ad-Hoc|x86 = Ad-Hoc|x86
41 | AppStore|Any CPU = AppStore|Any CPU
42 | AppStore|ARM = AppStore|ARM
43 | AppStore|ARM64 = AppStore|ARM64
44 | AppStore|iPhone = AppStore|iPhone
45 | AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
46 | AppStore|x64 = AppStore|x64
47 | AppStore|x86 = AppStore|x86
48 | Debug|Any CPU = Debug|Any CPU
49 | Debug|ARM = Debug|ARM
50 | Debug|ARM64 = Debug|ARM64
51 | Debug|iPhone = Debug|iPhone
52 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
53 | Debug|x64 = Debug|x64
54 | Debug|x86 = Debug|x86
55 | Release|Any CPU = Release|Any CPU
56 | Release|ARM = Release|ARM
57 | Release|ARM64 = Release|ARM64
58 | Release|iPhone = Release|iPhone
59 | Release|iPhoneSimulator = Release|iPhoneSimulator
60 | Release|x64 = Release|x64
61 | Release|x86 = Release|x86
62 | EndGlobalSection
63 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
64 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
65 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
66 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
67 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
68 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|ARM64.ActiveCfg = Release|Any CPU
69 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|ARM64.Build.0 = Release|Any CPU
70 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
71 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
72 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
73 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
74 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
75 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|x64.Build.0 = Release|Any CPU
76 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
77 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Ad-Hoc|x86.Build.0 = Release|Any CPU
78 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
79 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|Any CPU.Build.0 = Release|Any CPU
80 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|ARM.ActiveCfg = Release|Any CPU
81 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|ARM.Build.0 = Release|Any CPU
82 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|ARM64.ActiveCfg = Release|Any CPU
83 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|ARM64.Build.0 = Release|Any CPU
84 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
85 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|iPhone.Build.0 = Debug|Any CPU
86 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
87 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
88 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|x64.ActiveCfg = Release|Any CPU
89 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|x64.Build.0 = Release|Any CPU
90 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|x86.ActiveCfg = Release|Any CPU
91 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.AppStore|x86.Build.0 = Release|Any CPU
92 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
93 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
94 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|ARM.ActiveCfg = Debug|Any CPU
95 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|ARM.Build.0 = Debug|Any CPU
96 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|ARM64.ActiveCfg = Debug|Any CPU
97 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|ARM64.Build.0 = Debug|Any CPU
98 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|iPhone.ActiveCfg = Debug|Any CPU
99 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|iPhone.Build.0 = Debug|Any CPU
100 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
101 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
102 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|x64.ActiveCfg = Debug|Any CPU
103 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|x64.Build.0 = Debug|Any CPU
104 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|x86.ActiveCfg = Debug|Any CPU
105 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Debug|x86.Build.0 = Debug|Any CPU
106 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
107 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|Any CPU.Build.0 = Release|Any CPU
108 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|ARM.ActiveCfg = Release|Any CPU
109 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|ARM.Build.0 = Release|Any CPU
110 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|ARM64.ActiveCfg = Release|Any CPU
111 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|ARM64.Build.0 = Release|Any CPU
112 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|iPhone.ActiveCfg = Release|Any CPU
113 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|iPhone.Build.0 = Release|Any CPU
114 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
115 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
116 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|x64.ActiveCfg = Release|Any CPU
117 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|x64.Build.0 = Release|Any CPU
118 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|x86.ActiveCfg = Release|Any CPU
119 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1}.Release|x86.Build.0 = Release|Any CPU
120 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
121 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
122 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
123 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
124 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|ARM64.ActiveCfg = Release|Any CPU
125 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|ARM64.Build.0 = Release|Any CPU
126 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
127 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
128 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
129 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
130 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
131 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|x64.Build.0 = Release|Any CPU
132 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
133 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Ad-Hoc|x86.Build.0 = Release|Any CPU
134 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
135 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|Any CPU.Build.0 = Release|Any CPU
136 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|ARM.ActiveCfg = Release|Any CPU
137 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|ARM.Build.0 = Release|Any CPU
138 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|ARM64.ActiveCfg = Release|Any CPU
139 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|ARM64.Build.0 = Release|Any CPU
140 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
141 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|iPhone.Build.0 = Debug|Any CPU
142 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
143 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
144 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|x64.ActiveCfg = Release|Any CPU
145 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|x64.Build.0 = Release|Any CPU
146 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|x86.ActiveCfg = Release|Any CPU
147 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.AppStore|x86.Build.0 = Release|Any CPU
148 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
149 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
150 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|ARM.ActiveCfg = Debug|Any CPU
151 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|ARM.Build.0 = Debug|Any CPU
152 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
153 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|ARM64.Build.0 = Debug|Any CPU
154 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
155 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|iPhone.Build.0 = Debug|Any CPU
156 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
157 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
158 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|x64.ActiveCfg = Debug|Any CPU
159 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|x64.Build.0 = Debug|Any CPU
160 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|x86.ActiveCfg = Debug|Any CPU
161 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Debug|x86.Build.0 = Debug|Any CPU
162 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
163 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|Any CPU.Build.0 = Release|Any CPU
164 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|ARM.ActiveCfg = Release|Any CPU
165 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|ARM.Build.0 = Release|Any CPU
166 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|ARM64.ActiveCfg = Release|Any CPU
167 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|ARM64.Build.0 = Release|Any CPU
168 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|iPhone.ActiveCfg = Release|Any CPU
169 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|iPhone.Build.0 = Release|Any CPU
170 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
171 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
172 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|x64.ActiveCfg = Release|Any CPU
173 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|x64.Build.0 = Release|Any CPU
174 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|x86.ActiveCfg = Release|Any CPU
175 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF}.Release|x86.Build.0 = Release|Any CPU
176 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|Any CPU.ActiveCfg = Release|x64
177 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|Any CPU.Build.0 = Release|x64
178 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|Any CPU.Deploy.0 = Release|x64
179 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|ARM.ActiveCfg = Release|ARM
180 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|ARM.Build.0 = Release|ARM
181 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|ARM.Deploy.0 = Release|ARM
182 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|ARM64.ActiveCfg = Release|ARM64
183 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|ARM64.Build.0 = Release|ARM64
184 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|ARM64.Deploy.0 = Release|ARM64
185 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|iPhone.ActiveCfg = Debug|x86
186 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|iPhone.Build.0 = Debug|x86
187 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x64
188 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x64
189 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|x64
190 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|x64.ActiveCfg = Release|x64
191 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|x64.Build.0 = Release|x64
192 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|x64.Deploy.0 = Release|x64
193 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|x86.ActiveCfg = Release|x86
194 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|x86.Build.0 = Release|x86
195 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Ad-Hoc|x86.Deploy.0 = Release|x86
196 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|Any CPU.ActiveCfg = Release|x64
197 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|Any CPU.Build.0 = Release|x64
198 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|Any CPU.Deploy.0 = Release|x64
199 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|ARM.ActiveCfg = Release|ARM
200 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|ARM.Build.0 = Release|ARM
201 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|ARM.Deploy.0 = Release|ARM
202 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|ARM64.ActiveCfg = Release|ARM64
203 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|ARM64.Build.0 = Release|ARM64
204 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|ARM64.Deploy.0 = Release|ARM64
205 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|iPhone.ActiveCfg = Debug|x86
206 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|iPhone.Build.0 = Debug|x86
207 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|iPhoneSimulator.ActiveCfg = Release|x64
208 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|iPhoneSimulator.Build.0 = Release|x64
209 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|iPhoneSimulator.Deploy.0 = Release|x64
210 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|x64.ActiveCfg = Release|x64
211 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|x64.Build.0 = Release|x64
212 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|x64.Deploy.0 = Release|x64
213 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|x86.ActiveCfg = Release|x86
214 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|x86.Build.0 = Release|x86
215 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.AppStore|x86.Deploy.0 = Release|x86
216 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|Any CPU.ActiveCfg = Debug|x86
217 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|ARM.ActiveCfg = Debug|ARM
218 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|ARM.Build.0 = Debug|ARM
219 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|ARM.Deploy.0 = Debug|ARM
220 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|ARM64.ActiveCfg = Debug|ARM64
221 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|ARM64.Build.0 = Debug|ARM64
222 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|ARM64.Deploy.0 = Debug|ARM64
223 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|iPhone.ActiveCfg = Debug|x86
224 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
225 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|x64.ActiveCfg = Debug|x64
226 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|x64.Build.0 = Debug|x64
227 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|x64.Deploy.0 = Debug|x64
228 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|x86.ActiveCfg = Debug|x86
229 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|x86.Build.0 = Debug|x86
230 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Debug|x86.Deploy.0 = Debug|x86
231 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|Any CPU.ActiveCfg = Release|x86
232 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|ARM.ActiveCfg = Release|ARM
233 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|ARM.Build.0 = Release|ARM
234 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|ARM.Deploy.0 = Release|ARM
235 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|ARM64.ActiveCfg = Release|ARM64
236 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|ARM64.Build.0 = Release|ARM64
237 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|ARM64.Deploy.0 = Release|ARM64
238 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|iPhone.ActiveCfg = Release|x86
239 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|iPhoneSimulator.ActiveCfg = Release|x86
240 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|x64.ActiveCfg = Release|x64
241 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|x64.Build.0 = Release|x64
242 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|x64.Deploy.0 = Release|x64
243 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|x86.ActiveCfg = Release|x86
244 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|x86.Build.0 = Release|x86
245 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1}.Release|x86.Deploy.0 = Release|x86
246 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
247 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
248 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
249 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
250 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|ARM64.ActiveCfg = Release|Any CPU
251 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|ARM64.Build.0 = Release|Any CPU
252 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
253 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
254 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
255 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
256 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
257 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|x64.Build.0 = Release|Any CPU
258 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
259 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Ad-Hoc|x86.Build.0 = Release|Any CPU
260 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
261 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|Any CPU.Build.0 = Release|Any CPU
262 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|ARM.ActiveCfg = Release|Any CPU
263 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|ARM.Build.0 = Release|Any CPU
264 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|ARM64.ActiveCfg = Release|Any CPU
265 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|ARM64.Build.0 = Release|Any CPU
266 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
267 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|iPhone.Build.0 = Debug|Any CPU
268 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
269 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
270 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|x64.ActiveCfg = Release|Any CPU
271 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|x64.Build.0 = Release|Any CPU
272 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|x86.ActiveCfg = Release|Any CPU
273 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.AppStore|x86.Build.0 = Release|Any CPU
274 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
275 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
276 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|ARM.ActiveCfg = Debug|Any CPU
277 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|ARM.Build.0 = Debug|Any CPU
278 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|ARM64.ActiveCfg = Debug|Any CPU
279 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|ARM64.Build.0 = Debug|Any CPU
280 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
281 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|iPhone.Build.0 = Debug|Any CPU
282 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
283 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
284 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|x64.ActiveCfg = Debug|Any CPU
285 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|x64.Build.0 = Debug|Any CPU
286 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|x86.ActiveCfg = Debug|Any CPU
287 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Debug|x86.Build.0 = Debug|Any CPU
288 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
289 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|Any CPU.Build.0 = Release|Any CPU
290 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|ARM.ActiveCfg = Release|Any CPU
291 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|ARM.Build.0 = Release|Any CPU
292 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|ARM64.ActiveCfg = Release|Any CPU
293 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|ARM64.Build.0 = Release|Any CPU
294 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|iPhone.ActiveCfg = Release|Any CPU
295 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|iPhone.Build.0 = Release|Any CPU
296 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
297 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
298 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|x64.ActiveCfg = Release|Any CPU
299 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|x64.Build.0 = Release|Any CPU
300 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|x86.ActiveCfg = Release|Any CPU
301 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB}.Release|x86.Build.0 = Release|Any CPU
302 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|Any CPU.ActiveCfg = Release|iPhoneSimulator
303 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|Any CPU.Build.0 = Release|iPhoneSimulator
304 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|ARM.ActiveCfg = Release|iPhoneSimulator
305 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|ARM.Build.0 = Release|iPhoneSimulator
306 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|ARM64.ActiveCfg = Release|iPhoneSimulator
307 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|ARM64.Build.0 = Release|iPhoneSimulator
308 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|iPhone.ActiveCfg = Release|iPhone
309 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|iPhone.Build.0 = Release|iPhone
310 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
311 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
312 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|x64.ActiveCfg = Release|iPhoneSimulator
313 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|x64.Build.0 = Release|iPhoneSimulator
314 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|x86.ActiveCfg = Release|iPhoneSimulator
315 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Ad-Hoc|x86.Build.0 = Release|iPhoneSimulator
316 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|Any CPU.ActiveCfg = Release|iPhoneSimulator
317 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|Any CPU.Build.0 = Release|iPhoneSimulator
318 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|ARM.ActiveCfg = Release|iPhoneSimulator
319 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|ARM.Build.0 = Release|iPhoneSimulator
320 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|ARM64.ActiveCfg = Release|iPhoneSimulator
321 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|ARM64.Build.0 = Release|iPhoneSimulator
322 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|iPhone.ActiveCfg = Release|iPhone
323 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|iPhone.Build.0 = Release|iPhone
324 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
325 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
326 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|x64.ActiveCfg = Release|iPhoneSimulator
327 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|x64.Build.0 = Release|iPhoneSimulator
328 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|x86.ActiveCfg = Release|iPhoneSimulator
329 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.AppStore|x86.Build.0 = Release|iPhoneSimulator
330 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
331 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
332 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|ARM.ActiveCfg = Debug|iPhoneSimulator
333 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|ARM.Build.0 = Debug|iPhoneSimulator
334 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|ARM64.ActiveCfg = Debug|iPhoneSimulator
335 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|ARM64.Build.0 = Debug|iPhoneSimulator
336 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|iPhone.ActiveCfg = Debug|iPhone
337 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|iPhone.Build.0 = Debug|iPhone
338 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
339 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
340 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|x64.ActiveCfg = Debug|iPhoneSimulator
341 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|x64.Build.0 = Debug|iPhoneSimulator
342 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|x86.ActiveCfg = Debug|iPhoneSimulator
343 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Debug|x86.Build.0 = Debug|iPhoneSimulator
344 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|Any CPU.ActiveCfg = Release|iPhone
345 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|Any CPU.Build.0 = Release|iPhone
346 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|ARM.ActiveCfg = Release|iPhone
347 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|ARM.Build.0 = Release|iPhone
348 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|ARM64.ActiveCfg = Release|iPhone
349 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|ARM64.Build.0 = Release|iPhone
350 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|iPhone.ActiveCfg = Release|iPhone
351 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|iPhone.Build.0 = Release|iPhone
352 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
353 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
354 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|x64.ActiveCfg = Release|iPhone
355 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|x64.Build.0 = Release|iPhone
356 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|x86.ActiveCfg = Release|iPhone
357 | {F70F519C-49D8-4178-B05B-C4A0391D7C91}.Release|x86.Build.0 = Release|iPhone
358 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
359 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
360 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
361 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
362 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU
363 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU
364 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
365 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
366 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
367 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
368 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
369 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
370 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
371 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
372 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
373 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|Any CPU.Build.0 = Debug|Any CPU
374 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|ARM.ActiveCfg = Debug|Any CPU
375 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|ARM.Build.0 = Debug|Any CPU
376 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|ARM64.ActiveCfg = Debug|Any CPU
377 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|ARM64.Build.0 = Debug|Any CPU
378 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
379 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|iPhone.Build.0 = Debug|Any CPU
380 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
381 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
382 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|x64.ActiveCfg = Debug|Any CPU
383 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|x64.Build.0 = Debug|Any CPU
384 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|x86.ActiveCfg = Debug|Any CPU
385 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.AppStore|x86.Build.0 = Debug|Any CPU
386 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
387 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|Any CPU.Build.0 = Debug|Any CPU
388 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|ARM.ActiveCfg = Debug|Any CPU
389 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|ARM.Build.0 = Debug|Any CPU
390 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|ARM64.ActiveCfg = Debug|Any CPU
391 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|ARM64.Build.0 = Debug|Any CPU
392 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
393 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|iPhone.Build.0 = Debug|Any CPU
394 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
395 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
396 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|x64.ActiveCfg = Debug|Any CPU
397 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|x64.Build.0 = Debug|Any CPU
398 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|x86.ActiveCfg = Debug|Any CPU
399 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Debug|x86.Build.0 = Debug|Any CPU
400 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|Any CPU.ActiveCfg = Release|Any CPU
401 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|Any CPU.Build.0 = Release|Any CPU
402 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|ARM.ActiveCfg = Release|Any CPU
403 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|ARM.Build.0 = Release|Any CPU
404 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|ARM64.ActiveCfg = Release|Any CPU
405 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|ARM64.Build.0 = Release|Any CPU
406 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|iPhone.ActiveCfg = Release|Any CPU
407 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|iPhone.Build.0 = Release|Any CPU
408 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
409 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
410 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|x64.ActiveCfg = Release|Any CPU
411 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|x64.Build.0 = Release|Any CPU
412 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|x86.ActiveCfg = Release|Any CPU
413 | {A2182B4A-A700-47BE-8905-65E8C258B87E}.Release|x86.Build.0 = Release|Any CPU
414 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
415 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone
416 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|ARM64.ActiveCfg = Ad-Hoc|iPhone
417 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
418 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
419 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
420 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
421 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone
422 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone
423 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
424 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|ARM.ActiveCfg = AppStore|iPhone
425 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|ARM64.ActiveCfg = AppStore|iPhone
426 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
427 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|iPhone.Build.0 = AppStore|iPhone
428 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
429 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
430 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|x64.ActiveCfg = AppStore|iPhone
431 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.AppStore|x86.ActiveCfg = AppStore|iPhone
432 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|Any CPU.ActiveCfg = Debug|iPhone
433 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|ARM.ActiveCfg = Debug|iPhone
434 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|ARM64.ActiveCfg = Debug|iPhone
435 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|iPhone.ActiveCfg = Debug|iPhone
436 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|iPhone.Build.0 = Debug|iPhone
437 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
438 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
439 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|x64.ActiveCfg = Debug|iPhone
440 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Debug|x86.ActiveCfg = Debug|iPhone
441 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|Any CPU.ActiveCfg = Release|iPhone
442 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|ARM.ActiveCfg = Release|iPhone
443 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|ARM64.ActiveCfg = Release|iPhone
444 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|iPhone.ActiveCfg = Release|iPhone
445 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|iPhone.Build.0 = Release|iPhone
446 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
447 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
448 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|x64.ActiveCfg = Release|iPhone
449 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2}.Release|x86.ActiveCfg = Release|iPhone
450 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
451 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
452 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|Any CPU.Deploy.0 = Debug|Any CPU
453 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|ARM.ActiveCfg = Release|ARM
454 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|ARM.Build.0 = Release|ARM
455 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|ARM.Deploy.0 = Release|ARM
456 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|ARM64.ActiveCfg = Release|ARM64
457 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|ARM64.Build.0 = Release|ARM64
458 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|ARM64.Deploy.0 = Release|ARM64
459 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
460 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
461 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|iPhone.Deploy.0 = Debug|Any CPU
462 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
463 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
464 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Debug|Any CPU
465 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|x64.ActiveCfg = Release|x64
466 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|x64.Build.0 = Release|x64
467 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|x64.Deploy.0 = Release|x64
468 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|x86.ActiveCfg = Release|x86
469 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|x86.Build.0 = Release|x86
470 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Ad-Hoc|x86.Deploy.0 = Release|x86
471 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
472 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|Any CPU.Build.0 = Debug|Any CPU
473 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|Any CPU.Deploy.0 = Debug|Any CPU
474 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|ARM.ActiveCfg = Release|ARM
475 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|ARM.Build.0 = Release|ARM
476 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|ARM.Deploy.0 = Release|ARM
477 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|ARM64.ActiveCfg = Release|ARM64
478 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|ARM64.Build.0 = Release|ARM64
479 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|ARM64.Deploy.0 = Release|ARM64
480 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
481 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|iPhone.Build.0 = Debug|Any CPU
482 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|iPhone.Deploy.0 = Debug|Any CPU
483 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
484 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
485 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|iPhoneSimulator.Deploy.0 = Debug|Any CPU
486 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|x64.ActiveCfg = Release|x64
487 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|x64.Build.0 = Release|x64
488 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|x64.Deploy.0 = Release|x64
489 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|x86.ActiveCfg = Release|x86
490 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|x86.Build.0 = Release|x86
491 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.AppStore|x86.Deploy.0 = Release|x86
492 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
493 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
494 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
495 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|ARM.ActiveCfg = Debug|ARM
496 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|ARM.Build.0 = Debug|ARM
497 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|ARM.Deploy.0 = Debug|ARM
498 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|ARM64.ActiveCfg = Debug|ARM64
499 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|ARM64.Build.0 = Debug|ARM64
500 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|ARM64.Deploy.0 = Debug|ARM64
501 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
502 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|iPhone.Build.0 = Debug|Any CPU
503 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|iPhone.Deploy.0 = Debug|Any CPU
504 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
505 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
506 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
507 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|x64.ActiveCfg = Debug|x64
508 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|x64.Build.0 = Debug|x64
509 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|x64.Deploy.0 = Debug|x64
510 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|x86.ActiveCfg = Debug|x86
511 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|x86.Build.0 = Debug|x86
512 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Debug|x86.Deploy.0 = Debug|x86
513 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
514 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|Any CPU.Build.0 = Release|Any CPU
515 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|Any CPU.Deploy.0 = Release|Any CPU
516 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|ARM.ActiveCfg = Release|ARM
517 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|ARM.Build.0 = Release|ARM
518 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|ARM.Deploy.0 = Release|ARM
519 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|ARM64.ActiveCfg = Release|ARM64
520 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|ARM64.Build.0 = Release|ARM64
521 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|ARM64.Deploy.0 = Release|ARM64
522 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|iPhone.ActiveCfg = Release|Any CPU
523 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|iPhone.Build.0 = Release|Any CPU
524 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|iPhone.Deploy.0 = Release|Any CPU
525 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
526 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
527 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
528 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|x64.ActiveCfg = Release|x64
529 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|x64.Build.0 = Release|x64
530 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|x64.Deploy.0 = Release|x64
531 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|x86.ActiveCfg = Release|x86
532 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|x86.Build.0 = Release|x86
533 | {18BF7E9A-D417-4673-9CF2-D23C130036E6}.Release|x86.Deploy.0 = Release|x86
534 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
535 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
536 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
537 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
538 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU
539 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU
540 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
541 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
542 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
543 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
544 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
545 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
546 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
547 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
548 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
549 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|Any CPU.Build.0 = Debug|Any CPU
550 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|ARM.ActiveCfg = Debug|Any CPU
551 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|ARM.Build.0 = Debug|Any CPU
552 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|ARM64.ActiveCfg = Debug|Any CPU
553 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|ARM64.Build.0 = Debug|Any CPU
554 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
555 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|iPhone.Build.0 = Debug|Any CPU
556 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
557 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
558 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|x64.ActiveCfg = Debug|Any CPU
559 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|x64.Build.0 = Debug|Any CPU
560 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|x86.ActiveCfg = Debug|Any CPU
561 | {3862980D-169C-4736-89CC-8744D15F3CFE}.AppStore|x86.Build.0 = Debug|Any CPU
562 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
563 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
564 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|ARM.ActiveCfg = Debug|Any CPU
565 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|ARM.Build.0 = Debug|Any CPU
566 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|ARM64.ActiveCfg = Debug|Any CPU
567 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|ARM64.Build.0 = Debug|Any CPU
568 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|iPhone.ActiveCfg = Debug|Any CPU
569 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|iPhone.Build.0 = Debug|Any CPU
570 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
571 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
572 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|x64.ActiveCfg = Debug|Any CPU
573 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|x64.Build.0 = Debug|Any CPU
574 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|x86.ActiveCfg = Debug|Any CPU
575 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Debug|x86.Build.0 = Debug|Any CPU
576 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
577 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|Any CPU.Build.0 = Release|Any CPU
578 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|ARM.ActiveCfg = Release|Any CPU
579 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|ARM.Build.0 = Release|Any CPU
580 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|ARM64.ActiveCfg = Release|Any CPU
581 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|ARM64.Build.0 = Release|Any CPU
582 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|iPhone.ActiveCfg = Release|Any CPU
583 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|iPhone.Build.0 = Release|Any CPU
584 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
585 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
586 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|x64.ActiveCfg = Release|Any CPU
587 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|x64.Build.0 = Release|Any CPU
588 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|x86.ActiveCfg = Release|Any CPU
589 | {3862980D-169C-4736-89CC-8744D15F3CFE}.Release|x86.Build.0 = Release|Any CPU
590 | EndGlobalSection
591 | GlobalSection(SolutionProperties) = preSolution
592 | HideSolutionNode = FALSE
593 | EndGlobalSection
594 | GlobalSection(NestedProjects) = preSolution
595 | {ECE91EB2-2DD8-41F7-BE7F-FB57484807B1} = {3B434268-93DE-49AD-83B0-069B50CB6891}
596 | {EE74B884-6E2B-4D73-B5E3-B2C22BF4B2FF} = {3B434268-93DE-49AD-83B0-069B50CB6891}
597 | {9A511A00-B27F-42FC-B398-5ABE4D60C2E1} = {3120DFA2-0946-4259-833C-7A704CF00ECC}
598 | {83D719E9-3D7B-4266-BE47-0FDEB92FECCB} = {3120DFA2-0946-4259-833C-7A704CF00ECC}
599 | {F70F519C-49D8-4178-B05B-C4A0391D7C91} = {B3A6F801-0997-4EAE-8F7C-41D90B224B61}
600 | {A2182B4A-A700-47BE-8905-65E8C258B87E} = {3B434268-93DE-49AD-83B0-069B50CB6891}
601 | {EBAB995B-ABCF-488A-A3FA-726F99CFC9A2} = {B3A6F801-0997-4EAE-8F7C-41D90B224B61}
602 | {18BF7E9A-D417-4673-9CF2-D23C130036E6} = {3120DFA2-0946-4259-833C-7A704CF00ECC}
603 | {3862980D-169C-4736-89CC-8744D15F3CFE} = {4175E5A0-1B5A-47E4-A9EA-0FC421148938}
604 | EndGlobalSection
605 | GlobalSection(ExtensibilityGlobals) = postSolution
606 | SolutionGuid = {19215C22-DBE9-4567-A4E4-FCBCDED21E1A}
607 | EndGlobalSection
608 | EndGlobal
609 |
--------------------------------------------------------------------------------