├── .DS_Store ├── .gitattributes ├── .gitignore ├── 75fc04d2-b524-43c2-b7c1-f21230eb7056.mobileprovision ├── 8b50129c-bc44-4eb4-a330-7884c3c8bb63.mobileprovision ├── CloudKeybaord.Cli ├── ConsoleLineReader.cs ├── Program.cs └── Walterlv.CloudKeybaord.Cli.csproj ├── CloudKeyboard.Core ├── Client │ ├── CloudKeyboardReceiver.cs │ ├── CloudKeyboardSender.cs │ ├── DelayRunner.cs │ ├── ExceptionEventArgs.cs │ └── TypingTextEventArgs.cs ├── CloudKeyboard.cs ├── FileConfigurationRepo.cs ├── HostInfo.cs ├── TypingResponse.cs ├── TypingText.cs └── Walterlv.CloudKeyboard.Core.csproj ├── CloudKeyboard.Package ├── Images │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-125.png │ ├── LargeTile.scale-150.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-400.png │ ├── LockScreenLogo.scale-200.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-125.png │ ├── SmallTile.scale-150.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-400.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-125.png │ ├── SplashScreen.scale-150.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-400.png │ ├── Square150x150Logo.scale-100.png │ ├── Square150x150Logo.scale-125.png │ ├── Square150x150Logo.scale-150.png │ ├── Square150x150Logo.scale-200.png │ ├── Square150x150Logo.scale-400.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.scale-100.png │ ├── Square44x44Logo.scale-125.png │ ├── Square44x44Logo.scale-150.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.scale-400.png │ ├── Square44x44Logo.targetsize-16.png │ ├── Square44x44Logo.targetsize-24.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── Square44x44Logo.targetsize-256.png │ ├── Square44x44Logo.targetsize-32.png │ ├── Square44x44Logo.targetsize-48.png │ ├── StoreLogo.backup.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-125.png │ ├── StoreLogo.scale-150.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-400.png │ ├── Wide310x150Logo.scale-100.png │ ├── Wide310x150Logo.scale-125.png │ ├── Wide310x150Logo.scale-150.png │ ├── Wide310x150Logo.scale-200.png │ └── Wide310x150Logo.scale-400.png ├── Package.appxmanifest ├── Walterlv.CloudKeyboard.Package.wapproj ├── icon.afdesign └── icon.png ├── CloudKeyboard.WebApi ├── .config │ └── dotnet-tools.json ├── Controllers │ └── KeyboardController.cs ├── Models │ ├── Keyboard.cs │ ├── KeyboardContext.cs │ ├── TypingChange.cs │ └── TypingText.cs ├── Program.cs ├── Properties │ ├── PublishProfiles │ │ └── FolderProfile.pubxml │ └── launchSettings.json ├── Startup.cs ├── Utils_ │ └── TypingAsyncTracker.cs ├── Walterlv.CloudKeyboard.WebApi.csproj ├── appsettings.Development.json └── appsettings.json ├── CloudKeyboard.Windows ├── App.xaml ├── App.xaml.cs ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png ├── MainPage.xaml ├── MainPage.xaml.cs ├── Package.appxmanifest ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml └── Walterlv.CloudKeyboard.Windows.csproj ├── CloudKeyboard.Wpf ├── App.config ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Program.cs ├── Utils │ └── EmptyStringToVisibilityConverter.cs ├── Walterlv.CloudKeyboard.Wpf.csproj └── configs.fkv ├── CloudKeyboard.Xaml ├── App.xaml ├── App.xaml.cs ├── MainPage.xaml ├── MainPage.xaml.cs └── Walterlv.CloudKeyboard.Xaml.csproj ├── CloudKeyboard.iOS.Extension ├── Entitlements.plist ├── Info.plist ├── KeyboardViewController.cs ├── KeyboardViewController.designer.cs ├── Walterlv.CloudKeyboard.iOS.Extension.csproj └── packages.config ├── CloudKeyboard.iOS ├── AppDelegate.cs ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon1024.png │ │ ├── Icon120.png │ │ ├── Icon152.png │ │ ├── Icon167.png │ │ ├── Icon180.png │ │ ├── Icon20.png │ │ ├── Icon29.png │ │ ├── Icon40.png │ │ ├── Icon58.png │ │ ├── Icon60.png │ │ ├── Icon76.png │ │ ├── Icon80.png │ │ └── Icon87.png ├── Entitlements.plist ├── Info.plist ├── Main.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ ├── Default-568h@2x.png │ ├── Default-Portrait.png │ ├── Default-Portrait@2x.png │ ├── Default.png │ ├── Default@2x.png │ └── LaunchScreen.storyboard └── Walterlv.CloudKeyboard.iOS.csproj ├── README.md └── Walterlv.CloudKeyboard.sln /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/.DS_Store -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 -------------------------------------------------------------------------------- /75fc04d2-b524-43c2-b7c1-f21230eb7056.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/75fc04d2-b524-43c2-b7c1-f21230eb7056.mobileprovision -------------------------------------------------------------------------------- /8b50129c-bc44-4eb4-a330-7884c3c8bb63.mobileprovision: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/8b50129c-bc44-4eb4-a330-7884c3c8bb63.mobileprovision -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.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/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/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.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.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/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.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 | -------------------------------------------------------------------------------- /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.Package/Images/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/LargeTile.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/LargeTile.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/LargeTile.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/LargeTile.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/LargeTile.scale-400.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SmallTile.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SmallTile.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SmallTile.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SmallTile.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SmallTile.scale-400.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/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/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/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/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/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/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/StoreLogo.backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/StoreLogo.backup.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Package/Images/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/Images/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /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.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.Package/icon.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/icon.afdesign -------------------------------------------------------------------------------- /CloudKeyboard.Package/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Package/icon.png -------------------------------------------------------------------------------- /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/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.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 | } -------------------------------------------------------------------------------- /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.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.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.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/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.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.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.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.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/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /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.Windows/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/StoreLogo.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.Windows/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /CloudKeyboard.Windows/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /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.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.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/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /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.Wpf/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CloudKeyboard.Wpf/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /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.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.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.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.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.Wpf/configs.fkv: -------------------------------------------------------------------------------- 1 | Token 2 | walterlv -------------------------------------------------------------------------------- /CloudKeyboard.Xaml/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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.Xaml/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /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.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.iOS.Extension/Entitlements.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /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.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 | -------------------------------------------------------------------------------- /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.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.iOS.Extension/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /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.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.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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/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/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.iOS/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Resources/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Resources/Default-Portrait.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Resources/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Resources/Default-Portrait@2x.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Resources/Default.png -------------------------------------------------------------------------------- /CloudKeyboard.iOS/Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walterlv/Walterlv.CloudKeyboard/3dc8f1ffae4f9ffef10d0ed470c1123966f501e0/CloudKeyboard.iOS/Resources/Default@2x.png -------------------------------------------------------------------------------- /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.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------