├── .gitignore ├── 01-Core ├── Mobile.Core │ ├── Enumerations │ │ └── ErrorType.cs │ ├── Interfaces │ │ ├── Entities │ │ │ ├── IEntityBase.cs │ │ │ └── IUser.cs │ │ ├── Models │ │ │ └── IError.cs │ │ └── Services │ │ │ └── Database │ │ │ ├── IServiceBase.cs │ │ │ └── IUserService.cs │ ├── Mobile.Core.csproj │ ├── Models │ │ ├── Error.cs │ │ ├── KeyStoreModel.cs │ │ └── User.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── Mobile.Services.Http │ ├── Mobile.Services.Http.csproj │ └── Properties │ │ └── AssemblyInfo.cs ├── Mobile.Services.Realm │ ├── Entities │ │ └── User.cs │ ├── FodyWeavers.xml │ ├── Interfaces │ │ └── IRepositoryService.cs │ ├── Mobile.Services.Realm.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Services │ │ ├── RepositoryService.cs │ │ ├── ServiceBase.cs │ │ └── UserService.cs │ └── packages.config └── Mobile.ViewModels │ ├── App.cs │ ├── AppColors.cs │ ├── AppSizes.cs │ ├── AppText.cs │ ├── Logger.cs │ ├── Mobile.ViewModels.csproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── ViewModels │ ├── BaseViewModel.cs │ ├── HomeViewModel.cs │ └── LoginViewModel.cs │ └── packages.config ├── 02-Presentation ├── Mobile.Android │ ├── Assets │ │ └── AboutAssets.txt │ ├── Bootstrap │ │ └── ColorPluginBootstrap.cs │ ├── FodyWeavers.xml │ ├── MainActivity.cs │ ├── Mobile.Android.csproj │ ├── Mvx │ │ ├── DebugTrace.cs │ │ ├── LinkerPleaseInclude.cs │ │ └── Setup.cs │ ├── Properties │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── Resource.designer.cs │ │ ├── layout │ │ │ ├── HomeLayout.axml │ │ │ └── LoginLayout.axml │ │ └── values │ │ │ └── Strings.xml │ ├── Views │ │ ├── BaseView.cs │ │ ├── HomeView.cs │ │ ├── LoginView.cs │ │ └── LoginView.presenter.cs │ └── packages.config ├── Mobile.Svg │ ├── Mobile.Svg.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SVGImages.cs │ └── avatar.svg └── Mobile.iOS │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Bootstrap │ └── ColorPluginBootstrap.cs │ ├── Delegates │ ├── AppDelegate.cs │ └── ImagePickerDelegate.cs │ ├── Entitlements.plist │ ├── Extensions │ ├── NSDateExtensions.cs │ ├── NSObjectExtensions.cs │ ├── ObjectExtensions.cs │ ├── UIExtensions.cs │ └── ViewControllerExtensions.cs │ ├── FodyWeavers.xml │ ├── Info.plist │ ├── Main.cs │ ├── Mobile.iOS.csproj │ ├── Mvx │ ├── DebugTrace.cs │ ├── LinkerPleaseInclude.cs │ └── Setup.cs │ ├── Storyboards │ └── LaunchScreen.storyboard │ ├── TableSources │ └── UsersTableSource.cs │ ├── Utilities │ ├── AppColors.cs │ ├── ImagePickerHelper.cs │ ├── KeychainHelper.cs │ ├── ReachabilityHelper.cs │ ├── SurroundingSubviews.cs │ └── UIUtilities.cs │ ├── ViewControllers │ ├── Base │ │ ├── BaseScrollViewController.cs │ │ └── BaseViewController.cs │ ├── HomeViewController.cs │ ├── HomeViewController.layout.cs │ ├── HomeViewController.presenter.cs │ ├── LoginVIewController.presenter.cs │ ├── LoginViewController.cs │ └── LoginViewController.layout.cs │ ├── Views │ └── Cells │ │ ├── UserCell.cs │ │ ├── UserCell.layout.cs │ │ └── UserCell.presenter.cs │ └── packages.config ├── 03-Tests ├── Mobile.ViewModels.Tests.Android │ ├── Assets │ │ └── AboutAssets.txt │ ├── FodyWeavers.xml │ ├── MainActivity.cs │ ├── Mobile.ViewModels.Tests.Android.csproj │ ├── Properties │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── Resource.designer.cs │ │ ├── mipmap-hdpi │ │ │ └── Icon.png │ │ ├── mipmap-mdpi │ │ │ └── Icon.png │ │ ├── mipmap-xhdpi │ │ │ └── Icon.png │ │ ├── mipmap-xxhdpi │ │ │ └── Icon.png │ │ ├── mipmap-xxxhdpi │ │ │ └── Icon.png │ │ └── values │ │ │ └── Strings.xml │ └── packages.config ├── Mobile.ViewModels.Tests.Shared │ ├── Integration │ │ ├── LoginViewModelTest.cs │ │ └── ViewModelTestBase.cs │ ├── Mobile.ViewModels.Tests.Shared.projitems │ ├── Mobile.ViewModels.Tests.Shared.shproj │ └── Mocks │ │ ├── DisposableMock.cs │ │ ├── ProgressDialogMock.cs │ │ └── UserDialogsMock.cs └── Mobile.ViewModels.Tests.iOS │ ├── Entitlements.plist │ ├── FodyWeavers.xml │ ├── Info.plist │ ├── LaunchScreen.storyboard │ ├── Main.cs │ ├── Mobile.ViewModels.Tests.iOS.csproj │ ├── UnitTestAppDelegate.cs │ └── packages.config ├── CNAME ├── README.md ├── Tools └── RealmWeaver.Fody.dll └── Xamarin-Architecture.sln /.gitignore: -------------------------------------------------------------------------------- 1 | # Autosave files 2 | *~ 3 | 4 | # build 5 | [Oo]bj/ 6 | [Bb]in/ 7 | packages/ 8 | TestResults/ 9 | 10 | # globs 11 | Makefile.in 12 | *.DS_Store 13 | *.sln.cache 14 | *.suo 15 | *.cache 16 | *.pidb 17 | *.userprefs 18 | *.usertasks 19 | config.log 20 | config.make 21 | config.status 22 | aclocal.m4 23 | install-sh 24 | autom4te.cache/ 25 | *.user 26 | *.tar.gz 27 | tarballs/ 28 | test-results/ 29 | Thumbs.db 30 | 31 | # Mac bundle stuff 32 | *.dmg 33 | *.app 34 | 35 | # resharper 36 | *_Resharper.* 37 | *.Resharper 38 | 39 | # dotCover 40 | *.dotCover 41 | 42 | TestResult\.xml 43 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Enumerations/ErrorType.cs: -------------------------------------------------------------------------------- 1 | namespace Mobile.Core.Enumerations 2 | { 3 | public enum ErrorType 4 | { 5 | Error, 6 | ValidationError 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Interfaces/Entities/IEntityBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Mobile.Core.Interfaces.Entities 4 | { 5 | public interface IEntityBase 6 | { 7 | string CreatedBy { get; set; } 8 | DateTimeOffset? CreatedOn { get; set; } 9 | string DeletedBy { get; set; } 10 | DateTimeOffset? DeletedOn { get; set; } 11 | string Id { get; set; } 12 | string UpdatedBy { get; set; } 13 | DateTimeOffset? UpdatedOn { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Interfaces/Entities/IUser.cs: -------------------------------------------------------------------------------- 1 | namespace Mobile.Core.Interfaces.Entities 2 | { 3 | public interface IUser : IEntityBase 4 | { 5 | string Email { get; set; } 6 | string FirstName { get; set; } 7 | string LastName { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Interfaces/Models/IError.cs: -------------------------------------------------------------------------------- 1 | using Mobile.Core.Enumerations; 2 | 3 | namespace Mobile.Core.Interfaces.Models 4 | { 5 | public interface IError 6 | { 7 | ErrorType ErrorType { get; set; } 8 | string Key { get; set; } 9 | string Message { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Interfaces/Services/Database/IServiceBase.cs: -------------------------------------------------------------------------------- 1 | using Mobile.Core.Interfaces.Entities; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | 5 | namespace Mobile.Core.Interfaces.Services.Database 6 | { 7 | public interface IServiceBase 8 | { 9 | IQueryable GetAll(bool includeDeleted = false); 10 | IEntityBase GetById(string id); 11 | void Save(IEntityBase entity); 12 | void Delete(string id, bool isSoft = true); 13 | void DeleteAll(bool isSoft = true); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Interfaces/Services/Database/IUserService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Mobile.Core.Interfaces.Entities; 3 | using Mobile.Core.Models; 4 | 5 | namespace Mobile.Core.Interfaces.Services.Database 6 | { 7 | public interface IUserService 8 | { 9 | void Delete(string id, bool isSoft = true); 10 | void DeleteAll(bool isSoft = true); 11 | List GetAll(bool includeDeleted = false); 12 | User GetByEmail(string email); 13 | void Save(User user); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Mobile.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {0969D6C0-A3C3-4D2C-9D06-582E08BD1323} 7 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | true 9 | Library 10 | Mobile.Core 11 | Mobile.Core 12 | v4.5 13 | Profile111 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | 24 | 25 | true 26 | bin\Release 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Models/Error.cs: -------------------------------------------------------------------------------- 1 | using Mobile.Core.Enumerations; 2 | using Mobile.Core.Interfaces.Models; 3 | 4 | namespace Mobile.Core.Models 5 | { 6 | public class Error : IError 7 | { 8 | public ErrorType ErrorType { get; set; } 9 | public string Key { get; set; } 10 | public string Message { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Models/KeyStoreModel.cs: -------------------------------------------------------------------------------- 1 | namespace Mobile.Core.Models 2 | { 3 | public class KeyStoreModel 4 | { 5 | public string Password { get; set; } 6 | public string Username { get; set; } 7 | public string UserId { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Models/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Mobile.Core.Interfaces.Entities; 3 | 4 | namespace Mobile.Core.Models 5 | { 6 | public class User : IUser 7 | { 8 | public string Email { get; set; } 9 | public string FirstName { get; set; } 10 | public string LastName { get; set; } 11 | public string CreatedBy { get; set; } 12 | public DateTimeOffset? CreatedOn { get; set; } 13 | public string DeletedBy { get; set; } 14 | public DateTimeOffset? DeletedOn { get; set; } 15 | public string Id { get; set; } 16 | public string UpdatedBy { get; set; } 17 | public DateTimeOffset? UpdatedOn { get; set; } 18 | 19 | public string FullName => $"{FirstName} {LastName}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /01-Core/Mobile.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("Mobile.Core")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("(c) Mike Koser")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Http/Mobile.Services.Http.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {B907FBA8-CABF-43B4-A8F9-0D1006E51F47} 7 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | true 9 | Library 10 | Mobile.Services.Http 11 | Mobile.Services.Http 12 | v4.5 13 | Profile111 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | 24 | 25 | true 26 | bin\Release 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | {0969D6C0-A3C3-4D2C-9D06-582E08BD1323} 36 | Mobile.Core 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Http/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("Services.RestSharp")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("(c) Mike Koser")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using Mobile.Core.Interfaces.Entities; 2 | using Realms; 3 | using System; 4 | 5 | namespace Mobile.Services.Realm 6 | { 7 | public class User : RealmObject, IUser 8 | { 9 | public string CreatedBy { get; set; } 10 | public DateTimeOffset? CreatedOn { get; set; } 11 | public string DeletedBy { get; set; } 12 | public DateTimeOffset? DeletedOn { get; set; } 13 | public string Email { get; set; } 14 | public string FirstName { get; set; } 15 | [PrimaryKey] 16 | public string Id { get; set; } 17 | public string LastName { get; set; } 18 | public string UpdatedBy { get; set; } 19 | public DateTimeOffset? UpdatedOn { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Interfaces/IRepositoryService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Mobile.Core.Interfaces.Entities; 5 | using Realms; 6 | 7 | namespace Mobile.Services.Realm.Interfaces 8 | { 9 | public interface IRepositoryService : IDisposable 10 | { 11 | void ConfigureInstance(); 12 | void AddOrUpdate(T item) where T : RealmObject; 13 | void AddOrUpdate(IEnumerable items) where T : RealmObject; 14 | void Write(Action writeAction); 15 | T Query(long id) where T : RealmObject; 16 | T Query(string id) where T : RealmObject; 17 | RealmObject Query(string className, long id); 18 | RealmObject Query(string className, string id); 19 | IQueryable QueryAll(string className); 20 | IQueryable QueryAll(bool includeDeleted = false) where T : RealmObject, IEntityBase; 21 | void RemoveAll(); 22 | void RemoveAll(string className); 23 | void RemoveAll() where T : RealmObject; 24 | void RemoveAll(bool isSoft = true) where T : RealmObject, IEntityBase; 25 | void Remove(T item) where T : RealmObject; 26 | void Remove(T item, bool isSoft = true) where T : RealmObject, IEntityBase; 27 | void RemoveRange(IQueryable range) where T : RealmObject; 28 | void Refresh(); 29 | void DeleteRealm(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Mobile.Services.Realm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {711CE704-A550-48F9-8C12-6565D1E540C6} 7 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | true 9 | Library 10 | Mobile.Services.Realm 11 | Mobile.Services.Realm 12 | v4.5 13 | Profile111 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | 24 | 25 | true 26 | bin\Release 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ..\..\packages\Realm.DataBinding.1.1.0\lib\netstandard1.0\Realm.DataBinding.dll 45 | 46 | 47 | ..\..\packages\Realm.Database.1.5.0\lib\portable-net45+sl5+wp8+wpa81+win8+monoandroid+Xamarin.iOS10+monotouch+Xamarin.Mac\Realm.dll 48 | 49 | 50 | ..\..\packages\Realm.1.5.0\lib\portable-net45+sl5+wp8+wpa81+win8+monoandroid+Xamarin.iOS10+monotouch+Xamarin.Mac\Realm.Sync.dll 51 | 52 | 53 | ..\..\packages\System.ComponentModel.Primitives.4.3.0\lib\netstandard1.0\System.ComponentModel.Primitives.dll 54 | 55 | 56 | ..\..\packages\System.ComponentModel.TypeConverter.4.3.0\lib\netstandard1.0\System.ComponentModel.TypeConverter.dll 57 | 58 | 59 | ..\..\packages\AutoMapper.6.1.1\lib\netstandard1.1\AutoMapper.dll 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | {0969D6C0-A3C3-4D2C-9D06-582E08BD1323} 70 | Mobile.Core 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("Services.Realm")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("(c) Mike Koser")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Services/RepositoryService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Mobile.Core.Interfaces.Entities; 5 | using Mobile.Services.Realm.Interfaces; 6 | using Realms; 7 | 8 | namespace Mobile.Services.Realm.Services 9 | { 10 | public class RepositoryService : IRepositoryService 11 | { 12 | Realms.Realm _realm; 13 | readonly RealmConfiguration _config; 14 | 15 | public RepositoryService() 16 | { 17 | } 18 | 19 | public RepositoryService(RealmConfiguration config) 20 | { 21 | _config = config; 22 | } 23 | 24 | public void ConfigureInstance() 25 | { 26 | if (_config != null) 27 | { 28 | _realm = Realms.Realm.GetInstance(_config); 29 | } 30 | else 31 | { 32 | _realm = Realms.Realm.GetInstance(); 33 | } 34 | _realm.Error += OnRealmError; 35 | } 36 | 37 | public void AddOrUpdate(T item) where T : RealmObject 38 | { 39 | ConfigureInstance(); 40 | _realm.WriteAsync(tempRealm => 41 | { 42 | tempRealm.Add(item, true); 43 | }); 44 | } 45 | 46 | public void AddOrUpdate(IEnumerable items) where T : RealmObject 47 | { 48 | if (items.Count() == 0) 49 | return; 50 | 51 | ConfigureInstance(); 52 | _realm.Write(() => 53 | { 54 | foreach (var item in items) 55 | { 56 | _realm.Add(item, true); 57 | } 58 | }); 59 | } 60 | 61 | public void Write(Action writeAction) 62 | { 63 | ConfigureInstance(); 64 | _realm.Write(writeAction); 65 | } 66 | 67 | public T Query(long id) where T : RealmObject 68 | { 69 | ConfigureInstance(); 70 | return _realm.Find(id); 71 | } 72 | 73 | public T Query(string id) where T : RealmObject 74 | { 75 | if (string.IsNullOrEmpty(id)) 76 | { 77 | return null; 78 | } 79 | ConfigureInstance(); 80 | return _realm.Find(id); 81 | } 82 | 83 | public RealmObject Query(string className, long id) 84 | { 85 | ConfigureInstance(); 86 | return _realm.Find(className, id); 87 | } 88 | 89 | public RealmObject Query(string className, string id) 90 | { 91 | if (string.IsNullOrEmpty(id)) 92 | { 93 | return null; 94 | } 95 | ConfigureInstance(); 96 | return _realm.Find(className, id); 97 | } 98 | 99 | public IQueryable QueryAll(string className) 100 | { 101 | ConfigureInstance(); 102 | return _realm.All(className); 103 | } 104 | 105 | public IQueryable QueryAll(bool includeDeleted = false) where T : RealmObject, IEntityBase 106 | { 107 | ConfigureInstance(); 108 | if(includeDeleted) 109 | { 110 | return _realm.All(); 111 | } 112 | return _realm.All().Where(e => e.DeletedOn == null); 113 | } 114 | 115 | public void RemoveAll() 116 | { 117 | ConfigureInstance(); 118 | _realm.Write(() => { _realm.RemoveAll(); }); 119 | } 120 | 121 | public void RemoveAll(string className) 122 | { 123 | ConfigureInstance(); 124 | _realm.Write(() => { _realm.RemoveAll(className); }); 125 | } 126 | 127 | public void RemoveAll() where T : RealmObject 128 | { 129 | ConfigureInstance(); 130 | _realm.Write(() => { _realm.RemoveAll(); }); 131 | } 132 | 133 | public void RemoveAll(bool isSoft = true) where T : RealmObject, IEntityBase 134 | { 135 | ConfigureInstance(); 136 | if(isSoft) { 137 | var items = QueryAll(); 138 | _realm.Write(() => { 139 | foreach(var i in items) 140 | { 141 | i.DeletedOn = DateTime.Now; 142 | _realm.Add(i, true); 143 | } 144 | }); 145 | } 146 | else 147 | { 148 | RemoveAll(); 149 | } 150 | } 151 | 152 | public void Remove(T item) where T : RealmObject 153 | { 154 | ConfigureInstance(); 155 | _realm.Write(() => { _realm.Remove(item); }); 156 | } 157 | 158 | public void Remove(T item, bool isSoft = true) where T : RealmObject, IEntityBase 159 | { 160 | ConfigureInstance(); 161 | if(isSoft) 162 | { 163 | _realm.Write(() => { 164 | item.DeletedOn = DateTime.Now; 165 | }); 166 | } 167 | else 168 | { 169 | _realm.Write(() => { _realm.Remove(item); }); 170 | } 171 | } 172 | 173 | public void RemoveRange(IQueryable range) where T : RealmObject 174 | { 175 | ConfigureInstance(); 176 | _realm.Write(() => { _realm.RemoveRange(range); }); 177 | } 178 | 179 | public void Refresh() 180 | { 181 | ConfigureInstance(); 182 | _realm.Refresh(); 183 | } 184 | 185 | public void Dispose() 186 | { 187 | ConfigureInstance(); 188 | _realm.Dispose(); 189 | } 190 | 191 | public void DeleteRealm() 192 | { 193 | ConfigureInstance(); 194 | Realms.Realm.DeleteRealm(_realm.Config); 195 | } 196 | 197 | private void OnRealmError(object sender, ErrorEventArgs args) 198 | { 199 | // TODO Add analytics here 200 | } 201 | 202 | public void Dispose(bool disposing) 203 | { 204 | if (disposing) 205 | { 206 | ConfigureInstance(); 207 | _realm.Error -= OnRealmError; 208 | } 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Services/ServiceBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using AutoMapper; 4 | using Mobile.Core.Interfaces.Entities; 5 | using Mobile.Core.Interfaces.Services.Database; 6 | using Mobile.Services.Realm.Services; 7 | 8 | namespace Mobile.Services.Realm 9 | { 10 | public abstract class ServiceBase 11 | { 12 | #region Protected Members 13 | 14 | protected readonly IMapper _mappingEngine; 15 | protected readonly RepositoryService _repository; 16 | 17 | #endregion Protected Members 18 | 19 | #region Constructor 20 | 21 | protected ServiceBase(IMapper mappingEngine) 22 | { 23 | _mappingEngine = mappingEngine; 24 | _repository = new RepositoryService(); 25 | } 26 | 27 | #endregion Constructor 28 | 29 | #region Protected Methods 30 | 31 | protected void Delete(string id, bool isSoft = true) 32 | where TRealm : Realms.RealmObject, IEntityBase 33 | { 34 | var user = _repository.Query(id); 35 | _repository.Remove(user, isSoft); 36 | } 37 | 38 | protected void DeleteAll(bool isSoft = true) 39 | where TRealm : Realms.RealmObject, IEntityBase 40 | { 41 | _repository.RemoveAll(isSoft); 42 | } 43 | 44 | protected IQueryable GetAll(bool includeDeleted = false) 45 | where TModel : IEntityBase 46 | where TRealm : Realms.RealmObject, IEntityBase 47 | { 48 | var models = new List(); 49 | var realmEntities = _repository.QueryAll(includeDeleted); 50 | if (realmEntities == null) 51 | { 52 | return models.AsQueryable(); 53 | } 54 | foreach (var e in realmEntities) 55 | { 56 | models.Add(_mappingEngine.Map(e)); 57 | } 58 | return models.AsQueryable(); 59 | } 60 | 61 | protected IEntityBase GetById(string id) 62 | where TRealm : Realms.RealmObject, IEntityBase 63 | where TModel : IEntityBase 64 | { 65 | var realmEntity = _repository.Query(id); 66 | return _mappingEngine.Map(realmEntity); 67 | } 68 | 69 | protected void Save(IEntityBase entity) 70 | where TRealm : Realms.RealmObject, IEntityBase 71 | { 72 | var realmEntity = _mappingEngine.Map(entity); 73 | _repository.AddOrUpdate(realmEntity); 74 | } 75 | 76 | #endregion Protected Methods 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/Services/UserService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using AutoMapper; 4 | using Mobile.Core.Interfaces.Services.Database; 5 | 6 | namespace Mobile.Services.Realm 7 | { 8 | public class UserService : ServiceBase, IUserService 9 | { 10 | #region Constructor 11 | 12 | public UserService(IMapper mappingEngine) : base(mappingEngine) 13 | { 14 | } 15 | 16 | #endregion Constructor 17 | 18 | #region IUserService Implementation 19 | 20 | public void Delete(string id, bool isSoft = true) 21 | { 22 | Delete(id, isSoft); 23 | } 24 | 25 | public void DeleteAll(bool isSoft = true) 26 | { 27 | DeleteAll(); 28 | } 29 | 30 | public List GetAll(bool includeDeleted = false) 31 | { 32 | var users = GetAll(includeDeleted); 33 | return users.ToList(); 34 | } 35 | 36 | public Core.Models.User GetByEmail(string email) 37 | { 38 | var realmUser = _repository.QueryAll().Where(u => u.Email == email).FirstOrDefault(); 39 | return _mappingEngine.Map(realmUser); 40 | } 41 | 42 | public void Save(Core.Models.User entity) 43 | { 44 | Save(entity); 45 | } 46 | 47 | #endregion IUserService Implementation 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /01-Core/Mobile.Services.Realm/packages.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/App.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Acr.UserDialogs; 3 | using AutoMapper; 4 | using Mobile.Services.Realm; 5 | using MvvmCross.Platform; 6 | using MvvmCross.Platform.IoC; 7 | using Splat; 8 | 9 | namespace Mobile.ViewModels 10 | { 11 | public class App : MvvmCross.Core.ViewModels.MvxApplication 12 | { 13 | public override void Initialize() 14 | { 15 | // Initialize mappings 16 | InitializeMappings(); 17 | // Register AutoMapper 18 | Mvx.RegisterSingleton(() => Mapper.Instance); 19 | 20 | // Register Realm Services 21 | var assembly = typeof(Mobile.Services.Realm.Services.RepositoryService).GetTypeInfo().Assembly; 22 | assembly.CreatableTypes() 23 | .InNamespace("Mobile.Services.Realm") 24 | .EndingWith("Service") 25 | .AsInterfaces() 26 | .RegisterAsSingleton(); 27 | 28 | // Register Dialogs 29 | Mvx.RegisterSingleton(() => UserDialogs.Instance); 30 | Locator.CurrentMutable.RegisterConstant(new Logger(), typeof(ILogger)); 31 | 32 | // Register 33 | RegisterAppStart(); 34 | } 35 | 36 | private void InitializeMappings() 37 | { 38 | Mapper.Initialize(cfg => { 39 | cfg.CreateMap(); 40 | cfg.CreateMap().ReverseMap(); 41 | }); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/AppColors.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MvvmCross.Platform.UI; 3 | 4 | namespace Mobile.ViewModels 5 | { 6 | public static class AppColors 7 | { 8 | public static MvxColor Gray => new MvxColor(191, 191, 191); 9 | public static MvxColor Primary => new MvxColor(255, 87, 51); 10 | public static MvxColor Secondary => new MvxColor(138, 124, 255); 11 | public static MvxColor White => new MvxColor(255, 255, 255); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/AppSizes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Mobile.ViewModels 3 | { 4 | public static class AppSizes 5 | { 6 | public const float FIELD_HEIGHT = 30f; 7 | public const float MARGIN = 20f; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/AppText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Mobile.ViewModels 3 | { 4 | public static class AppText 5 | { 6 | public const string EMAIL = "Email"; 7 | public const string FIRST_NAME = "First Name"; 8 | public const string LAST_NAME = "Last Name"; 9 | public const string LOGIN = "Login"; 10 | public const string LOGIN_SUCCESS = "Login Successful!"; 11 | public const string NATIVE_COLOR = "NativeColor"; 12 | public const string PASSWORD = "Password"; 13 | public const string USERNAME = "Username"; 14 | public const string USERS_LIST = "Users"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Splat; 3 | 4 | namespace Mobile.ViewModels 5 | { 6 | public class Logger : ILogger 7 | { 8 | public LogLevel Level { get; set; } = LogLevel.Debug; 9 | 10 | public void Write([Localizable(false)] string message, LogLevel logLevel) 11 | { 12 | System.Diagnostics.Debug.WriteLine(message); 13 | this.WriteCallCount = this.WriteCallCount + 1; 14 | } 15 | 16 | public int WriteCallCount { get; private set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/Mobile.ViewModels.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {47998622-D2A8-4682-A4C9-138A4D4E270E} 7 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | true 9 | Library 10 | Mobile.ViewModels 11 | Mobile.ViewModels 12 | v4.5 13 | Profile111 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | 24 | 25 | true 26 | bin\Release 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ..\..\packages\Splat.2.0.0\lib\netstandard1.1\Splat.dll 44 | 45 | 46 | ..\..\packages\Acr.UserDialogs.6.5.1\lib\netstandard1.1\Acr.UserDialogs.dll 47 | 48 | 49 | ..\..\packages\Acr.UserDialogs.6.5.1\lib\netstandard1.1\Acr.UserDialogs.Interface.dll 50 | 51 | 52 | ..\..\packages\System.ComponentModel.Primitives.4.3.0\lib\netstandard1.0\System.ComponentModel.Primitives.dll 53 | 54 | 55 | ..\..\packages\System.ComponentModel.TypeConverter.4.3.0\lib\netstandard1.0\System.ComponentModel.TypeConverter.dll 56 | 57 | 58 | ..\..\packages\AutoMapper.6.1.1\lib\netstandard1.1\AutoMapper.dll 59 | 60 | 61 | ..\..\packages\MvvmCross.Platform.5.1.0\lib\portable-net45+win+wpa81+wp80\MvvmCross.Platform.dll 62 | 63 | 64 | ..\..\packages\MvvmCross.Core.5.1.0\lib\portable-net45+win+wpa81+wp80\MvvmCross.Core.dll 65 | 66 | 67 | ..\..\packages\MvvmCross.Binding.5.1.0\lib\portable-net45+win+wpa81+wp80\MvvmCross.Binding.dll 68 | 69 | 70 | ..\..\packages\MvvmCross.Binding.5.1.0\lib\portable-net45+win+wpa81+wp80\MvvmCross.Localization.dll 71 | 72 | 73 | ..\..\packages\MvvmCross.Plugin.Color.5.1.0\lib\portable-net45+win+wpa81+wp80\MvvmCross.Plugins.Color.dll 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | {711CE704-A550-48F9-8C12-6565D1E540C6} 82 | Mobile.Services.Realm 83 | 84 | 85 | {0969D6C0-A3C3-4D2C-9D06-582E08BD1323} 86 | Mobile.Core 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("Mobile.ViewModels")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/ViewModels/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Mobile.Core.Models; 3 | using MvvmCross.Core.ViewModels; 4 | using MvvmCross.Platform.UI; 5 | 6 | namespace Mobile.ViewModels.ViewModels 7 | { 8 | public class BaseViewModel : MvxViewModel 9 | { 10 | public BaseViewModel() 11 | { 12 | Errors = new List(); 13 | } 14 | 15 | #region Public Properties 16 | 17 | public List Errors { get; set; } 18 | 19 | public bool HasErrors 20 | { 21 | get 22 | { 23 | return Errors?.Count > 0; 24 | } 25 | } 26 | 27 | public MvxColor GrayColor => AppColors.Gray; 28 | 29 | public MvxColor PrimaryColor => AppColors.Primary; 30 | 31 | public MvxColor SecondaryColor => AppColors.Secondary; 32 | 33 | public MvxColor NeutralColor => AppColors.White; 34 | 35 | #endregion Public Properties 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/ViewModels/HomeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Acr.UserDialogs; 5 | using Mobile.Core.Interfaces.Services.Database; 6 | using Mobile.Core.Models; 7 | using MvvmCross.Core.ViewModels; 8 | 9 | namespace Mobile.ViewModels.ViewModels 10 | { 11 | public class HomeViewModel : BaseViewModel, IMvxViewModel 12 | { 13 | #region Member Variables 14 | 15 | readonly IUserDialogs _userDialog; 16 | List _users; 17 | readonly IUserService _userService; 18 | 19 | #endregion Member Variables 20 | 21 | #region Constructors 22 | 23 | public HomeViewModel(IUserService userService, IUserDialogs userDialog) : base() 24 | { 25 | _userDialog = userDialog; 26 | _userService = userService; 27 | } 28 | 29 | #endregion Constructors 30 | 31 | #region Overrides 32 | 33 | public Task Initialize() 34 | { 35 | // Get all users 36 | LoadData(); 37 | return base.Initialize(); 38 | } 39 | 40 | #endregion Overrides 41 | 42 | #region Public Properties 43 | 44 | public List Users 45 | { 46 | get 47 | { 48 | return _users; 49 | } 50 | set 51 | { 52 | SetProperty(ref _users, value); 53 | } 54 | } 55 | 56 | public string TitleText => AppText.USERS_LIST; 57 | 58 | #endregion Public Properties 59 | 60 | #region Public Methods 61 | 62 | #endregion Public Methods 63 | 64 | #region Private Methods 65 | 66 | async Task LoadData() 67 | { 68 | _userDialog.ShowLoading("Loading Users...", MaskType.Black); 69 | await Task.Factory.StartNew(GetUsers); 70 | _userDialog.HideLoading(); 71 | } 72 | 73 | void GetUsers() 74 | { 75 | // Get all the users we just saved to ensure they are persisited in the database. 76 | Users = _userService.GetAll().ToList(); 77 | } 78 | 79 | #endregion Private Methods 80 | } 81 | } -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/ViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Acr.UserDialogs; 5 | using Mobile.Core.Interfaces.Services.Database; 6 | using Mobile.Core.Models; 7 | using MvvmCross.Core.Navigation; 8 | using MvvmCross.Core.ViewModels; 9 | using MvvmCross.Platform.UI; 10 | using Splat; 11 | 12 | namespace Mobile.ViewModels.ViewModels 13 | { 14 | public class LoginViewModel : BaseViewModel, IEnableLogger 15 | { 16 | #region Member Variables 17 | 18 | string _message; 19 | readonly IMvxNavigationService _navigationService; 20 | string _password; 21 | string _username; 22 | readonly IUserDialogs _userDialog; 23 | readonly IUserService _userService; 24 | 25 | #endregion Member Variables 26 | 27 | #region Constructors 28 | 29 | public LoginViewModel(IMvxNavigationService navigationService, IUserService userService, IUserDialogs userDialog) : base() 30 | { 31 | _navigationService = navigationService; 32 | _userDialog = userDialog; 33 | _userService = userService; 34 | } 35 | 36 | #endregion Constructors 37 | 38 | #region Overrides 39 | 40 | public override Task Initialize() 41 | { 42 | this.Log().Info("================ In LoginViewModel Initialize."); 43 | LoadData(); 44 | return base.Initialize(); 45 | } 46 | 47 | #endregion Overrides 48 | 49 | #region Public Properties 50 | 51 | public string LoginButtonText => AppText.LOGIN; 52 | 53 | public IMvxCommand LoginCommand => new MvxCommand(LoginUser); 54 | 55 | public string Message 56 | { 57 | get 58 | { 59 | return _message; 60 | } 61 | set 62 | { 63 | SetProperty(ref _message, value); 64 | } 65 | } 66 | 67 | public string Password 68 | { 69 | get 70 | { 71 | return _password; 72 | } 73 | set 74 | { 75 | SetProperty(ref _password, value); 76 | } 77 | } 78 | 79 | public string PasswordPlaceholderText => AppText.PASSWORD; 80 | 81 | public string Username 82 | { 83 | get 84 | { 85 | return _username; 86 | } 87 | set 88 | { 89 | SetProperty(ref _username, value); 90 | } 91 | } 92 | 93 | public string UsernamePlaceholderText => AppText.USERNAME; 94 | 95 | #endregion Public Properties 96 | 97 | #region Public Methods 98 | 99 | public async Task LoadData() 100 | { 101 | _userDialog.ShowLoading("Processing", MaskType.Black); 102 | await Task.Factory.StartNew(SeedUsers); 103 | _userDialog.HideLoading(); 104 | } 105 | 106 | #endregion Public Methods 107 | 108 | #region Private Methods 109 | 110 | void LoginUser() 111 | { 112 | // TODO: Replace with actual logic 113 | try 114 | { 115 | _userService.Save(new User { 116 | CreatedBy = "Test", 117 | CreatedOn = DateTime.Now, 118 | Email = "test@test.com", 119 | FirstName = "Test", 120 | Id = "2f89db5ae1e04679a22cd48167969a08", 121 | LastName = "User" 122 | }); 123 | var user = _userService.GetByEmail(Username); 124 | if(user == null) 125 | { 126 | AddLoginError(); 127 | _userDialog.Alert("Error", "Login Failed!"); 128 | return; 129 | } 130 | // Navigate to the home view model. 131 | _navigationService.Navigate(); 132 | } 133 | catch(Exception ex) 134 | { 135 | // TODO: Implement logging service 136 | AddLoginError(); 137 | } 138 | } 139 | 140 | /// 141 | /// This method is intended to test/demonstrate the interaction with the database across an async thread. 142 | /// 143 | void SeedUsers() 144 | { 145 | int count = 1; 146 | // Ensure we have 10 users. 147 | while (count < 11) 148 | { 149 | _userService.Save(new User 150 | { 151 | CreatedBy = "Test", 152 | CreatedOn = DateTime.Now, 153 | Email = $"test@test{count.ToString()}.com", 154 | FirstName = "Test", 155 | Id = count.ToString(), 156 | LastName = $"User{count.ToString()}" 157 | }); 158 | count++; 159 | } 160 | // Get all the users we just saved to ensure they are persisited in the database. 161 | var users = _userService.GetAll().ToList(); 162 | 163 | if(users == null || users.Count == 0) 164 | { 165 | return; 166 | } 167 | // Get the first user, and update their information. 168 | var featuredUser = users[0]; 169 | featuredUser.LastName = "Succup"; 170 | featuredUser.Email = "suckup@email.com"; 171 | // Save the changes to the user 172 | _userService.Save(featuredUser); 173 | // Requery the user to ensure that the changes were persisted in the database. 174 | var updatedUser = _userService.GetByEmail(featuredUser.Email); 175 | 176 | Message = $"Join the {users.Count.ToString()} users! Take it from {updatedUser.FirstName} {updatedUser.LastName} 'I love this app!'"; 177 | } 178 | 179 | void AddLoginError() 180 | { 181 | Errors.Add(new Error 182 | { 183 | ErrorType = Core.Enumerations.ErrorType.Error, 184 | Key = "LoginUser", 185 | Message = $"Unable to find a user with the email {Username}." 186 | }); 187 | } 188 | 189 | #endregion Private Methods 190 | } 191 | } -------------------------------------------------------------------------------- /01-Core/Mobile.ViewModels/packages.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with your package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Bootstrap/ColorPluginBootstrap.cs: -------------------------------------------------------------------------------- 1 | using MvvmCross.Platform.Plugins; 2 | 3 | namespace Mobile.Android.Bootstrap 4 | { 5 | public class ColorPluginBootstrap 6 | : MvxPluginBootstrapAction 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Widget; 3 | using Android.OS; 4 | 5 | namespace Mobile.Android 6 | { 7 | [Activity(Label = "Mobile.Android", MainLauncher = true)] 8 | public class MainActivity : Activity 9 | { 10 | protected override void OnCreate(Bundle savedInstanceState) 11 | { 12 | base.OnCreate(savedInstanceState); 13 | 14 | // Set our view from the "main" layout resource 15 | SetContentView(Resource.Layout.Main); 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Mvx/DebugTrace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using MvvmCross.Platform.Platform; 4 | // NOTE: The namespace _must_ be the root namespace, otherwise MVX is not initialized properly. 5 | namespace Mobile.Android 6 | { 7 | public class DebugTrace : IMvxTrace 8 | { 9 | public void Trace(MvxTraceLevel level, string tag, Func message) 10 | { 11 | Debug.WriteLine(tag + ":" + level + ":" + message()); 12 | } 13 | 14 | public void Trace(MvxTraceLevel level, string tag, string message) 15 | { 16 | Debug.WriteLine(tag + ":" + level + ":" + message); 17 | } 18 | 19 | public void Trace(MvxTraceLevel level, string tag, string message, params object[] args) 20 | { 21 | try 22 | { 23 | Debug.WriteLine(tag + ":" + level + ":" + message, args); 24 | } 25 | catch (FormatException) 26 | { 27 | Trace(MvxTraceLevel.Error, tag, "Exception during trace of {0} {1}", level, message); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Mvx/LinkerPleaseInclude.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using System.Windows.Input; 3 | using Android.App; 4 | using Android.Views; 5 | using Android.Widget; 6 | using MvvmCross.Binding.BindingContext; 7 | // NOTE: The namespace _must_ be the root namespace, otherwise MVX is not initialized properly. 8 | namespace Mobile.Android 9 | { 10 | public class LinkerPleaseInclude 11 | { 12 | public void Include(Button button) 13 | { 14 | button.Click += (s, e) => button.Text = button.Text + ""; 15 | } 16 | 17 | public void Include(CheckBox checkBox) 18 | { 19 | checkBox.CheckedChange += (sender, args) => checkBox.Checked = !checkBox.Checked; 20 | } 21 | 22 | public void Include(Switch @switch) 23 | { 24 | @switch.CheckedChange += (sender, args) => @switch.Checked = !@switch.Checked; 25 | } 26 | 27 | public void Include(View view) 28 | { 29 | view.Click += (s, e) => view.ContentDescription = view.ContentDescription + ""; 30 | } 31 | 32 | public void Include(TextView text) 33 | { 34 | text.AfterTextChanged += (sender, args) => text.Text = "" + text.Text; 35 | text.Hint = "" + text.Hint; 36 | } 37 | 38 | public void Include(CheckedTextView text) 39 | { 40 | text.AfterTextChanged += (sender, args) => text.Text = "" + text.Text; 41 | text.Hint = "" + text.Hint; 42 | } 43 | 44 | public void Include(CompoundButton cb) 45 | { 46 | cb.CheckedChange += (sender, args) => cb.Checked = !cb.Checked; 47 | } 48 | 49 | public void Include(SeekBar sb) 50 | { 51 | sb.ProgressChanged += (sender, args) => sb.Progress = sb.Progress + 1; 52 | } 53 | 54 | public void Include(RadioGroup radioGroup) 55 | { 56 | radioGroup.CheckedChange += (sender, args) => radioGroup.Check(args.CheckedId); 57 | } 58 | 59 | public void Include(RadioButton radioButton) 60 | { 61 | radioButton.CheckedChange += (sender, args) => radioButton.Checked = args.IsChecked; 62 | } 63 | 64 | public void Include(RatingBar ratingBar) 65 | { 66 | ratingBar.RatingBarChange += (sender, args) => ratingBar.Rating = 0 + ratingBar.Rating; 67 | } 68 | 69 | public void Include(Activity act) 70 | { 71 | act.Title = act.Title + ""; 72 | } 73 | 74 | public void Include(INotifyCollectionChanged changed) 75 | { 76 | changed.CollectionChanged += (s, e) => { var test = $"{e.Action}{e.NewItems}{e.NewStartingIndex}{e.OldItems}{e.OldStartingIndex}"; }; 77 | } 78 | 79 | public void Include(ICommand command) 80 | { 81 | command.CanExecuteChanged += (s, e) => { if (command.CanExecute(null)) command.Execute(null); }; 82 | } 83 | 84 | public void Include(MvvmCross.Platform.IoC.MvxPropertyInjector injector) 85 | { 86 | injector = new MvvmCross.Platform.IoC.MvxPropertyInjector(); 87 | } 88 | 89 | public void Include(System.ComponentModel.INotifyPropertyChanged changed) 90 | { 91 | changed.PropertyChanged += (sender, e) => 92 | { 93 | var test = e.PropertyName; 94 | }; 95 | } 96 | 97 | public void Include(MvxTaskBasedBindingContext context) 98 | { 99 | context.Dispose(); 100 | var context2 = new MvxTaskBasedBindingContext(); 101 | context2.Dispose(); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Mvx/Setup.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using Mobile.ViewModels; 3 | using MvvmCross.Core.ViewModels; 4 | using MvvmCross.Droid.Platform; 5 | using MvvmCross.Platform.Platform; 6 | // NOTE: The namespace _must_ be the root namespace, otherwise MVX is not initialized properly. 7 | namespace Mobile.Android 8 | { 9 | public class Setup : MvxAndroidSetup 10 | { 11 | public Setup(Context applicationContext) : base(applicationContext) 12 | { 13 | } 14 | 15 | protected override IMvxApplication CreateApp() 16 | { 17 | return new App(); 18 | } 19 | 20 | protected override IMvxTrace CreateDebugTrace() 21 | { 22 | return new DebugTrace(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using Android.App; 4 | 5 | // Information about this assembly is defined by the following attributes. 6 | // Change them to the values specific to your project. 7 | 8 | [assembly: AssemblyTitle("Mobile.Android")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("${AuthorCopyright}")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 20 | 21 | [assembly: AssemblyVersion("1.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.axml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.axml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. 45 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Resources/layout/HomeLayout.axml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 19 | 25 | 31 | 37 | 43 | 49 | -------------------------------------------------------------------------------- /02-Presentation/Mobile.Android/Resources/layout/LoginLayout.axml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 15 | 21 | 27 |