├── .gitignore ├── DevsDNA.Application ├── DevsDNA.Application.Tests │ ├── Base │ │ └── BaseTests.cs │ ├── DevsDNA.Application.Tests.csproj │ ├── Extensions │ │ └── ExtensionMethodsString.cs │ ├── Features │ │ ├── News │ │ │ └── NewsDetailParserTest.cs │ │ └── SocialNetwork │ │ │ └── PostTextParserTest.cs │ ├── MockDependencyService │ │ └── MockDependencyService.cs │ └── TestServices │ │ ├── Facebook │ │ ├── FacebookAPIServiceTest.cs │ │ └── FacebookServiceTest.cs │ │ ├── RssFeed │ │ └── RssFeedTests.cs │ │ └── Youtube │ │ ├── YoutubeAPIServiceTest.cs │ │ └── YoutubeServiceTest.cs ├── DevsDNA.Application.sln └── DevsDNA.Application │ ├── DevsDNA.Application.Android │ ├── Assets │ │ ├── AboutAssets.txt │ │ ├── BluePattern.json │ │ ├── BoxToSymbol.json │ │ ├── CenterToLogo.json │ │ ├── Heebo-Black.ttf │ │ ├── Heebo-Regular.ttf │ │ ├── LogoResolve.json │ │ └── loading.json │ ├── DevsDNA.Application.Android.csproj │ ├── Effects │ │ ├── DropShadowEffect.cs │ │ ├── LabelHeightAdjustEffect.cs │ │ ├── LabelShadowEffect.cs │ │ └── PageStatusBarEffect.cs │ ├── GarbageCollector.config │ ├── MainActivity.cs │ ├── Properties │ │ ├── AndroidManifest 2.xml │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Renderers │ │ ├── CarouselAnimatedRenderer.cs │ │ ├── CollectionViewSocialNetworkRenderer.cs │ │ ├── FrameGradientRenderer.cs │ │ ├── ItemsViewOnGlobalLayoutListener.cs │ │ ├── WebviewNewsRenderer │ │ │ ├── DynamicSizeWebViewClient.cs │ │ │ └── WebviewNewsRenderer.cs │ │ └── WebviewYoutubeRenderer │ │ │ ├── FullScreenClient.cs │ │ │ ├── JSBridge.cs │ │ │ ├── JavascriptWebViewClient.cs │ │ │ └── WebviewYoutubeRenderer.cs │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── Resource.designer.cs │ │ ├── drawable-hdpi │ │ │ ├── Thumbs.db │ │ │ ├── close.png │ │ │ ├── close_blue.png │ │ │ ├── facebook.png │ │ │ ├── facebook_white.png │ │ │ ├── ic_launcher_foreground.png │ │ │ ├── instagram_white.png │ │ │ ├── linkedin_white.png │ │ │ ├── logotipo.png │ │ │ ├── phone.png │ │ │ ├── share.png │ │ │ ├── shareColor.png │ │ │ ├── talk.png │ │ │ └── twitter_white.png │ │ ├── drawable-mdpi │ │ │ ├── Thumbs.db │ │ │ ├── close.png │ │ │ ├── close_blue.png │ │ │ ├── facebook.png │ │ │ ├── facebook_white.png │ │ │ ├── ic_launcher_foreground.png │ │ │ ├── instagram_white.png │ │ │ ├── linkedin_white.png │ │ │ ├── logotipo.png │ │ │ ├── phone.png │ │ │ ├── share.png │ │ │ ├── shareColor.png │ │ │ ├── talk.png │ │ │ └── twitter_white.png │ │ ├── drawable-v26 │ │ │ └── launcher.xml │ │ ├── drawable-xhdpi │ │ │ ├── Thumbs.db │ │ │ ├── close.png │ │ │ ├── close_blue.png │ │ │ ├── facebook.png │ │ │ ├── facebook_white.png │ │ │ ├── ic_launcher_foreground.png │ │ │ ├── instagram_white.png │ │ │ ├── linkedin_white.png │ │ │ ├── logotipo.png │ │ │ ├── phone.png │ │ │ ├── share.png │ │ │ ├── shareColor.png │ │ │ ├── talk.png │ │ │ └── twitter_white.png │ │ ├── drawable-xxhdpi │ │ │ ├── Thumbs.db │ │ │ ├── close.png │ │ │ ├── close_blue.png │ │ │ ├── facebook.png │ │ │ ├── facebook_white.png │ │ │ ├── ic_launcher_foreground.png │ │ │ ├── instagram_white.png │ │ │ ├── linkedin_white.png │ │ │ ├── logotipo.png │ │ │ ├── phone.png │ │ │ ├── share.png │ │ │ ├── shareColor.png │ │ │ ├── talk.png │ │ │ └── twitter_white.png │ │ ├── drawable-xxxhdpi │ │ │ ├── Thumbs.db │ │ │ ├── close.png │ │ │ ├── close_blue.png │ │ │ ├── facebook.png │ │ │ ├── facebook_white.png │ │ │ ├── ic_launcher_foreground.png │ │ │ ├── instagram_white.png │ │ │ ├── linkedin_white.png │ │ │ ├── logotipo.png │ │ │ ├── phone.png │ │ │ ├── share.png │ │ │ ├── shareColor.png │ │ │ ├── talk.png │ │ │ └── twitter_white.png │ │ ├── drawable │ │ │ ├── beatriz.png │ │ │ ├── ciani.png │ │ │ ├── ic_notification.png │ │ │ ├── icon.png │ │ │ ├── jorge.png │ │ │ ├── luis.png │ │ │ ├── marco.png │ │ │ ├── notificationSmallIcon.png │ │ │ ├── splashscreen.xml │ │ │ └── yeray.png │ │ ├── layout │ │ │ ├── Tabbar.xml │ │ │ └── Toolbar.xml │ │ └── values │ │ │ ├── colors.xml │ │ │ └── styles.xml │ └── Services │ │ ├── AccessibilityChecker │ │ └── AccessibilityCheckerService.cs │ │ └── Notifications │ │ ├── FirebaseNotificationService.cs │ │ └── NotificationService.cs │ ├── DevsDNA.Application.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 │ ├── DevsDNA.Application.iOS.csproj │ ├── DevsDNA.Application.iOS.sln │ ├── Effects │ │ ├── DropShadowEffect.cs │ │ ├── FixedFrameClippedToBoundsEffect.cs │ │ ├── LabelShadowEffect.cs │ │ └── RemoveBouncesEffect.cs │ ├── Entitlements.plist │ ├── Info.plist │ ├── Main.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Renderers │ │ ├── CarouselAnimatedRenderer.cs │ │ ├── CollectionViewSocialNetworkRenderer.cs │ │ ├── DisableZoomScrollDelegate.cs │ │ ├── FrameGradientRenderer.cs │ │ ├── WebviewNewsRenderer │ │ │ ├── WebviewNewsNavigationDelegate.cs │ │ │ └── WebviewNewsRenderer.cs │ │ └── WebviewYoutubeRenderer │ │ │ └── WebviewYoutubeRenderer.cs │ ├── Resources │ │ ├── BluePattern.json │ │ ├── BoxToSymbol.json │ │ ├── CenterToLogo.json │ │ ├── Heebo-Black.ttf │ │ ├── Heebo-Regular.ttf │ │ ├── LaunchScreen.storyboard │ │ ├── LogoResolve.json │ │ ├── beatriz.png │ │ ├── ciani.png │ │ ├── close.png │ │ ├── close@2x.png │ │ ├── close@3x.png │ │ ├── close_blue.png │ │ ├── close_blue@2x.png │ │ ├── close_blue@3x.png │ │ ├── facebook.png │ │ ├── facebook@2x.png │ │ ├── facebook@3x.png │ │ ├── facebook_white.png │ │ ├── facebook_white@2x.png │ │ ├── facebook_white@3x.png │ │ ├── instagram_white.png │ │ ├── instagram_white@2x.png │ │ ├── instagram_white@3x.png │ │ ├── jorge.png │ │ ├── linkedin_white.png │ │ ├── linkedin_white@2x.png │ │ ├── linkedin_white@3x.png │ │ ├── loading.json │ │ ├── logotipo.png │ │ ├── logotipo@2x.png │ │ ├── logotipo@3x.png │ │ ├── luis.png │ │ ├── marco.png │ │ ├── phone.png │ │ ├── phone@2x.png │ │ ├── phone@3x.png │ │ ├── share.png │ │ ├── share@2x.png │ │ ├── share@3x.png │ │ ├── shareColor.png │ │ ├── shareColor@2x.png │ │ ├── shareColor@3x.png │ │ ├── talk.png │ │ ├── talk@2x.png │ │ ├── talk@3x.png │ │ ├── twitter_white.png │ │ ├── twitter_white@2x.png │ │ ├── twitter_white@3x.png │ │ └── yeray.png │ ├── Services │ │ ├── AccessibilityChecker │ │ │ └── AccessibilityCheckerService.cs │ │ └── Notifications │ │ │ ├── NotificationsService.cs │ │ │ └── UNNotificationsCenterDelegate.cs │ ├── iTunesArtwork │ └── iTunesArtwork@2x │ └── DevsDNA.Application │ ├── App.xaml │ ├── App.xaml.cs │ ├── AssemblyInfo.cs │ ├── Base │ ├── BaseContentPage.cs │ ├── BaseContentView.cs │ └── BaseViewModel.cs │ ├── Common │ ├── GlobalInfo.cs │ └── SettingsKeyValues.cs │ ├── Controls │ ├── ButtonRoundedGradient.xaml │ ├── ButtonRoundedGradient.xaml.cs │ ├── Carousel │ │ ├── CarouselAnimated.cs │ │ ├── CarouselAnimatedScroller.cs │ │ └── ContentViewAnimated.cs │ ├── CarouselViewScrollFixed.cs │ ├── FrameGradient.cs │ └── LabelTypewriter.cs │ ├── DevsDNA.Application.csproj │ ├── Effects │ ├── DropShadowEffect.cs │ ├── FixedFrameClippedToBoundsEffect.cs │ ├── LabelHeightAdjustEffect.cs │ ├── LabelShadowEffect.cs │ ├── PageStatusBarEffect.cs │ └── RemoveBouncesEffect.cs │ ├── Extensions │ └── ExtensionMethodsString.cs │ ├── Features │ ├── AboutUs │ │ ├── AboutUsView.xaml │ │ ├── AboutUsView.xaml.cs │ │ ├── AboutUsViewModel.cs │ │ ├── IWeService.cs │ │ ├── ThunderMateControl.xaml │ │ ├── ThunderMateControl.xaml.cs │ │ ├── ThunderMateModel.cs │ │ └── WeService.cs │ ├── Main │ │ ├── ButtonFan.xaml │ │ ├── ButtonFan.xaml.cs │ │ ├── ITransitionable.cs │ │ ├── MainView.xaml │ │ ├── MainView.xaml.cs │ │ ├── TabButton.xaml │ │ ├── TabButton.xaml.cs │ │ └── TabMain.cs │ ├── News │ │ ├── BlogItemModel.cs │ │ ├── BlogModel.cs │ │ ├── IRssFeedService.cs │ │ ├── NewsCarouselItemView.xaml │ │ ├── NewsCarouselItemView.xaml.cs │ │ ├── NewsDetail │ │ │ ├── HtmlFont.cs │ │ │ ├── NewsDetailParser.cs │ │ │ ├── NewsDetailView.xaml │ │ │ ├── NewsDetailView.xaml.cs │ │ │ ├── NewsDetailViewModel.cs │ │ │ ├── NewsHtmlSettings.cs │ │ │ └── WebviewNews.cs │ │ ├── NewsView.xaml │ │ ├── NewsView.xaml.cs │ │ ├── NewsViewModel.cs │ │ └── RssFeedService.cs │ ├── SocialNetwork │ │ ├── Attachment.cs │ │ ├── AttachmentType.cs │ │ ├── CollectionViewSocialNetwork.cs │ │ ├── Facebook │ │ │ ├── APIModels │ │ │ │ ├── Attachment.cs │ │ │ │ ├── Attachments.cs │ │ │ │ ├── Image.cs │ │ │ │ ├── Media.cs │ │ │ │ ├── PageFeed.cs │ │ │ │ └── Post.cs │ │ │ ├── FacebookService.cs │ │ │ ├── IFacebookAPIService.cs │ │ │ └── IFacebookService.cs │ │ ├── PostControl.cs │ │ ├── PostDetailView.xaml │ │ ├── PostDetailView.xaml.cs │ │ ├── PostLeftControl.xaml │ │ ├── PostLeftControl.xaml.cs │ │ ├── PostModel.cs │ │ ├── PostParser │ │ │ ├── PostSpan.cs │ │ │ ├── PostTextParser.cs │ │ │ └── SpanType.cs │ │ ├── PostRigthControl.xaml │ │ ├── PostRigthControl.xaml.cs │ │ ├── PostsDataTemplateSelector.cs │ │ ├── SocialNetworkView.xaml │ │ ├── SocialNetworkView.xaml.cs │ │ └── SocialNetworkViewModel.cs │ ├── Splash │ │ ├── SplashView.xaml │ │ ├── SplashView.xaml.cs │ │ └── SplashViewModel.cs │ └── Videos │ │ ├── APIModels │ │ ├── Content.cs │ │ ├── Entry.cs │ │ ├── Feed.cs │ │ ├── Link.cs │ │ ├── Media.cs │ │ └── Thumbnail.cs │ │ ├── IYoutubeAPIService.cs │ │ ├── IYoutubeService.cs │ │ ├── VideoCarouselItemView.xaml │ │ ├── VideoCarouselItemView.xaml.cs │ │ ├── VideoDetail │ │ ├── VideoDetailView.xaml │ │ ├── VideoDetailView.xaml.cs │ │ ├── VideoDetailViewModel.cs │ │ └── WebviewYoutube.cs │ │ ├── VideoModel.cs │ │ ├── VideosView.xaml │ │ ├── VideosView.xaml.cs │ │ ├── VideosViewModel.cs │ │ └── YoutubeService.cs │ ├── Fonts │ ├── Heebo-Black.ttf │ ├── Heebo-Bold.ttf │ ├── Heebo-ExtraBold.ttf │ ├── Heebo-Light.ttf │ ├── Heebo-Medium.ttf │ ├── Heebo-Regular.ttf │ ├── Heebo-Thin.ttf │ ├── SpaceMono-Bold.ttf │ └── SpaceMono-Regular.ttf │ ├── Messages │ ├── Orientation.cs │ └── OrientationMessage.cs │ ├── Services │ ├── AccessibilityChecker │ │ └── IAccessibilityCheckerService.cs │ ├── AppLogger │ │ ├── ILogService.cs │ │ └── LogService.cs │ ├── CustomDependencyService.cs │ ├── DataService │ │ ├── DataService.cs │ │ ├── DataType.cs │ │ └── IDataService.cs │ ├── IDependencyService.cs │ ├── Notifications │ │ ├── INotificationManagerService.cs │ │ ├── INotificationService.cs │ │ ├── NotificationManagerService.cs │ │ ├── PushNotificationInfo.cs │ │ └── PushNotificationsType.cs │ └── Track │ │ ├── ITrackService.cs │ │ └── TrackService.cs │ └── Strings │ ├── Strings.Designer.cs │ └── Strings.resx ├── README.md └── images ├── banner.png ├── detailScreenAndroid.jpg ├── detailScreenIOS.png ├── mainScreenAndroid.jpg └── mainScreenIOS.png /.gitignore: -------------------------------------------------------------------------------- 1 | DevsDNA.Application/.vs/ 2 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/obj/ 3 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/bin/ 4 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/obj/ 5 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/bin/ 6 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/obj/ 7 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/bin/ 8 | DevsDNA.Application/DevsDNA.Application.Tests/obj/ 9 | DevsDNA.Application/DevsDNA.Application.Tests/bin/ 10 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/secrets.json 11 | 12 | 13 | *.user 14 | 15 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/._LaunchScreen.storyboard 16 | 17 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Certificates/._DevsDNADev.mobileprovision 18 | 19 | DevsDNA.Application/DevsDNA.Application/.DS_Store 20 | 21 | DevsDNA.Application/.DS_Store 22 | 23 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/.vs/ 24 | 25 | .DS_Store 26 | 27 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/google-services.json 28 | 29 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Certificates/ 30 | 31 | DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Certificate/ 32 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/Base/BaseTests.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.Base 2 | { 3 | using DevsDNA.Application.Services; 4 | using Moq; 5 | using System.Reactive.Disposables; 6 | 7 | public abstract class BaseTests 8 | { 9 | protected MockDependencyService dependencyService; 10 | protected Mock logService; 11 | protected CompositeDisposable disposables; 12 | private object lockTest= new object(); 13 | private bool isInitialized; 14 | 15 | protected BaseTests() 16 | { 17 | lock (lockTest) 18 | { 19 | if (!isInitialized) 20 | { 21 | isInitialized = true; 22 | InitializeBaseMockServices(); 23 | } 24 | } 25 | } 26 | 27 | protected void InitializeBaseMockServices() 28 | { 29 | dependencyService = new MockDependencyService(); 30 | 31 | logService = new Mock(); 32 | dependencyService.Register(logService.Object); 33 | } 34 | 35 | public void ResetBaseMockServices() 36 | { 37 | logService.Reset(); 38 | 39 | disposables?.Dispose(); 40 | disposables = new CompositeDisposable(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/DevsDNA.Application.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 1.0.1 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers; buildtransitive 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/Extensions/ExtensionMethodsString.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.Extensions 2 | { 3 | using DevsDNA.Application.Extensions; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | [TestClass] 7 | public class ExtensionMethodsString 8 | { 9 | [TestMethod] 10 | public void GetImagePathWhenHtmlContainsOneImage() 11 | { 12 | string path = "This html contains a single image".GetPathFromFirstImage(); 13 | 14 | Assert.AreEqual("/image.png", path); 15 | } 16 | 17 | [TestMethod] 18 | public void GetFirstImagePathWhenHtmlContainsTwoImages() 19 | { 20 | string path = "This html contains two images".GetPathFromFirstImage(); 21 | 22 | Assert.AreEqual("/image.png", path); 23 | } 24 | 25 | [TestMethod] 26 | public void ReturnsNullIfHtmlNotContainsImages() 27 | { 28 | string path = "This html does not contains images".GetPathFromFirstImage(); 29 | 30 | Assert.IsNull(path); 31 | } 32 | 33 | [TestMethod] 34 | public void ReturnsNullIfHtmlContainsOneImageWithoutSrc() 35 | { 36 | string path = "This html contains an image but no src".GetPathFromFirstImage(); 37 | 38 | Assert.IsNull(path); 39 | } 40 | 41 | [TestMethod] 42 | public void GetSecondImagePathWhenFirstImageNotContainsSrc() 43 | { 44 | string path = "this html contains two images but only the second has src".GetPathFromFirstImage(); 45 | 46 | Assert.AreEqual("/image.png", path); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/MockDependencyService/MockDependencyService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests 2 | { 3 | using DevsDNA.Application.Services; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | public class MockDependencyService : IDependencyService 9 | { 10 | private readonly IDictionary registeredServices = new Dictionary(); 11 | 12 | public void Register(T implementation) 13 | { 14 | this.registeredServices.Add(typeof(T), implementation); 15 | } 16 | 17 | public T Get() where T : class 18 | { 19 | return (T)this.registeredServices[typeof(T)]; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/TestServices/Facebook/FacebookAPIServiceTest.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.TestServices 2 | { 3 | using DevsDNA.Application.Features.SocialNetwork.Facebook; 4 | using DevsDNA.Application.Helpers; 5 | using DevsDNA.Application.Common; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using Refit; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using System.Reactive.Linq; 11 | 12 | [TestClass] 13 | public class FacebookAPIServiceTest 14 | { 15 | private IFacebookAPIService facebookAPIService; 16 | 17 | [TestInitialize] 18 | public void SetUp() 19 | { 20 | facebookAPIService = RestService.For(SettingsKeyValues.FacebookEndPoint); 21 | } 22 | 23 | [TestMethod] 24 | public async Task GetPageFeed() 25 | { 26 | var pageFeed = await facebookAPIService.GetPageFeed(SettingsKeyValues.FacebookPageId, Secrets.FacebookAccessToken); 27 | 28 | Assert.IsTrue(pageFeed.Posts.Any()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/TestServices/Facebook/FacebookServiceTest.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.TestServices 2 | { 3 | using DevsDNA.Application.Features.SocialNetwork.Facebook; 4 | using DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Moq; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Reactive.Linq; 10 | using System.Threading.Tasks; 11 | 12 | [TestClass] 13 | public class FacebookServiceTest 14 | { 15 | 16 | [TestMethod] 17 | public async Task GetPostsFromPageFeed() 18 | { 19 | var facebookAPIServiceMoq = new Mock(); 20 | facebookAPIServiceMoq.Setup(f => f.GetPageFeed(It.IsAny(), It.IsAny())).Returns(Observable.Return(GivenAPageFeed())); 21 | FacebookService facebookService = new FacebookService(facebookAPIServiceMoq.Object); 22 | 23 | var posts = await facebookService.GetPosts(); 24 | 25 | Assert.AreEqual(2, posts.Count()); 26 | } 27 | 28 | [TestMethod] 29 | public async Task ReturnsNullIfPageFeedIsNull() 30 | { 31 | var facebookAPIServiceMoq = new Mock(); 32 | facebookAPIServiceMoq.Setup(f => f.GetPageFeed(It.IsAny(), It.IsAny())).Returns(Observable.Return(null)); 33 | FacebookService facebookService = new FacebookService(facebookAPIServiceMoq.Object); 34 | 35 | var posts = await facebookService.GetPosts(); 36 | 37 | Assert.IsNull(posts); 38 | } 39 | 40 | private PageFeed GivenAPageFeed() 41 | { 42 | return new PageFeed() 43 | { 44 | Posts = new List() 45 | { 46 | new Post() { Id = "112726127146289_112825800469655", CreatedTime = "2020-06-15T11:22:12+0000", Message = "Dummy message" }, 47 | new Post() { Id = "112222146289_112825800469655", CreatedTime = "2020-06-15T11:20:12+0000", Message = "Other dummy message" } 48 | } 49 | }; 50 | } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/TestServices/RssFeed/RssFeedTests.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.TestServices 2 | { 3 | using DevsDNA.Application.Features.News; 4 | using DevsDNA.Application.Tests.Base; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using System.Reactive.Linq; 7 | using System.Threading.Tasks; 8 | 9 | [TestClass] 10 | public class RssFeedTests : BaseTests 11 | { 12 | private IRssFeedService rssFeedService; 13 | 14 | 15 | [TestInitialize] 16 | public void SetUp() 17 | { 18 | ResetBaseMockServices(); 19 | 20 | rssFeedService = new RssFeedService(dependencyService); 21 | } 22 | 23 | [TestMethod] 24 | public async Task GetSyndicationFeed() 25 | { 26 | BlogModel blog = await rssFeedService.GetBlogModel(); 27 | 28 | Assert.IsNotNull(blog); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/TestServices/Youtube/YoutubeAPIServiceTest.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.TestServices 2 | { 3 | using DevsDNA.Application.Features.Videos; 4 | using DevsDNA.Application.Common; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Refit; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Reactive.Linq; 10 | 11 | [TestClass] 12 | public class YouTubeAPIServiceTest 13 | { 14 | private IYouTubeAPIService youTubeAPIService; 15 | 16 | [TestInitialize] 17 | public void SetUp() 18 | { 19 | youTubeAPIService = RestService.For(SettingsKeyValues.YouTubeEndPoint, new RefitSettings(new XmlContentSerializer())); 20 | } 21 | 22 | [TestMethod] 23 | public async Task GetChannelFeed() 24 | { 25 | var feed = await youTubeAPIService.GetChannelFeed(SettingsKeyValues.YouTubeChannelId); 26 | 27 | Assert.IsTrue(feed.Entries.Any()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application.Tests/TestServices/Youtube/YoutubeServiceTest.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Tests.TestServices 2 | { 3 | using DevsDNA.Application.Features.Videos; 4 | using DevsDNA.Application.Features.Videos.APIModels; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Moq; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Reactive.Linq; 10 | using System.Threading.Tasks; 11 | 12 | [TestClass] 13 | public class YouTubeServiceTest 14 | { 15 | [TestMethod] 16 | public async Task GetVideosFromChannelFeed() 17 | { 18 | var youTubeAPIServiceMoq = new Mock(); 19 | youTubeAPIServiceMoq.Setup(y => y.GetChannelFeed(It.IsAny())).Returns(Observable.Return(GivenAFeed())); 20 | YouTubeService youTubeService = new YouTubeService(youTubeAPIServiceMoq.Object); 21 | 22 | var videos = await youTubeService.GetVideos(); 23 | 24 | Assert.AreEqual(1, videos.Count()); 25 | } 26 | 27 | [TestMethod] 28 | public async Task ReturnsNullIfChannelFeedIsNull() 29 | { 30 | var youTubeAPIServiceMoq = new Mock(); 31 | youTubeAPIServiceMoq.Setup(y => y.GetChannelFeed(It.IsAny())).Returns(Observable.Return(null)); 32 | YouTubeService youTubeService = new YouTubeService(youTubeAPIServiceMoq.Object); 33 | 34 | var videos = await youTubeService.GetVideos(); 35 | 36 | Assert.IsNull(videos); 37 | } 38 | 39 | 40 | 41 | private Feed GivenAFeed() 42 | { 43 | return new Feed() 44 | { 45 | Entries = new List() 46 | { 47 | new Entry(){ 48 | Id = "CLDLDkoJ9fE", 49 | Title = "Dummy title", 50 | Published= "2019-05-22T09:20:48+00:00", 51 | Link = new Link(){ Url = "https://www.youtube.com/watch?v=CLDLDkoJ9fE"}, 52 | Media = new Media(){ Description = "Dummy description", Thumbnail = new Thumbnail(){ Url ="https://i4.ytimg.com/vi/CLCLDkoJ9fE/hqdefault.jpg" }} 53 | } 54 | } 55 | }; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.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 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Assets/Heebo-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Assets/Heebo-Black.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Assets/Heebo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Assets/Heebo-Regular.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Effects/DropShadowEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.Droid.Effects.DropShadowEffect), 2 | nameof(DevsDNA.Application.Droid.Effects.DropShadowEffect))] 3 | namespace DevsDNA.Application.Droid.Effects 4 | { 5 | using System.Linq; 6 | using Xamarin.Forms.Platform.Android; 7 | 8 | public class DropShadowEffect : PlatformEffect 9 | { 10 | protected override void OnAttached() 11 | { 12 | var view = Control ?? Container; 13 | var dropEffect = (Application.Effects.DropShadowEffect)Element.Effects.FirstOrDefault(e => e is Application.Effects.DropShadowEffect); 14 | if (view == null || dropEffect == null) 15 | return; 16 | 17 | view.Elevation = (float)(dropEffect.Offset.X + dropEffect.Offset.Y) / 2f * 5f; 18 | view.SetOutlineAmbientShadowColor(dropEffect.ShadowColor.ToAndroid()); 19 | view.SetOutlineSpotShadowColor(dropEffect.ShadowColor.ToAndroid()); 20 | } 21 | 22 | protected override void OnDetached() 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Effects/LabelHeightAdjustEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.Droid.Effects.LabelHeightAdjustEffect), 2 | nameof(DevsDNA.Application.Droid.Effects.LabelHeightAdjustEffect))] 3 | namespace DevsDNA.Application.Droid.Effects 4 | { 5 | using Android.Widget; 6 | using Java.Lang; 7 | using Xamarin.Forms.Platform.Android; 8 | 9 | public class LabelHeightAdjustEffect : PlatformEffect 10 | { 11 | protected override void OnAttached() 12 | { 13 | if (Control is TextView textView) 14 | { 15 | textView.LayoutChange += TextView_LayoutChange; 16 | } 17 | } 18 | 19 | protected override void OnDetached() 20 | { 21 | if (Control is TextView textView) 22 | { 23 | textView.LayoutChange -= TextView_LayoutChange; 24 | } 25 | } 26 | 27 | private void TextView_LayoutChange(object sender, Android.Views.View.LayoutChangeEventArgs e) 28 | { 29 | if(sender is FormsTextView textView) 30 | { 31 | int maxLines = (int)Math.Floor((double)textView.Height / (double)textView.LineHeight); 32 | textView.SetLines(maxLines); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Effects/LabelShadowEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.Droid.Effects.LabelShadowEffect), 2 | nameof(DevsDNA.Application.Droid.Effects.LabelShadowEffect))] 3 | namespace DevsDNA.Application.Droid.Effects 4 | { 5 | using Android.Widget; 6 | using System.Linq; 7 | using Xamarin.Forms.Platform.Android; 8 | 9 | public class LabelShadowEffect : PlatformEffect 10 | { 11 | protected override void OnAttached() 12 | { 13 | var labelShadowEffect = (Application.Effects.LabelShadowEffect)Element.Effects.FirstOrDefault(e => e is Application.Effects.LabelShadowEffect); 14 | if (Control is TextView textView) 15 | { 16 | textView.SetShadowLayer(1, 1, 1, labelShadowEffect.Color.ToAndroid()); 17 | } 18 | } 19 | 20 | protected override void OnDetached() 21 | { 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Effects/PageStatusBarEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.Droid.Effects.PageStatusBarEffect), 2 | nameof(DevsDNA.Application.Droid.Effects.PageStatusBarEffect))] 3 | namespace DevsDNA.Application.Droid.Effects 4 | { 5 | using Android.Graphics; 6 | using System.Linq; 7 | using Xamarin.Forms.Platform.Android; 8 | 9 | public class PageStatusBarEffect : PlatformEffect 10 | { 11 | Color defaultStatusBarColor; 12 | 13 | protected override void OnAttached() 14 | { 15 | var pageStatusBarEffect = (Application.Effects.PageStatusBarEffect)Element.Effects.FirstOrDefault(e => e is Application.Effects.PageStatusBarEffect); 16 | defaultStatusBarColor = new Color(Xamarin.Essentials.Platform.CurrentActivity.Window.StatusBarColor); 17 | SetStatusBarColor(pageStatusBarEffect.Color.ToAndroid()); 18 | } 19 | 20 | protected override void OnDetached() 21 | { 22 | SetStatusBarColor(defaultStatusBarColor); 23 | } 24 | 25 | private void SetStatusBarColor(Color color) 26 | { 27 | var window = Xamarin.Essentials.Platform.CurrentActivity.Window; 28 | window.AddFlags(Android.Views.WindowManagerFlags.DrawsSystemBarBackgrounds); 29 | window.ClearFlags(Android.Views.WindowManagerFlags.TranslucentStatus); 30 | window.SetStatusBarColor(color); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/GarbageCollector.config: -------------------------------------------------------------------------------- 1 | MONO_GC_PARAMS=nursery-size=64m -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Properties/AndroidManifest 2.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using Android.App; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("DevsDNA.Application.Android")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("DevsDNA.Application.Android")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: ComVisible(false)] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | [assembly: AssemblyVersion("1.0.0.0")] 26 | [assembly: AssemblyFileVersion("1.0.0.0")] 27 | 28 | // Add some common permissions, these can be removed if not needed 29 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)] 30 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] 31 | 32 | [assembly: Xamarin.Forms.ResolutionGroupName(DevsDNA.Application.Common.SettingsKeyValues.ResolutionGroupName)] 33 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/FrameGradientRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Controls.FrameGradient), typeof(DevsDNA.Application.Droid.Renderers.FrameGradientRenderer))] 2 | namespace DevsDNA.Application.Droid.Renderers 3 | { 4 | using Android.Content; 5 | using Android.Graphics.Drawables; 6 | using DevsDNA.Application.Controls; 7 | using Xamarin.Forms; 8 | using Xamarin.Forms.Platform.Android; 9 | 10 | public class FrameGradientRenderer : Xamarin.Forms.Platform.Android.FastRenderers.FrameRenderer 11 | { 12 | private FrameGradient FrameGradient => Element as FrameGradient; 13 | 14 | public FrameGradientRenderer(Context context) : base(context) 15 | { 16 | } 17 | 18 | protected override void OnElementChanged(ElementChangedEventArgs e) 19 | { 20 | base.OnElementChanged(e); 21 | if (e.NewElement != null) 22 | { 23 | SetGradientBackgroundColor(); 24 | } 25 | } 26 | 27 | private void SetGradientBackgroundColor() 28 | { 29 | if (Background is GradientDrawable gradientDrawable) 30 | { 31 | gradientDrawable.SetOrientation(GradientDrawable.Orientation.LeftRight); 32 | gradientDrawable.SetColors(new int[] { FrameGradient.StartColor.ToAndroid(), FrameGradient.EndColor.ToAndroid() }); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/ItemsViewOnGlobalLayoutListener.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Droid.Renderers 2 | { 3 | using Android.Views; 4 | using System; 5 | 6 | class ItemsViewOnGlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener 7 | { 8 | public EventHandler LayoutReady; 9 | public void OnGlobalLayout() 10 | { 11 | LayoutReady?.Invoke(this, new EventArgs()); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/WebviewNewsRenderer/DynamicSizeWebViewClient.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Droid.Renderers 2 | { 3 | using Android.Runtime; 4 | using System; 5 | using Xamarin.Forms.Platform.Android; 6 | 7 | class DynamicSizeWebViewClient : FormsWebViewClient 8 | { 9 | private WebViewRenderer webViewRenderer; 10 | 11 | public DynamicSizeWebViewClient(WebViewRenderer webViewRenderer) 12 | : base(webViewRenderer) 13 | { 14 | this.webViewRenderer = webViewRenderer; 15 | } 16 | 17 | protected DynamicSizeWebViewClient(IntPtr javaReference, JniHandleOwnership transfer) 18 | : base(javaReference,transfer) 19 | { 20 | 21 | } 22 | 23 | public async override void OnPageFinished(Android.Webkit.WebView view, string url) 24 | { 25 | base.OnPageFinished(view, url); 26 | 27 | if (webViewRenderer?.Element == null) 28 | return; 29 | 30 | var contentHeight = await webViewRenderer.Element.EvaluateJavaScriptAsync("document.body.scrollHeight"); 31 | if (double.TryParse(contentHeight?.ToString(), out double height)) 32 | { 33 | webViewRenderer.Element.HeightRequest = height; 34 | } 35 | } 36 | 37 | protected override void Dispose(bool disposing) 38 | { 39 | base.Dispose(disposing); 40 | 41 | if (disposing) 42 | webViewRenderer = null; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/WebviewNewsRenderer/WebviewNewsRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.News.NewsDetail.WebviewNews), typeof(DevsDNA.Application.Droid.Renderers.WebviewNewsRenderer))] 2 | namespace DevsDNA.Application.Droid.Renderers 3 | { 4 | using Android.Content; 5 | using Android.Webkit; 6 | using System; 7 | using Xamarin.Essentials; 8 | using Xamarin.Forms; 9 | using Xamarin.Forms.Platform.Android; 10 | 11 | public class WebviewNewsRenderer : WebViewRenderer 12 | { 13 | public WebviewNewsRenderer(Context context) : base(context) 14 | { 15 | } 16 | 17 | protected override void OnElementChanged(ElementChangedEventArgs e) 18 | { 19 | base.OnElementChanged(e); 20 | if (e.OldElement != null) 21 | { 22 | Element.Navigating -= OnWebviewNavigating; 23 | } 24 | 25 | if (e.NewElement != null && Control != null) 26 | { 27 | Element.Navigating += OnWebviewNavigating; 28 | Control.HorizontalScrollBarEnabled = false; 29 | Control.VerticalScrollBarEnabled = false; 30 | } 31 | } 32 | 33 | protected override WebViewClient GetWebViewClient() 34 | { 35 | return new DynamicSizeWebViewClient(this); 36 | } 37 | 38 | private void OnWebviewNavigating(object sender, WebNavigatingEventArgs e) 39 | { 40 | if (Uri.IsWellFormedUriString(e.Url, UriKind.Absolute)) 41 | { 42 | Launcher.TryOpenAsync(e.Url); 43 | e.Cancel = true; 44 | } 45 | } 46 | 47 | protected override void Dispose(bool disposing) 48 | { 49 | base.Dispose(disposing); 50 | 51 | if (disposing) 52 | { 53 | if (Element != null) 54 | { 55 | Element.Navigating -= OnWebviewNavigating; 56 | } 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/WebviewYoutubeRenderer/FullScreenClient.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Droid.Renderers 2 | { 3 | using Android.App; 4 | using Android.Views; 5 | using Android.Webkit; 6 | using Android.Widget; 7 | 8 | class FullScreenClient : WebChromeClient 9 | { 10 | private readonly Activity context; 11 | private int originalUiOptions; 12 | private View customView; 13 | private ICustomViewCallback videoViewCallback; 14 | 15 | public FullScreenClient(Activity context) 16 | { 17 | this.context = context; 18 | } 19 | 20 | public override void OnShowCustomView(View view, ICustomViewCallback callback) 21 | { 22 | if (customView != null) 23 | { 24 | OnHideCustomView(); 25 | return; 26 | } 27 | 28 | videoViewCallback = callback; 29 | customView = view; 30 | customView.SetBackgroundColor(Android.Graphics.Color.Black); 31 | context.RequestedOrientation = Android.Content.PM.ScreenOrientation.Landscape; 32 | 33 | originalUiOptions = (int)context.Window.DecorView.SystemUiVisibility; 34 | var newUiOptions = originalUiOptions | (int)SystemUiFlags.LayoutStable | (int)SystemUiFlags.LayoutHideNavigation | (int)SystemUiFlags.LayoutHideNavigation | 35 | (int)SystemUiFlags.LayoutFullscreen | (int)SystemUiFlags.HideNavigation | (int)SystemUiFlags.Fullscreen | (int)SystemUiFlags.Immersive; 36 | context.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)newUiOptions; 37 | 38 | if (context.Window.DecorView is FrameLayout layout) 39 | layout.AddView(customView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent)); 40 | } 41 | 42 | 43 | public override void OnHideCustomView() 44 | { 45 | if (context.Window.DecorView is FrameLayout layout) 46 | layout.RemoveView(customView); 47 | 48 | context.RequestedOrientation = Android.Content.PM.ScreenOrientation.Portrait; 49 | context.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)originalUiOptions; 50 | videoViewCallback.OnCustomViewHidden(); 51 | customView = null; 52 | videoViewCallback = null; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/WebviewYoutubeRenderer/JSBridge.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.Videos.VideoDetail.WebviewYoutube), typeof(DevsDNA.Application.Droid.Renderers.WebviewYoutubeRenderer))] 2 | namespace DevsDNA.Application.Droid.Renderers 3 | { 4 | using Android.Webkit; 5 | using DevsDNA.Application.Features.Videos.VideoDetail; 6 | using Java.Interop; 7 | using System; 8 | 9 | class JSBridge : Java.Lang.Object 10 | { 11 | private readonly WeakReference webviewRenderer; 12 | 13 | public JSBridge(WebviewYoutubeRenderer webviewYoutubeRenderer) 14 | { 15 | webviewRenderer = new WeakReference(webviewYoutubeRenderer); 16 | } 17 | 18 | [JavascriptInterface] 19 | [Export("invokeAction")] 20 | public void InvokeAction(string data) 21 | { 22 | if (webviewRenderer != null && webviewRenderer.TryGetTarget(out WebviewYoutubeRenderer webviewYoutubeRenderer) && 23 | webviewYoutubeRenderer.Element is WebviewYoutube webviewYoutube) 24 | { 25 | webviewYoutube.InvokeAction(data); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/WebviewYoutubeRenderer/JavascriptWebViewClient.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.Videos.VideoDetail.WebviewYoutube), typeof(DevsDNA.Application.Droid.Renderers.WebviewYoutubeRenderer))] 2 | namespace DevsDNA.Application.Droid.Renderers 3 | { 4 | using Android.Webkit; 5 | using Xamarin.Forms.Platform.Android; 6 | 7 | class JavascriptWebViewClient : FormsWebViewClient 8 | { 9 | private readonly string javascript; 10 | 11 | public JavascriptWebViewClient(WebviewYoutubeRenderer renderer, string javascript) : base(renderer) 12 | { 13 | this.javascript = javascript; 14 | } 15 | 16 | public override void OnPageFinished(WebView view, string url) 17 | { 18 | view.EvaluateJavascript(javascript, null); 19 | base.OnPageFinished(view, url); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Renderers/WebviewYoutubeRenderer/WebviewYoutubeRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.Videos.VideoDetail.WebviewYoutube), typeof(DevsDNA.Application.Droid.Renderers.WebviewYoutubeRenderer))] 2 | namespace DevsDNA.Application.Droid.Renderers 3 | { 4 | using Android.App; 5 | using Android.Content; 6 | using Xamarin.Forms.Platform.Android; 7 | 8 | public class WebviewYoutubeRenderer : WebViewRenderer 9 | { 10 | private const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}"; 11 | private const string NativeScriptName = "jsBridge"; 12 | 13 | public WebviewYoutubeRenderer(Context context) : base(context) 14 | { 15 | } 16 | 17 | protected override void OnElementChanged(ElementChangedEventArgs e) 18 | { 19 | base.OnElementChanged(e); 20 | 21 | if (e.OldElement != null) 22 | { 23 | Control.RemoveJavascriptInterface(NativeScriptName); 24 | } 25 | if (e.NewElement != null) 26 | { 27 | Control.SetWebViewClient(new JavascriptWebViewClient(this, $"javascript: {JavascriptFunction}")); 28 | Control.AddJavascriptInterface(new JSBridge(this), NativeScriptName); 29 | Control.SetWebChromeClient(new FullScreenClient(Context as Activity)); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.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.xml), 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-hdpi/ 12 | icon.png 13 | 14 | drawable-ldpi/ 15 | icon.png 16 | 17 | drawable-mdpi/ 18 | icon.png 19 | 20 | layout/ 21 | main.xml 22 | 23 | values/ 24 | strings.xml 25 | 26 | In order to get the build system to recognize Android resources, set the build action to 27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 28 | instead operate on resource IDs. When you compile an Android application that uses resources, 29 | the build system will package the resources for distribution and generate a class called 30 | "Resource" that contains the tokens for each one of the resources included. For example, 31 | for the above Resources layout, this is what the Resource class would expose: 32 | 33 | public class Resource { 34 | public class drawable { 35 | public const int icon = 0x123; 36 | } 37 | 38 | public class layout { 39 | public const int main = 0x456; 40 | } 41 | 42 | public class strings { 43 | public const int first_string = 0xabc; 44 | public const int second_string = 0xbcd; 45 | } 46 | } 47 | 48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main 49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first 50 | string in the dictionary file values/strings.xml. 51 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/Thumbs.db -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/close.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/close_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/close_blue.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/facebook.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/facebook_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/facebook_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/instagram_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/instagram_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/linkedin_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/linkedin_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/logotipo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/logotipo.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/phone.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/share.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/shareColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/shareColor.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/talk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/talk.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/twitter_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-hdpi/twitter_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/Thumbs.db -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/close.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/close_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/close_blue.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/facebook.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/facebook_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/facebook_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/instagram_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/instagram_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/linkedin_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/linkedin_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/logotipo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/logotipo.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/phone.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/share.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/shareColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/shareColor.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/talk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/talk.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/twitter_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-mdpi/twitter_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-v26/launcher.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/Thumbs.db -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/close.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/close_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/close_blue.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/facebook.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/facebook_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/facebook_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/instagram_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/instagram_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/linkedin_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/linkedin_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/logotipo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/logotipo.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/phone.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/share.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/shareColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/shareColor.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/talk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/talk.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/twitter_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xhdpi/twitter_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/Thumbs.db -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/close.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/close_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/close_blue.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/facebook.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/facebook_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/facebook_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/instagram_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/instagram_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/linkedin_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/linkedin_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/logotipo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/logotipo.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/phone.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/share.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/shareColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/shareColor.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/talk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/talk.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/twitter_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxhdpi/twitter_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/Thumbs.db -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/close.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/close_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/close_blue.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/facebook.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/facebook_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/facebook_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/instagram_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/instagram_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/linkedin_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/linkedin_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/logotipo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/logotipo.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/phone.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/share.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/shareColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/shareColor.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/talk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/talk.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/twitter_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable-xxxhdpi/twitter_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/beatriz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/beatriz.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/ciani.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/ciani.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/ic_notification.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/icon.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/jorge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/jorge.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/luis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/luis.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/marco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/marco.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/notificationSmallIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/notificationSmallIcon.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/splashscreen.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/yeray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/drawable/yeray.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/layout/Tabbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/layout/Toolbar.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #1d1d54 5 | #1d1d54 6 | #FF4081 7 | 8 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 30 | 31 | 38 | 39 | 47 | 48 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Services/AccessibilityChecker/AccessibilityCheckerService.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.Dependency(typeof(DevsDNA.Application.Droid.Services.AccessibilityCheckerService))] 2 | namespace DevsDNA.Application.Droid.Services 3 | { 4 | using Android.Content; 5 | using Android.Views.Accessibility; 6 | using DevsDNA.Application.Services; 7 | 8 | public class AccessibilityCheckerService : IAccessibilityCheckerService 9 | { 10 | public bool IsVoiceAssistantActive() 11 | { 12 | using (AccessibilityManager accessibilityManager = (AccessibilityManager)MainActivity.CurrentActivity.GetSystemService(Context.AccessibilityService)) 13 | { 14 | return accessibilityManager?.IsTouchExplorationEnabled ?? false; 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.Android/Services/Notifications/NotificationService.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.Dependency(typeof(DevsDNA.Application.Droid.Services.NotificationService))] 2 | namespace DevsDNA.Application.Droid.Services 3 | { 4 | using System; 5 | using System.Threading.Tasks; 6 | using DevsDNA.Application.Common; 7 | using DevsDNA.Application.Services; 8 | using WindowsAzure.Messaging; 9 | using Xamarin.Essentials; 10 | 11 | public class NotificationService : INotificationService 12 | { 13 | private readonly ILogService logService; 14 | 15 | public NotificationService() 16 | { 17 | logService = CustomDependencyService.Instance.Get(); 18 | } 19 | 20 | public static string NotificationToken { get; set; } 21 | 22 | public void EnableNotifications() 23 | { 24 | try 25 | { 26 | string token = NotificationToken; 27 | 28 | if (string.IsNullOrWhiteSpace(token)) 29 | { 30 | token = Preferences.Get(SettingsKeyValues.PreferenceKeyNotificationToken, string.Empty); 31 | } 32 | 33 | if (!string.IsNullOrEmpty(token)) 34 | { 35 | NotificationHub hub = new NotificationHub(SettingsKeyValues.NotificationHubName, SettingsKeyValues.NotificationConnectionString, MainActivity.CurrentActivity); 36 | Task.Run(() => hub.Register(NotificationToken, null)).ConfigureAwait(false); 37 | } 38 | } 39 | catch (Exception ex) 40 | { 41 | logService.LogError(ex); 42 | } 43 | } 44 | 45 | public void DisableNotifications() 46 | { 47 | try 48 | { 49 | if (!string.IsNullOrEmpty(NotificationToken)) 50 | { 51 | Task.Run(() => 52 | new NotificationHub(SettingsKeyValues.NotificationHubName, SettingsKeyValues.NotificationConnectionString, MainActivity.CurrentActivity) 53 | .UnregisterAll(NotificationToken)); 54 | } 55 | } 56 | catch (Exception ex) 57 | { 58 | logService.LogError(ex); 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/DevsDNA.Application.iOS.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevsDNA.Application.iOS", "DevsDNA.Application.iOS.csproj", "{99556E27-EFEE-4E4A-8253-BF64A73C5E3F}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|iPhoneSimulator = Debug|iPhoneSimulator 9 | Release|iPhoneSimulator = Release|iPhoneSimulator 10 | Debug|iPhone = Debug|iPhone 11 | Release|iPhone = Release|iPhone 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator 15 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator 16 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator 17 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator 18 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Debug|iPhone.ActiveCfg = Debug|iPhone 19 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Debug|iPhone.Build.0 = Debug|iPhone 20 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Release|iPhone.ActiveCfg = Release|iPhone 21 | {99556E27-EFEE-4E4A-8253-BF64A73C5E3F}.Release|iPhone.Build.0 = Release|iPhone 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Effects/DropShadowEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.iOS.Effects.DropShadowEffect), 2 | nameof(DevsDNA.Application.iOS.Effects.DropShadowEffect))] 3 | namespace DevsDNA.Application.iOS.Effects 4 | { 5 | using CoreGraphics; 6 | using System.Linq; 7 | using Xamarin.Forms.Platform.iOS; 8 | 9 | public class DropShadowEffect : PlatformEffect 10 | { 11 | protected override void OnAttached() 12 | { 13 | var view = Control ?? Container; 14 | var dropEffect = (DevsDNA.Application.Effects.DropShadowEffect)Element.Effects.FirstOrDefault(e => e is DevsDNA.Application.Effects.DropShadowEffect); 15 | if (view == null || dropEffect == null) 16 | return; 17 | 18 | view.Layer.MasksToBounds = false; 19 | view.Layer.ShadowColor = dropEffect.ShadowColor.ToCGColor(); 20 | view.Layer.ShadowOpacity = dropEffect.Opacity; 21 | view.Layer.ShadowOffset = new CGSize(dropEffect.Offset.X, dropEffect.Offset.Y); 22 | view.Layer.ShadowRadius = dropEffect.Radius; 23 | } 24 | 25 | protected override void OnDetached() 26 | { 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Effects/FixedFrameClippedToBoundsEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.iOS.Effects.FixedFrameClippedToBoundsEffect), 2 | nameof(DevsDNA.Application.iOS.Effects.FixedFrameClippedToBoundsEffect))] 3 | namespace DevsDNA.Application.iOS.Effects 4 | { 5 | using System.Linq; 6 | using Xamarin.Forms.Platform.iOS; 7 | 8 | public class FixedFrameClippedToBoundsEffect : PlatformEffect 9 | { 10 | protected override void OnAttached() 11 | { 12 | var frame = Container?.Subviews?.FirstOrDefault() ?? Control?.Subviews?.FirstOrDefault(); 13 | if (frame != null) 14 | { 15 | frame.ClipsToBounds = true; 16 | } 17 | } 18 | 19 | protected override void OnDetached() 20 | { 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Effects/RemoveBouncesEffect.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportEffect(typeof(DevsDNA.Application.iOS.Effects.RemoveBouncesEffect), 2 | nameof(DevsDNA.Application.iOS.Effects.RemoveBouncesEffect))] 3 | namespace DevsDNA.Application.iOS.Effects 4 | { 5 | using UIKit; 6 | using Xamarin.Forms.Platform.iOS; 7 | 8 | public class RemoveBouncesEffect : PlatformEffect 9 | { 10 | protected override void OnAttached() 11 | { 12 | if (Container is UIScrollView uiScrollView) 13 | { 14 | uiScrollView.Bounces = false; 15 | } 16 | } 17 | 18 | protected override void OnDetached() 19 | { 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | production 7 | 8 | 9 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UISupportedInterfaceOrientations 11 | 12 | UIInterfaceOrientationPortrait 13 | 14 | UISupportedInterfaceOrientations~ipad 15 | 16 | UIInterfaceOrientationPortrait 17 | UIInterfaceOrientationPortraitUpsideDown 18 | UIInterfaceOrientationLandscapeLeft 19 | UIInterfaceOrientationLandscapeRight 20 | 21 | MinimumOSVersion 22 | 12.0 23 | CFBundleDisplayName 24 | DevsDNA 25 | CFBundleIdentifier 26 | com.devsdna.application 27 | CFBundleVersion 28 | 1.0.1 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | CFBundleName 32 | DevsDNA 33 | XSAppIconAssets 34 | Assets.xcassets/AppIcon.appiconset 35 | CFBundleShortVersionString 36 | 4 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | UIStatusBarStyle 40 | UIStatusBarStyleLightContent 41 | UIBackgroundModes 42 | 43 | remote-notification 44 | 45 | UIUserInterfaceStyle 46 | Light 47 | 48 | 49 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.iOS 2 | { 3 | using System; 4 | using UIKit; 5 | 6 | public class Application 7 | { 8 | // This is the main entry point of the application. 9 | static void Main(string[] args) 10 | { 11 | try 12 | { 13 | // if you want to use a different Application Delegate class from "AppDelegate" 14 | // you can specify it here. 15 | UIApplication.Main(args, null, "AppDelegate"); 16 | } 17 | catch (Exception ex) 18 | { 19 | Microsoft.AppCenter.Crashes.Crashes.TrackError(ex); 20 | throw; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("DevsDNA.Application.iOS")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("DevsDNA.Application.iOS")] 12 | [assembly: AssemblyCopyright("Copyright © 2014")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | 37 | [assembly: Xamarin.Forms.ResolutionGroupName(DevsDNA.Application.Common.SettingsKeyValues.ResolutionGroupName)] 38 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/CarouselAnimatedRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Controls.Carousel.CarouselAnimated), typeof(DevsDNA.Application.iOS.Renderers.CarouselAnimatedRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using DevsDNA.Application.Controls.Carousel; 5 | using ReactiveUI; 6 | using System; 7 | using System.Reactive.Linq; 8 | using Xamarin.Forms; 9 | using Xamarin.Forms.Platform.iOS; 10 | 11 | public class CarouselAnimatedRenderer : CarouselViewRenderer 12 | { 13 | private CarouselAnimated CarouselAnimated => Element as CarouselAnimated; 14 | 15 | protected override void UpdateItemsSource() 16 | { 17 | base.UpdateItemsSource(); 18 | 19 | Controller?.CollectionView?.PerformBatchUpdatesAsync(() => 20 | { 21 | if (CarouselAnimated.Position != 0) 22 | { 23 | CarouselAnimated.WhenAny(c => c.Position, c => c.Value).ObserveOn(RxApp.MainThreadScheduler).Where(c => c == 0).Take(1) 24 | .Throttle(TimeSpan.FromMilliseconds(200)).Subscribe(_ => CarouselAnimated.OnItemsSourcePainted()); 25 | CarouselAnimated.ScrollTo(0, position: ScrollToPosition.Center, animate: false); 26 | } 27 | else 28 | { 29 | CarouselAnimated.OnItemsSourcePainted(); 30 | } 31 | }); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/CollectionViewSocialNetworkRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.SocialNetwork.CollectionViewSocialNetwork), typeof(DevsDNA.Application.iOS.Renderers.CollectionViewSocialNetworkRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using DevsDNA.Application.Features.SocialNetwork; 5 | using Xamarin.Forms.Platform.iOS; 6 | 7 | public class CollectionViewSocialNetworkRenderer : CollectionViewRenderer 8 | { 9 | private CollectionViewSocialNetwork CollectionViewSocialNetwork => Element as CollectionViewSocialNetwork; 10 | 11 | protected override void UpdateItemsSource() 12 | { 13 | base.UpdateItemsSource(); 14 | 15 | Controller?.CollectionView?.PerformBatchUpdatesAsync(() => { CollectionViewSocialNetwork?.OnItemsSourcePainted(); }); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/DisableZoomScrollDelegate.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.Videos.VideoDetail.WebviewYoutube), typeof(DevsDNA.Application.iOS.Renderers.WebviewYoutubeRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using UIKit; 5 | 6 | class DisableZoomScrollDelegate : UIScrollViewDelegate 7 | { 8 | public override void ZoomingStarted(UIScrollView scrollView, UIView view) 9 | { 10 | if (scrollView.PinchGestureRecognizer != null) 11 | { 12 | scrollView.PinchGestureRecognizer.Enabled = false; 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/FrameGradientRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Controls.FrameGradient), typeof(DevsDNA.Application.iOS.Renderers.FrameGradientRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using CoreAnimation; 5 | using CoreGraphics; 6 | using DevsDNA.Application.Controls; 7 | using UIKit; 8 | using Xamarin.Forms; 9 | using Xamarin.Forms.Platform.iOS; 10 | 11 | public class FrameGradientRenderer : FrameRenderer 12 | { 13 | private CAGradientLayer gradientLayer = new CAGradientLayer(); 14 | private UIView frameView; 15 | 16 | private FrameGradient FrameGradient => Element as FrameGradient; 17 | 18 | protected override void OnElementChanged(ElementChangedEventArgs e) 19 | { 20 | base.OnElementChanged(e); 21 | if (e.NewElement != null) 22 | { 23 | frameView = Subviews[0]; 24 | AddGradient(); 25 | } 26 | } 27 | 28 | public override void Draw(CGRect rect) 29 | { 30 | base.Draw(rect); 31 | 32 | gradientLayer.Frame = frameView.Frame; 33 | } 34 | 35 | protected override void Dispose(bool disposing) 36 | { 37 | if (disposing) 38 | { 39 | if (gradientLayer != null) 40 | { 41 | gradientLayer.RemoveFromSuperLayer(); 42 | gradientLayer.Dispose(); 43 | gradientLayer = null; 44 | } 45 | } 46 | } 47 | 48 | private void AddGradient() 49 | { 50 | frameView.BackgroundColor = UIColor.Clear; 51 | gradientLayer.Colors = new[] { FrameGradient.StartColor.ToCGColor(), FrameGradient.EndColor.ToCGColor() }; 52 | gradientLayer.StartPoint = new CGPoint(0, 0.5); 53 | gradientLayer.EndPoint = new CGPoint(1.0, 0.5); 54 | gradientLayer.Frame = frameView.Layer.Bounds; 55 | gradientLayer.CornerRadius = frameView.Layer.CornerRadius; 56 | frameView.Layer.InsertSublayer(gradientLayer, 0); 57 | } 58 | 59 | } 60 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/WebviewNewsRenderer/WebviewNewsNavigationDelegate.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.News.NewsDetail.WebviewNews), typeof(DevsDNA.Application.iOS.Renderers.WebviewNewsRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using System; 5 | using WebKit; 6 | using Xamarin.Essentials; 7 | using Xamarin.Forms.Platform.iOS; 8 | 9 | public class WebviewNewsNavigationDelegate : WKNavigationDelegate 10 | { 11 | public async override void DidFinishNavigation(WKWebView webView, WKNavigation navigation) 12 | { 13 | if (!webView.IsLoading && webView is WkWebViewRenderer wkWebViewRenderer) 14 | { 15 | var contentHeight = await webView.EvaluateJavaScriptAsync("document.body.scrollHeight"); 16 | if(double.TryParse(contentHeight?.ToString(), out double height)) 17 | { 18 | wkWebViewRenderer.Element.HeightRequest = height; 19 | } 20 | } 21 | } 22 | public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action decisionHandler) 23 | { 24 | if (!webView.IsLoading) 25 | { 26 | Launcher.TryOpenAsync(navigationAction.Request.Url.ToString()); 27 | decisionHandler(WKNavigationActionPolicy.Cancel); 28 | return; 29 | } 30 | 31 | decisionHandler(WKNavigationActionPolicy.Allow); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/WebviewNewsRenderer/WebviewNewsRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.News.NewsDetail.WebviewNews), typeof(DevsDNA.Application.iOS.Renderers.WebviewNewsRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using Xamarin.Forms.Platform.iOS; 5 | 6 | public class WebviewNewsRenderer : WkWebViewRenderer 7 | { 8 | protected override void OnElementChanged(VisualElementChangedEventArgs e) 9 | { 10 | base.OnElementChanged(e); 11 | 12 | if (e.NewElement != null) 13 | { 14 | Element.HeightRequest = 1; 15 | ScrollView.ScrollEnabled = false; 16 | ScrollView.Bounces = false; 17 | ScrollView.Delegate = new DisableZoomScrollDelegate(); 18 | NavigationDelegate = new WebviewNewsNavigationDelegate(); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Renderers/WebviewYoutubeRenderer/WebviewYoutubeRenderer.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.ExportRenderer(typeof(DevsDNA.Application.Features.Videos.VideoDetail.WebviewYoutube), typeof(DevsDNA.Application.iOS.Renderers.WebviewYoutubeRenderer))] 2 | namespace DevsDNA.Application.iOS.Renderers 3 | { 4 | using DevsDNA.Application.Features.Videos.VideoDetail; 5 | using Foundation; 6 | using WebKit; 7 | using Xamarin.Forms.Platform.iOS; 8 | 9 | public class WebviewYoutubeRenderer : WkWebViewRenderer, IWKScriptMessageHandler 10 | { 11 | private const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}"; 12 | private const string NativeScriptName = "invokeAction"; 13 | private readonly WKUserContentController userController; 14 | private WebviewYoutube WebviewYoutube => Element as WebviewYoutube; 15 | 16 | public WebviewYoutubeRenderer() : this(new WKWebViewConfiguration() { AllowsInlineMediaPlayback = true }) 17 | { 18 | } 19 | 20 | public WebviewYoutubeRenderer(WKWebViewConfiguration config) : base(config) 21 | { 22 | userController = config.UserContentController; 23 | var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false); 24 | userController.AddUserScript(script); 25 | userController.AddScriptMessageHandler(this, "invokeAction"); 26 | 27 | } 28 | 29 | protected override void OnElementChanged(VisualElementChangedEventArgs e) 30 | { 31 | base.OnElementChanged(e); 32 | 33 | if (e.OldElement != null) 34 | { 35 | userController.RemoveAllUserScripts(); 36 | userController.RemoveScriptMessageHandler(NativeScriptName); 37 | } 38 | 39 | if (e.NewElement != null) 40 | { 41 | ScrollView.ScrollEnabled = false; 42 | ScrollView.Delegate = new DisableZoomScrollDelegate(); 43 | } 44 | } 45 | 46 | 47 | public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message) 48 | { 49 | WebviewYoutube?.InvokeAction(message?.Body?.ToString()); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/Heebo-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/Heebo-Black.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/Heebo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/Heebo-Regular.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/beatriz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/beatriz.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/ciani.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/ciani.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close_blue.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close_blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close_blue@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close_blue@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/close_blue@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook_white@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/facebook_white@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/instagram_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/instagram_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/instagram_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/instagram_white@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/instagram_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/instagram_white@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/jorge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/jorge.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/linkedin_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/linkedin_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/linkedin_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/linkedin_white@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/linkedin_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/linkedin_white@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/logotipo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/logotipo.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/logotipo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/logotipo@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/logotipo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/logotipo@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/luis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/luis.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/marco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/marco.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/phone.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/phone@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/phone@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/phone@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/phone@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/share.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/share@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/share@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/share@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/shareColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/shareColor.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/shareColor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/shareColor@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/shareColor@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/shareColor@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/talk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/talk.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/talk@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/talk@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/talk@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/talk@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/twitter_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/twitter_white.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/twitter_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/twitter_white@2x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/twitter_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/twitter_white@3x.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/yeray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Resources/yeray.png -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Services/AccessibilityChecker/AccessibilityCheckerService.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.Dependency(typeof(DevsDNA.Application.iOS.Services.AccessibilityCheckerService))] 2 | namespace DevsDNA.Application.iOS.Services 3 | { 4 | using DevsDNA.Application.Services; 5 | using System; 6 | using UIKit; 7 | 8 | public class AccessibilityCheckerService : IAccessibilityCheckerService 9 | { 10 | public bool IsVoiceAssistantActive() 11 | { 12 | return UIAccessibility.IsVoiceOverRunning; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Services/Notifications/NotificationsService.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.Dependency(typeof(DevsDNA.Application.iOS.Services.NotificationService))] 2 | namespace DevsDNA.Application.iOS.Services 3 | { 4 | using DevsDNA.Application.Common; 5 | using DevsDNA.Application.Services; 6 | using Foundation; 7 | using System; 8 | using System.Threading.Tasks; 9 | using UIKit; 10 | using UserNotifications; 11 | using WindowsAzure.Messaging; 12 | 13 | public class NotificationService : INotificationService 14 | { 15 | private readonly ILogService logService; 16 | private readonly SBNotificationHub notificationHub; 17 | private NSData notificationToken; 18 | 19 | public NotificationService() 20 | { 21 | logService = CustomDependencyService.Instance.Get(); 22 | notificationHub = new SBNotificationHub(SettingsKeyValues.NotificationConnectionString, SettingsKeyValues.NotificationHubName); 23 | } 24 | 25 | 26 | public void EnableNotifications() 27 | { 28 | // register for remote notifications based on system version 29 | if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0)) 30 | { 31 | UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Sound, 32 | (granted, error) => 33 | { 34 | if (granted) 35 | Xamarin.Forms.Device.BeginInvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications); 36 | }); 37 | } 38 | else 39 | { 40 | throw new Exception("Application is not supported for lowers versions."); 41 | } 42 | } 43 | 44 | public void DisableNotifications() 45 | { 46 | try 47 | { 48 | if (notificationToken != null) 49 | { 50 | notificationHub.UnregisterAll(notificationToken, out NSError error); 51 | 52 | if (error != null) 53 | { 54 | logService.Log(error.DebugDescription); 55 | } 56 | } 57 | } 58 | catch (Exception ex) 59 | { 60 | logService.LogError(ex); 61 | } 62 | } 63 | 64 | public async Task DidRegisterRemoteNotificationsAsync(NSData deviceToken) 65 | { 66 | notificationToken = deviceToken; 67 | try 68 | { 69 | if (notificationToken != null) 70 | { 71 | await notificationHub.RegisterNativeAsync(notificationToken, null); 72 | } 73 | } 74 | catch (Exception ex) 75 | { 76 | logService.LogError(ex); 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/Services/Notifications/UNNotificationsCenterDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.iOS.Services 2 | { 3 | using System; 4 | using UserNotifications; 5 | 6 | public class UNNotificationsCenterDelegate : UNUserNotificationCenterDelegate 7 | { 8 | public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action completionHandler) 9 | { 10 | // Tell system to display the notification anyway or use 11 | // `None` to say we have handled the display locally. 12 | completionHandler(UNNotificationPresentationOptions.Alert); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/iTunesArtwork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/iTunesArtwork -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/iTunesArtwork@2x: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application.iOS/iTunesArtwork@2x -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | #1d1d54 8 | #292969 9 | #369eae 10 | #b8ff16 11 | #707070 12 | #979797 13 | #d7d7d7 14 | #a8a8a8 15 | #fefefe 16 | White 17 | 18 | 19 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/App.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application 2 | { 3 | using DevsDNA.Application.Features.Splash; 4 | using DevsDNA.Application.Services; 5 | using DevsDNA.Application.Services.Notifications; 6 | using Plugin.SharedTransitions; 7 | using System.Threading.Tasks; 8 | using Xamarin.Forms; 9 | 10 | public partial class App : Application 11 | { 12 | private readonly INotificationManagerService notificationManagerService; 13 | private readonly ITrackService trackService; 14 | 15 | public App() 16 | { 17 | InitializeComponent(); 18 | 19 | IDependencyService dependencyService = CustomDependencyService.Instance; 20 | notificationManagerService = dependencyService.Get(); 21 | trackService = dependencyService.Get(); 22 | 23 | SplashView splashView = new SplashView { ViewModel = new SplashViewModel(dependencyService) }; 24 | NavigationPage navigationPage = new SharedTransitionNavigationPage(splashView) 25 | { 26 | BarTextColor = Color.White, 27 | BarBackgroundColor = Color.White, 28 | BackgroundColor = (Color)Resources["DarkBlueColor"] 29 | }; 30 | NavigationPage.SetHasNavigationBar(splashView, false); 31 | MainPage = navigationPage; 32 | } 33 | 34 | protected override void OnStart() 35 | { 36 | trackService.ConfigureAppCenter(); 37 | trackService.TrackEvent("Started"); 38 | } 39 | 40 | protected override void OnSleep() 41 | { 42 | trackService.TrackEvent("Sleeped"); 43 | } 44 | 45 | protected override void OnResume() 46 | { 47 | trackService.TrackEvent("Resumed"); 48 | } 49 | 50 | public Task NewNotificationReceivedAsync(PushNotificationsType pushType) 51 | { 52 | return notificationManagerService.ProcessNotificationAsync(pushType); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using Xamarin.Forms; 3 | using Xamarin.Forms.Xaml; 4 | 5 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)] 6 | [assembly: InternalsVisibleTo("DevsDNA.Application.Tests")] 7 | 8 | [assembly: ExportFont("Heebo-Black.ttf")] 9 | [assembly: ExportFont("Heebo-Bold.ttf")] 10 | [assembly: ExportFont("Heebo-ExtraBold.ttf")] 11 | [assembly: ExportFont("Heebo-Light.ttf")] 12 | [assembly: ExportFont("Heebo-Medium.ttf")] 13 | [assembly: ExportFont("Heebo-Regular.ttf")] 14 | [assembly: ExportFont("Heebo-Thin.ttf")] 15 | [assembly: ExportFont("SpaceMono-Bold.ttf")] 16 | [assembly: ExportFont("SpaceMono-Regular.ttf")] -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Base/BaseContentPage.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Base 2 | { 3 | using DevsDNA.Application.Services; 4 | using ReactiveUI; 5 | using ReactiveUI.XamForms; 6 | using System.Reactive.Disposables; 7 | using System.Threading.Tasks; 8 | 9 | public class BaseContentPage : ReactiveContentPage where TViewModel : BaseViewModel 10 | { 11 | private bool isAlreadyInitialized; 12 | 13 | public BaseContentPage() 14 | { 15 | DependencyService = CustomDependencyService.Instance; 16 | LogService = DependencyService.Get(); 17 | TrackService = DependencyService.Get(); 18 | this.WhenActivated(d => CreateBindings(d)); 19 | } 20 | 21 | protected IDependencyService DependencyService { get; } 22 | protected ILogService LogService { get; } 23 | protected ITrackService TrackService { get; } 24 | 25 | 26 | protected virtual CompositeDisposable CreateBindings(CompositeDisposable disposables) 27 | { 28 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.IsLoading, v => v.IsBusy, b => b)); 29 | return disposables; 30 | } 31 | 32 | protected override async void OnAppearing() 33 | { 34 | base.OnAppearing(); 35 | await ViewModel?.AppearingAsync(); 36 | 37 | if (!isAlreadyInitialized) 38 | { 39 | isAlreadyInitialized = true; 40 | await OnFirstAppearingAsync(); 41 | } 42 | } 43 | 44 | protected override async void OnDisappearing() 45 | { 46 | await ViewModel?.DisappearingAsync(); 47 | base.OnDisappearing(); 48 | } 49 | 50 | protected virtual Task OnFirstAppearingAsync() 51 | { 52 | return Task.CompletedTask; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Base/BaseContentView.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Base 2 | { 3 | using DevsDNA.Application.Services; 4 | using Lottie.Forms; 5 | using ReactiveUI; 6 | using ReactiveUI.XamForms; 7 | using System.Reactive.Disposables; 8 | using Xamarin.Forms; 9 | 10 | public abstract class BaseContentView : ReactiveContentView where TViewModel : BaseViewModel 11 | { 12 | private bool isAlreadySizeAllocated; 13 | 14 | public BaseContentView() 15 | { 16 | DependencyService = CustomDependencyService.Instance; 17 | LogService = DependencyService.Get(); 18 | TrackService = DependencyService.Get(); 19 | } 20 | 21 | protected IDependencyService DependencyService { get; } 22 | protected ILogService LogService { get; } 23 | protected ITrackService TrackService { get; } 24 | 25 | protected override void OnBindingContextChanged() 26 | { 27 | base.OnBindingContextChanged(); 28 | if (!(ViewModel is null)) 29 | { 30 | this.WhenActivated(d => CreateBindings(d)); 31 | } 32 | } 33 | 34 | protected virtual CompositeDisposable CreateBindings(CompositeDisposable disposables) 35 | { 36 | return disposables; 37 | } 38 | 39 | protected override void OnSizeAllocated(double width, double height) 40 | { 41 | base.OnSizeAllocated(width, height); 42 | 43 | if (!isAlreadySizeAllocated && width != -1 && height != -1) 44 | { 45 | isAlreadySizeAllocated = true; 46 | OnFirstSizeAllocated(width, height); 47 | } 48 | } 49 | 50 | protected virtual void OnFirstSizeAllocated(double width, double height) 51 | { 52 | } 53 | 54 | protected void StartLoadingAnimation(AnimationView animationView) 55 | { 56 | animationView.IsVisible = true; 57 | animationView.IsPlaying = true; 58 | } 59 | 60 | protected void StopLoadingAnimation(AnimationView animationView) 61 | { 62 | animationView.IsVisible = false; 63 | animationView.IsPlaying = false; 64 | if (Device.RuntimePlatform == Device.iOS) 65 | { 66 | animationView.Progress = 1; 67 | animationView.Progress = 0; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Base/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Base 2 | { 3 | using DevsDNA.Application.Services; 4 | using ReactiveUI; 5 | using System.Reactive.Disposables; 6 | using System.Threading.Tasks; 7 | 8 | public class BaseViewModel : ReactiveObject 9 | { 10 | private readonly string typeName; 11 | private bool isLoading; 12 | 13 | public BaseViewModel(IDependencyService dependencyService) 14 | { 15 | DependencyService = dependencyService ?? CustomDependencyService.Instance; 16 | LogService = DependencyService.Get(); 17 | TrackService = DependencyService.Get(); 18 | 19 | Disposables = new CompositeDisposable(); 20 | typeName = GetType().ToString(); 21 | LogService.Log($"Creating {typeName}"); 22 | } 23 | 24 | 25 | public virtual bool IsLoading 26 | { 27 | get { return isLoading || (IsLoadingPropertyHelper?.Value ?? false); } 28 | set { this.RaiseAndSetIfChanged(ref isLoading, value); } 29 | } 30 | 31 | public CompositeDisposable Disposables { get; set; } 32 | 33 | protected IDependencyService DependencyService { get; } 34 | protected ILogService LogService { get; } 35 | protected ITrackService TrackService { get; } 36 | protected virtual ObservableAsPropertyHelper IsLoadingPropertyHelper { get; set; } 37 | 38 | 39 | public virtual Task AppearingAsync() 40 | { 41 | LogService.Log($"Appearing {typeName}"); 42 | TrackService.TrackEvent($"Appearing {typeName}"); 43 | Disposables ??= new CompositeDisposable(); 44 | return Task.CompletedTask; 45 | } 46 | 47 | public virtual Task DisappearingAsync() 48 | { 49 | LogService.Log($"Disappearing {typeName}"); 50 | TrackService.TrackEvent($"Disappearing {typeName}"); 51 | Disposables?.Dispose(); 52 | Disposables = null; 53 | return Task.CompletedTask; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Common/GlobalInfo.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Common 2 | { 3 | using Xamarin.Forms; 4 | 5 | public static class GlobalInfo 6 | { 7 | public static Thickness SafeAreaInset { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Common/SettingsKeyValues.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Common 2 | { 3 | using DevsDNA.Application.Helpers; 4 | 5 | public static class SettingsKeyValues 6 | { 7 | public const string PreferenceKeyNotificationToken = "NotificationToken"; 8 | public const string PreferenceKeyFirstTimeKey = "firstTime"; 9 | 10 | 11 | public const string FacebookEndPoint = "https://graph.facebook.com"; 12 | public const string FacebookPageId = "434033656806892"; 13 | 14 | public const string UrlDevsDNAEndPoint = "https://www.devsdna.com"; 15 | public const string UrlDevsDNABlog = UrlDevsDNAEndPoint + "/feed/"; 16 | 17 | public const string YouTubeEndPoint = "https://www.youtube.com/"; 18 | public const string YouTubeChannelId = "UCulG_4j8ggcXJKyeXuHcvdA"; 19 | 20 | public const string UrlDevsDNAFacebook = "https://www.facebook.com/DevsDNA/"; 21 | public const string UrlDevsDNATwitter = "https://twitter.com/devsdna"; 22 | public const string UrlDevsDNALinkedIn = "https://www.linkedin.com/company/devsdna/"; 23 | public const string UrlDevsDNAInstagram = "https://www.instagram.com/devsdna"; 24 | public const string EmailDevsDNA = "info@devsdna.com"; 25 | public const string PhoneNumberDevsDNA = "+34627273613"; 26 | public const string UrlDevsDNAPlayStore = "https://play.google.com/store/apps/details?id=com.devsdna.application"; 27 | public const string UrlDevsDNAAppStore = "https://apps.apple.com/us/app/id1526657968"; 28 | 29 | public static string NotificationHubName = Secrets.NotificationHubName; 30 | public static string NotificationConnectionString = Secrets.NotificationHubConnectionString; 31 | 32 | public const string ResolutionGroupName = "DevsDNA"; 33 | 34 | public static string MessagingCenterOrientationChangedMessage = "OrientationChanged"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Controls/ButtonRoundedGradient.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Controls 2 | { 3 | using System.Windows.Input; 4 | using Xamarin.Forms; 5 | 6 | public partial class ButtonRoundedGradient : FrameGradient 7 | { 8 | public static BindableProperty TextProperty = BindableProperty.Create(nameof(TextProperty), typeof(string), typeof(ButtonRoundedGradient), null, propertyChanged: OnTextChanged); 9 | public static BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(ButtonRoundedGradient), null); 10 | 11 | 12 | public ButtonRoundedGradient() 13 | { 14 | InitializeComponent(); 15 | BindingContext = this; 16 | } 17 | 18 | public string Text 19 | { 20 | get { return (string)GetValue(TextProperty); } 21 | set { SetValue(TextProperty, value); } 22 | } 23 | 24 | public ICommand Command 25 | { 26 | get { return (ICommand)GetValue(CommandProperty); } 27 | set { SetValue(CommandProperty, value); } 28 | } 29 | 30 | 31 | private static void OnTextChanged(BindableObject bindable, object oldValue, object newValue) 32 | { 33 | if (bindable is ButtonRoundedGradient buttonRoundedGradient) 34 | { 35 | buttonRoundedGradient.LblText.Text = newValue?.ToString(); 36 | } 37 | } 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Controls/Carousel/ContentViewAnimated.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Controls.Carousel 2 | { 3 | using System.Threading.Tasks; 4 | using Xamarin.Forms; 5 | 6 | public abstract partial class ContentViewAnimated : ContentView 7 | { 8 | public static BindableProperty FrontTranslationProperty = BindableProperty.Create(nameof(FrontTranslation), typeof(double), typeof(ContentViewAnimated), 0d); 9 | 10 | public static BindableProperty BackOpacityProperty = BindableProperty.Create(nameof(BackOpacity), typeof(double), typeof(ContentViewAnimated), 0d); 11 | 12 | 13 | public double FrontTranslation 14 | { 15 | get { return (double)GetValue(FrontTranslationProperty); } 16 | set { SetValue(FrontTranslationProperty, value); } 17 | } 18 | 19 | public double BackOpacity 20 | { 21 | get { return (double)GetValue(BackOpacityProperty); } 22 | set { SetValue(BackOpacityProperty, value); } 23 | } 24 | 25 | public abstract View OpacityView { get; } 26 | 27 | public abstract Task EnterDownAsync(); 28 | public abstract Task EnterLeftAsync(); 29 | public abstract Task EnterRightAsync(); 30 | public abstract Task LeaveDownAsync(); 31 | public abstract Task LeaveRightAsync(); 32 | public abstract Task LeaveLeftAsync(); 33 | 34 | 35 | public void GoToFront(double percentage) 36 | { 37 | double partsPerUnit = percentage / 100; 38 | Content.TranslationY = -(partsPerUnit * FrontTranslation); 39 | OpacityView.Opacity = BackOpacity - (partsPerUnit * BackOpacity); 40 | } 41 | 42 | public void GoToBack(double percentage) 43 | { 44 | double partsPerUnit = percentage / 100; 45 | Content.TranslationY = -(FrontTranslation - (partsPerUnit * FrontTranslation)); 46 | OpacityView.Opacity = partsPerUnit * BackOpacity; 47 | } 48 | 49 | } 50 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Controls/CarouselViewScrollFixed.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Controls 2 | { 3 | using DevsDNA.Application.Common; 4 | using DevsDNA.Application.Messages; 5 | using Xamarin.Forms; 6 | 7 | public class CarouselViewScrollFixed : CarouselView 8 | { 9 | private Thickness originalPeekAreaInsets; 10 | private int positionBeforeLandscape; 11 | 12 | public CarouselViewScrollFixed() 13 | { 14 | MessagingCenter.Instance.Subscribe(Application.Current, SettingsKeyValues.MessagingCenterOrientationChangedMessage, (a, o) => FixScrollBug(o)); 15 | } 16 | 17 | ~CarouselViewScrollFixed() 18 | { 19 | MessagingCenter.Instance.Unsubscribe(Application.Current, SettingsKeyValues.MessagingCenterOrientationChangedMessage); 20 | } 21 | 22 | private void FixScrollBug(OrientationMessage orientationMessage) 23 | { 24 | if (Device.RuntimePlatform != Device.Android) 25 | return; 26 | 27 | if (orientationMessage.Orientation == Orientation.Landscape) 28 | { 29 | positionBeforeLandscape = Position; 30 | originalPeekAreaInsets = PeekAreaInsets; 31 | PeekAreaInsets = 0; 32 | } 33 | else if(orientationMessage.Orientation == Orientation.Portrait) 34 | { 35 | PeekAreaInsets = originalPeekAreaInsets; 36 | ScrollTo(positionBeforeLandscape, position: ScrollToPosition.Center, animate: true); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Controls/FrameGradient.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Controls 2 | { 3 | using Xamarin.Forms; 4 | 5 | public class FrameGradient : Frame 6 | { 7 | public static BindableProperty StartColorProperty = BindableProperty.Create(nameof(StartColor), typeof(Color), typeof(FrameGradient), Color.Default); 8 | 9 | public static BindableProperty EndColorProperty = BindableProperty.Create(nameof(EndColor), typeof(Color), typeof(FrameGradient), Color.Default); 10 | 11 | public Color StartColor 12 | { 13 | get { return (Color)GetValue(StartColorProperty); } 14 | set { SetValue(StartColorProperty, value); } 15 | } 16 | 17 | public Color EndColor 18 | { 19 | get { return (Color)GetValue(EndColorProperty); } 20 | set { SetValue(EndColorProperty, value); } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Controls/LabelTypewriter.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace DevsDNA.Application.Controls 3 | { 4 | using System; 5 | using System.Linq; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Xamarin.Forms; 9 | 10 | public class LabelTypewriter : Label 11 | { 12 | //160 unicode is Non-breaking space. On iOS 160 unicode doesn't work for this purpose 13 | private readonly char invisibleChar = Device.RuntimePlatform == Device.iOS ? ' ': Convert.ToChar(160); 14 | 15 | public LabelTypewriter() 16 | { 17 | Opacity = 0; 18 | } 19 | 20 | public Task ShowAsync(int miliseconds = 75, bool includedInitialBlink = true) 21 | { 22 | return ShowAsync(CancellationToken.None, miliseconds, includedInitialBlink); 23 | } 24 | 25 | public async Task ShowAsync(CancellationToken ct, int miliseconds = 75, bool includedInitialBlink = true) 26 | { 27 | if (string.IsNullOrEmpty(Text) || Text.Length < 2) 28 | return; 29 | 30 | ct.ThrowIfCancellationRequested(); 31 | 32 | string originalText = Text; 33 | HeightRequest = Height; 34 | string invisibleText = string.Concat(originalText.Select(c => c != ' ' ? invisibleChar : c)); 35 | 36 | Text = invisibleText; 37 | Opacity = 1; 38 | 39 | if (includedInitialBlink) 40 | { 41 | for (int i = 0; i < 3; i++) 42 | { 43 | ct.ThrowIfCancellationRequested(); 44 | Text = $"{originalText[0]}{invisibleText.Substring(1, invisibleText.Length - 2)}"; 45 | await Task.Delay(350); 46 | Text = invisibleText; 47 | await Task.Delay(350); 48 | } 49 | } 50 | string t; 51 | for (int i = 0; i < originalText.Length + 1; i++) 52 | { 53 | ct.ThrowIfCancellationRequested(); 54 | t = new string(originalText.Take(i).ToArray()); 55 | Text = $"{t}{invisibleText.Substring(i)}"; 56 | await Task.Delay(miliseconds); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Effects/DropShadowEffect.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Effects 2 | { 3 | using DevsDNA.Application.Common; 4 | using Xamarin.Forms; 5 | 6 | public class DropShadowEffect : RoutingEffect 7 | { 8 | public DropShadowEffect() : base($"{SettingsKeyValues.ResolutionGroupName}.{nameof(DropShadowEffect)}") 9 | { 10 | } 11 | 12 | public Point Offset { get; set; } 13 | public float Radius { get; set; } 14 | public Color ShadowColor { get; set; } 15 | public float Opacity { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Effects/FixedFrameClippedToBoundsEffect.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Effects 2 | { 3 | using DevsDNA.Application.Common; 4 | using Xamarin.Forms; 5 | 6 | public class FixedFrameClippedToBoundsEffect : RoutingEffect 7 | { 8 | public FixedFrameClippedToBoundsEffect() : base($"{SettingsKeyValues.ResolutionGroupName}.{nameof(FixedFrameClippedToBoundsEffect)}") 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Effects/LabelHeightAdjustEffect.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Effects 2 | { 3 | using DevsDNA.Application.Common; 4 | using Xamarin.Forms; 5 | 6 | public class LabelHeightAdjustEffect : RoutingEffect 7 | { 8 | public LabelHeightAdjustEffect() : base($"{SettingsKeyValues.ResolutionGroupName}.{nameof(LabelHeightAdjustEffect)}") 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Effects/LabelShadowEffect.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Effects 2 | { 3 | using DevsDNA.Application.Common; 4 | using Xamarin.Forms; 5 | 6 | public class LabelShadowEffect : RoutingEffect 7 | { 8 | public Color Color { get; set; } 9 | 10 | public LabelShadowEffect() : base($"{SettingsKeyValues.ResolutionGroupName}.{nameof(LabelShadowEffect)}") 11 | { 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Effects/PageStatusBarEffect.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Effects 2 | { 3 | using DevsDNA.Application.Common; 4 | using Xamarin.Forms; 5 | 6 | public class PageStatusBarEffect : RoutingEffect 7 | { 8 | public Xamarin.Forms.Color Color { get; set; } 9 | 10 | public PageStatusBarEffect() : base($"{SettingsKeyValues.ResolutionGroupName}.{nameof(PageStatusBarEffect)}") 11 | { 12 | } 13 | } 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Effects/RemoveBouncesEffect.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Effects 2 | { 3 | using DevsDNA.Application.Common; 4 | using Xamarin.Forms; 5 | 6 | public class RemoveBouncesEffect : RoutingEffect 7 | { 8 | public RemoveBouncesEffect() : base($"{SettingsKeyValues.ResolutionGroupName}.{nameof(RemoveBouncesEffect)}") 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Extensions/ExtensionMethodsString.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Extensions 2 | { 3 | using System.Text.RegularExpressions; 4 | 5 | public static class ExtensionMethodsString 6 | { 7 | public static string GetPathFromFirstImage(this string html) 8 | { 9 | Match match = Regex.Match(html, ""); 10 | if (match.Success && match.Groups.Count > 1) 11 | return match.Groups[1].Value; 12 | 13 | return null; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/AboutUs/AboutUsView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.AboutUs 2 | { 3 | using DevsDNA.Application.Features.Main; 4 | using ReactiveUI; 5 | using System; 6 | using System.Linq; 7 | using System.Reactive.Disposables; 8 | using System.Reactive.Linq; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using Xamarin.Forms; 12 | 13 | public partial class AboutUsView : ITransitionable 14 | { 15 | private CancellationTokenSource cancellationTokenSource; 16 | private CancellationToken cancellationToken; 17 | 18 | public AboutUsView(double topPadding) 19 | { 20 | InitializeComponent(); 21 | 22 | LblTitle.Margin = new Thickness(0, topPadding, 0, 0); 23 | } 24 | 25 | 26 | public IObservable ScrolledObservable { get; private set; } 27 | 28 | 29 | public async Task DoAppearingAnimationAsync() 30 | { 31 | cancellationTokenSource?.Cancel(); 32 | cancellationTokenSource?.Dispose(); 33 | cancellationTokenSource = new CancellationTokenSource(); 34 | cancellationToken = cancellationTokenSource.Token; 35 | 36 | await Task.WhenAny(LblTitle.FadeTo(1), LblSubtitle.ShowAsync(cancellationToken, 50, false)); 37 | } 38 | 39 | public async Task DoDissappearingAnimationAsync() 40 | { 41 | MainCollection.ScrollTo(0, position: ScrollToPosition.Start); 42 | await LblTitle.FadeTo(0); 43 | } 44 | 45 | public Task Reset() 46 | { 47 | return Task.CompletedTask; 48 | } 49 | 50 | public void ScrollToInit() 51 | { 52 | MainCollection.ScrollTo(0, position: ScrollToPosition.Start); 53 | } 54 | 55 | protected override CompositeDisposable CreateBindings(CompositeDisposable disposables) 56 | { 57 | base.CreateBindings(disposables); 58 | ScrolledObservable = Observable.FromEventPattern(h => MainCollection.Scrolled += h, h => MainCollection.Scrolled -= h).Select(ep => ep.EventArgs); 59 | 60 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.ThunderMates, v => v.MainCollection.ItemsSource)); 61 | 62 | 63 | return disposables; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/AboutUs/AboutUsViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.AboutUs 2 | { 3 | using DevsDNA.Application.Base; 4 | using DevsDNA.Application.Services; 5 | using ReactiveUI; 6 | using System.Collections.ObjectModel; 7 | 8 | public class AboutUsViewModel : BaseViewModel 9 | { 10 | private readonly IWeService weService; 11 | private ObservableCollection thunderMates; 12 | 13 | 14 | public AboutUsViewModel(IDependencyService dependencyService) : base(dependencyService) 15 | { 16 | weService = DependencyService.Get(); 17 | 18 | ThunderMates = new ObservableCollection(weService.GetThunderMates()); 19 | } 20 | 21 | 22 | public ObservableCollection ThunderMates 23 | { 24 | get => thunderMates; 25 | set => this.RaiseAndSetIfChanged(ref thunderMates, value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/AboutUs/IWeService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.AboutUs 2 | { 3 | using System.Collections.Generic; 4 | 5 | public interface IWeService 6 | { 7 | List GetThunderMates(); 8 | } 9 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/AboutUs/ThunderMateModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.AboutUs 2 | { 3 | using ReactiveUI; 4 | 5 | public class ThunderMateModel : ReactiveObject 6 | { 7 | public string Name { get; set; } 8 | public string Title { get; set; } 9 | public string Photo { get; set; } 10 | public string Description { get; set; } 11 | public string FunnyDescription { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Main/ITransitionable.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Main 2 | { 3 | using System.Threading.Tasks; 4 | 5 | public interface ITransitionable 6 | { 7 | Task Reset(); 8 | Task DoAppearingAnimationAsync(); 9 | Task DoDissappearingAnimationAsync(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Main/TabButton.xaml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 10 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Main/TabMain.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Main 2 | { 3 | public enum TabMain 4 | { 5 | Unassigned = -1, 6 | News = 0, 7 | Videos = 1, 8 | SocialNetwork = 2, 9 | AboutUs = 3 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/BlogItemModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public class BlogItemModel 7 | { 8 | public string Id { get; set; } 9 | public string Title { get; set; } 10 | public string Content { get; set; } 11 | public string Description { get; set; } 12 | public string Image { get; set; } 13 | public DateTimeOffset? Created { get; set; } 14 | public DateTimeOffset? LastUpdate { get; set; } 15 | public List Authors { get; set; } 16 | public List Categories { get; set; } 17 | public List Tags { get; set; } 18 | public IEnumerable Images { get; set; } 19 | public string Link { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/BlogModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public class BlogModel 7 | { 8 | public string Id { get; set; } 9 | public string Title { get; set; } 10 | public List Posts { get; set; } 11 | public string Description { get; set; } 12 | public DateTimeOffset LastUpdate { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/IRssFeedService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News 2 | { 3 | using System; 4 | 5 | public interface IRssFeedService 6 | { 7 | IObservable GetBlogModel(); 8 | } 9 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/NewsDetail/HtmlFont.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News.NewsDetail 2 | { 3 | using Xamarin.Forms; 4 | 5 | public class HtmlFont 6 | { 7 | public HtmlFont(string fontPath, Color color) 8 | { 9 | Path = fontPath; 10 | Color = color.ToHex().Remove(1, 2); 11 | } 12 | 13 | public string Path { get; } 14 | public string Color { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/NewsDetail/NewsHtmlSettings.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News.NewsDetail 2 | { 3 | public class NewsHtmlSettings 4 | { 5 | public string Html { get; set; } 6 | public string Domain { get; set; } 7 | public HtmlFont RegularFont { get; set; } 8 | public HtmlFont HeadingFont { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/NewsDetail/WebviewNews.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News.NewsDetail 2 | { 3 | using Xamarin.Forms; 4 | 5 | public class WebviewNews : WebView 6 | { 7 | public static BindableProperty NewsHtmlSettingsProperty = BindableProperty.Create(nameof(NewsHtmlSettings), typeof(NewsHtmlSettings), typeof(WebviewNews), null, propertyChanged: OnNewsHtmlSettingsChanged); 8 | 9 | public NewsHtmlSettings NewsHtmlSettings 10 | { 11 | get { return (NewsHtmlSettings)GetValue(NewsHtmlSettingsProperty); } 12 | set { SetValue(NewsHtmlSettingsProperty, value); } 13 | } 14 | 15 | private static void OnNewsHtmlSettingsChanged(BindableObject bindable, object oldValue, object newValue) 16 | { 17 | if (bindable is WebviewNews webviewNews && newValue is NewsHtmlSettings newsHtmlSettings) 18 | { 19 | var newsDetailParser = new NewsDetailParser(newsHtmlSettings); 20 | HtmlWebViewSource htmlWebViewSource = new HtmlWebViewSource() 21 | { 22 | Html = newsDetailParser.BeautifyHtml() 23 | }; 24 | 25 | webviewNews.Source = htmlWebViewSource; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/NewsView.xaml: -------------------------------------------------------------------------------- 1 |  2 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/NewsView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News 2 | { 3 | using DevsDNA.Application.Features.Main; 4 | using ReactiveUI; 5 | using System.Reactive.Disposables; 6 | using System.Threading.Tasks; 7 | using System; 8 | using System.Reactive.Linq; 9 | using Xamarin.Forms; 10 | using System.Reactive; 11 | 12 | public partial class NewsView : ITransitionable 13 | { 14 | private const double carouselItemRatio = 1.5; 15 | 16 | public NewsView() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | public IObservable ScrolledObservable { get; private set; } 22 | public IObservable OpeningDetailObservable { get; private set; } 23 | 24 | 25 | public Task DoAppearingAnimationAsync() 26 | { 27 | return CarouselNews.OnAppearingAsync(); 28 | } 29 | 30 | public Task DoDissappearingAnimationAsync() 31 | { 32 | return CarouselNews.OnDisappearingAsync(); 33 | } 34 | 35 | public Task Reset() 36 | { 37 | return Task.CompletedTask; 38 | } 39 | 40 | 41 | protected override CompositeDisposable CreateBindings(CompositeDisposable disposables) 42 | { 43 | base.CreateBindings(disposables); 44 | 45 | disposables.Add(this.WhenAnyValue(view => view.ViewModel.BlogItemsModel).Subscribe(CarouselNews.UpdateItemsSource)); 46 | disposables.Add(ViewModel.WhenAnyValue(vm => vm.BlogItemsModel).Select(blogItem => blogItem == null).Subscribe(isLoading => 47 | { 48 | if (isLoading) 49 | StartLoadingAnimation(LottieLoading); 50 | else 51 | StopLoadingAnimation(LottieLoading); 52 | })); 53 | ScrolledObservable = Observable.FromEventPattern(h => CarouselNews.Scrolled += h, h => CarouselNews.Scrolled -= h).Select(ep => ep.EventArgs); 54 | OpeningDetailObservable = ViewModel.OpenDetailCommand.IsExecuting.Where(c => c).Select(_ => Unit.Default); 55 | 56 | return disposables; 57 | } 58 | 59 | protected override void OnFirstSizeAllocated(double width, double height) 60 | { 61 | base.OnFirstSizeAllocated(width, height); 62 | 63 | AdjustCarouselItemsRatio(); 64 | } 65 | 66 | private void AdjustCarouselItemsRatio() 67 | { 68 | Size carouselItemSize = NewsCarouselItemView.CalculateVisibleArea(new Size(CarouselNews.Width, CarouselNews.Height)); 69 | CarouselNews.AdjustCarouselItemsRatio(carouselItemRatio, carouselItemSize); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/News/NewsViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.News 2 | { 3 | using DevsDNA.Application.Base; 4 | using DevsDNA.Application.Services; 5 | using ReactiveUI; 6 | using System.Reactive.Linq; 7 | using System.Collections.Generic; 8 | using System; 9 | using System.Reactive; 10 | using System.Threading.Tasks; 11 | using Xamarin.Forms; 12 | using Plugin.SharedTransitions; 13 | 14 | public class NewsViewModel : BaseViewModel 15 | { 16 | private IList blogItemsModel; 17 | 18 | public NewsViewModel(IDependencyService dependencyService) : base(dependencyService) 19 | { 20 | OpenDetailCommand = ReactiveCommand.CreateFromTask(OpenDetailCommandExecuteAsync); 21 | Disposables.Add(dependencyService.Get().BlogModel.ObserveOn(RxApp.MainThreadScheduler).Subscribe(bm => BlogItemsModel = bm?.Posts)); 22 | Disposables.Add(OpenDetailCommand.ThrownExceptions.Subscribe(LogService.LogError, LogService.LogError)); 23 | } 24 | 25 | public IList BlogItemsModel 26 | { 27 | get => blogItemsModel; 28 | set => this.RaiseAndSetIfChanged(ref blogItemsModel, value); 29 | } 30 | 31 | public ReactiveCommand OpenDetailCommand { get; } 32 | 33 | private async Task OpenDetailCommandExecuteAsync(BlogItemModel blogItemModel) 34 | { 35 | INavigation navigation = (Application.Current.MainPage as NavigationPage)?.Navigation; 36 | SharedTransitionNavigationPage.SetTransitionSelectedGroup(navigation.NavigationStack[0], blogItemModel.Id); 37 | await navigation.PushAsync(new NewsDetailView() { ViewModel = new NewsDetailViewModel(DependencyService, blogItemModel) }); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Attachment.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | public class Attachment 4 | { 5 | public AttachmentType Type { get; set; } 6 | public string Description { get; set; } 7 | public string Image { get; set; } 8 | public string Title { get; set; } 9 | public string Url { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/AttachmentType.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | public enum AttachmentType 4 | { 5 | Image, 6 | Share 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/APIModels/Attachment.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels 2 | { 3 | using Newtonsoft.Json; 4 | 5 | public class Attachment 6 | { 7 | [JsonProperty("description")] 8 | public string Description { get; set; } 9 | 10 | [JsonProperty("title")] 11 | public string Title { get; set; } 12 | 13 | [JsonProperty("media")] 14 | public Media Media { get; set; } 15 | 16 | [JsonProperty("type")] 17 | public string Type { get; set; } 18 | 19 | [JsonProperty("url")] 20 | public string Url { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/APIModels/Attachments.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels 2 | { 3 | using Newtonsoft.Json; 4 | using System.Collections.Generic; 5 | 6 | public class Attachments 7 | { 8 | [JsonProperty("data")] 9 | public IEnumerable Data { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/APIModels/Image.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels 2 | { 3 | using Newtonsoft.Json; 4 | 5 | public class Image 6 | { 7 | [JsonProperty("height")] 8 | public long Height { get; set; } 9 | 10 | [JsonProperty("width")] 11 | public long Width { get; set; } 12 | 13 | [JsonProperty("src")] 14 | public string Src { get; set; } 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/APIModels/Media.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels 2 | { 3 | using Newtonsoft.Json; 4 | 5 | public class Media 6 | { 7 | [JsonProperty("image")] 8 | public Image Image { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/APIModels/PageFeed.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels 2 | { 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Web; 8 | 9 | public class PageFeed 10 | { 11 | [JsonProperty("data")] 12 | public IEnumerable Posts { get; set; } 13 | 14 | public IList ToPosts() 15 | { 16 | if (Posts == null) 17 | return null; 18 | 19 | List posts = new List(); 20 | foreach (var post in Posts.Where(p => !string.IsNullOrEmpty(p.Message))) 21 | { 22 | posts.Add(new PostModel() 23 | { 24 | Id = post.Id, 25 | Message = post.Message, 26 | CreationDate = DateTime.Parse(post.CreatedTime, null, System.Globalization.DateTimeStyles.None), 27 | Attachments = post.Attachments?.Data?.Where(d => d.Type == "photo" || d.Type == "share") 28 | .Select(d => new SocialNetwork.Attachment() 29 | { 30 | Description = d.Description, 31 | Image = d.Media?.Image?.Src, 32 | Title = d.Title, 33 | Type = d.Type == "photo" ? AttachmentType.Image : AttachmentType.Share, 34 | Url = GetUrl(d) 35 | })?.ToList() 36 | }); 37 | 38 | } 39 | 40 | return posts; 41 | } 42 | 43 | private string GetUrl(Attachment attachment) 44 | { 45 | if (attachment.Type == "share" && Uri.TryCreate(attachment.Url, UriKind.Absolute, out Uri uri)) 46 | { 47 | return HttpUtility.ParseQueryString(uri.Query).Get("u"); 48 | } 49 | return attachment.Url; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/APIModels/Post.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels 2 | { 3 | using Newtonsoft.Json; 4 | 5 | public class Post 6 | { 7 | [JsonProperty("id")] 8 | public string Id { get; set; } 9 | 10 | [JsonProperty("created_time")] 11 | public string CreatedTime { get; set; } 12 | 13 | [JsonProperty("message")] 14 | public string Message { get; set; } 15 | 16 | [JsonProperty("attachments")] 17 | public Attachments Attachments { get; set; } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/FacebookService.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.Dependency(typeof(DevsDNA.Application.Features.SocialNetwork.Facebook.FacebookService))] 2 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook 3 | { 4 | using DevsDNA.Application.Helpers; 5 | using DevsDNA.Application.Common; 6 | using Refit; 7 | using System.Collections.Generic; 8 | using System; 9 | using System.Reactive.Linq; 10 | 11 | public class FacebookService : IFacebookService 12 | { 13 | private readonly IFacebookAPIService facebookAPIService; 14 | 15 | public FacebookService() : this(RestService.For(SettingsKeyValues.FacebookEndPoint)) 16 | { 17 | } 18 | 19 | public FacebookService(IFacebookAPIService facebookAPIService) 20 | { 21 | this.facebookAPIService = facebookAPIService; 22 | } 23 | 24 | public IObservable> GetPosts() 25 | { 26 | return facebookAPIService.GetPageFeed(SettingsKeyValues.FacebookPageId, Secrets.FacebookAccessToken).Select(p => p?.ToPosts()); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/IFacebookAPIService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.Facebook 2 | { 3 | using DevsDNA.Application.Features.SocialNetwork.Facebook.APIModels; 4 | using Refit; 5 | using System; 6 | 7 | public interface IFacebookAPIService 8 | { 9 | [Get("/v7.0/{page-id}/feed?fields=id,created_time,message,attachments&limit=25&access_token={access-token}")] 10 | IObservable GetPageFeed([AliasAs("page-id")] string pageId, [AliasAs("access-token")] string accessToken); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/Facebook/IFacebookService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public interface IFacebookService 7 | { 8 | IObservable> GetPosts(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostControl.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using DevsDNA.Application.Features.Main; 4 | using System.Threading.Tasks; 5 | using Xamarin.Forms; 6 | using DevsDNA.Application.Strings; 7 | 8 | public abstract class PostControl : ContentView, ITransitionable 9 | { 10 | protected abstract double StartingTranslation { get; } 11 | protected abstract Label LabelMessage { get; } 12 | protected abstract Label LabelAccountAndDate { get; } 13 | protected abstract ContentView ContentViewMain { get; } 14 | 15 | 16 | public Task DoAppearingAnimationAsync() 17 | { 18 | ViewExtensions.CancelAnimations(ContentViewMain); 19 | TranslateToInitialPosition(); 20 | return ContentViewMain.TranslateTo(0, 0, 500, Easing.CubicOut); 21 | } 22 | 23 | public Task DoDissappearingAnimationAsync() 24 | { 25 | ViewExtensions.CancelAnimations(ContentViewMain); 26 | return ContentViewMain.TranslateTo(StartingTranslation, 0, 500, Easing.CubicOut); 27 | } 28 | 29 | public Task Reset() 30 | { 31 | ViewExtensions.CancelAnimations(ContentViewMain); 32 | TranslateToInitialPosition(); 33 | return Task.CompletedTask; 34 | } 35 | 36 | 37 | protected override void OnBindingContextChanged() 38 | { 39 | base.OnBindingContextChanged(); 40 | 41 | DoAppearingAnimationAsync(); 42 | 43 | if (BindingContext is PostModel postModel) 44 | { 45 | SetUIProperties(postModel); 46 | } 47 | } 48 | 49 | protected void TranslateToInitialPosition() 50 | { 51 | ContentViewMain.TranslationX = StartingTranslation; 52 | } 53 | 54 | 55 | private void SetUIProperties(PostModel postModel) 56 | { 57 | LabelMessage.Text = postModel.Message; 58 | LabelAccountAndDate.Text = string.Concat(Strings.SocialNetworkPostAccount, " · ", string.Format("{0:dd MMMM}", postModel.CreationDate)); 59 | 60 | AutomationProperties.SetName(ContentViewMain, postModel.Message); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostLeftControl.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using System; 4 | using Xamarin.Essentials; 5 | using Xamarin.Forms; 6 | 7 | public partial class PostLeftControl : PostControl 8 | { 9 | private readonly double startingTranslationX; 10 | 11 | public PostLeftControl() 12 | { 13 | InitializeComponent(); 14 | startingTranslationX = -(DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Density) - Math.Abs(Padding.Left); 15 | TranslateToInitialPosition(); 16 | } 17 | 18 | protected override double StartingTranslation => startingTranslationX; 19 | protected override ContentView ContentViewMain => ViewMain; 20 | protected override Label LabelMessage => LblMessage; 21 | protected override Label LabelAccountAndDate => LblAccountAndDate; 22 | } 23 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public class PostModel 7 | { 8 | public string Id { get; set; } 9 | public string Message { get; set; } 10 | public DateTime CreationDate { get; set; } 11 | public IList Attachments { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostParser/PostSpan.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.PostParser 2 | { 3 | public class PostSpan 4 | { 5 | public PostSpan(string text, SpanType type) 6 | { 7 | Text = text; 8 | Type = type; 9 | } 10 | 11 | public string Text { get; } 12 | public SpanType Type { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostParser/PostTextParser.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.PostParser 2 | { 3 | using System.Collections.Generic; 4 | using System.Text.RegularExpressions; 5 | 6 | public static class PostTextParser 7 | { 8 | private const string urlPattern = @"\b(?:https?://|www\.)\S+\b"; 9 | private const string hashtagPattern = @"(?:#)\w+"; 10 | private static readonly string urlOrHashtagPattern = string.Concat(urlPattern, "|", hashtagPattern); 11 | 12 | public static List Parse(string text) 13 | { 14 | List postSpans = new List(); 15 | 16 | var lastIndex = 0; 17 | foreach (Match match in Regex.Matches(text, urlOrHashtagPattern)) 18 | { 19 | postSpans.Add(new PostSpan(text[lastIndex..match.Index], SpanType.Plain)); 20 | postSpans.Add(new PostSpan(match.Value,match.Value.StartsWith("#")? SpanType.Hashtag: SpanType.Url)); 21 | lastIndex = match.Index + match.Length; 22 | } 23 | 24 | if(lastIndex < text.Length) 25 | postSpans.Add(new PostSpan(text.Substring(lastIndex), SpanType.Plain)); 26 | 27 | return postSpans; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostParser/SpanType.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork.PostParser 2 | { 3 | public enum SpanType 4 | { 5 | Plain, 6 | Url, 7 | Hashtag 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostRigthControl.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using System; 4 | using Xamarin.Essentials; 5 | using Xamarin.Forms; 6 | 7 | public partial class PostRightControl : PostControl 8 | { 9 | private readonly double startingTranslationX; 10 | 11 | public PostRightControl() 12 | { 13 | InitializeComponent(); 14 | startingTranslationX = (DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Density) + Math.Abs(Padding.Right); 15 | TranslateToInitialPosition(); 16 | } 17 | 18 | protected override double StartingTranslation => startingTranslationX; 19 | protected override ContentView ContentViewMain => ViewMain; 20 | protected override Label LabelMessage => LblMessage; 21 | protected override Label LabelAccountAndDate => LblAccountAndDate; 22 | } 23 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/PostsDataTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using System.Linq; 4 | using Xamarin.Forms; 5 | 6 | public class PostsDataTemplateSelector : DataTemplateSelector 7 | { 8 | private readonly DataTemplate leftTemplate = new DataTemplate(typeof(PostLeftControl)); 9 | private readonly DataTemplate rightTemplate = new DataTemplate(typeof(PostRightControl)); 10 | 11 | protected override DataTemplate OnSelectTemplate(object item, BindableObject container) 12 | { 13 | int itemIndex = ((CollectionView)container).ItemsSource.Cast().ToList().IndexOf(item); 14 | return (itemIndex % 2 == 0) ? leftTemplate : rightTemplate; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/SocialNetworkView.xaml: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 31 | 32 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/SocialNetwork/SocialNetworkViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.SocialNetwork 2 | { 3 | using DevsDNA.Application.Base; 4 | using DevsDNA.Application.Services; 5 | using ReactiveUI; 6 | using System.Collections.Generic; 7 | using System.Reactive.Linq; 8 | using System; 9 | using System.Reactive; 10 | using System.Threading.Tasks; 11 | using Xamarin.Essentials; 12 | 13 | public class SocialNetworkViewModel : BaseViewModel 14 | { 15 | private IList postsModel; 16 | private PostModel selectedPostModel; 17 | 18 | public SocialNetworkViewModel(IDependencyService dependencyService) : base(dependencyService) 19 | { 20 | Disposables.Add(dependencyService.Get().FacebookPostsModel.ObserveOn(RxApp.MainThreadScheduler).Subscribe(pm => PostsModel = pm)); 21 | OpenPostDetailCommand = ReactiveCommand.Create(OpenPostDetailCommandExecute); 22 | OpenLinkCommand = ReactiveCommand.CreateFromTask(OpenLinkCommandExecuteAsync); 23 | Disposables.Add(OpenPostDetailCommand.ThrownExceptions.Subscribe(LogService.LogError, LogService.LogError)); 24 | Disposables.Add(OpenLinkCommand.ThrownExceptions.Subscribe(LogService.LogError, LogService.LogError)); 25 | } 26 | 27 | public IList PostsModel 28 | { 29 | get => postsModel; 30 | set => this.RaiseAndSetIfChanged(ref postsModel, value); 31 | } 32 | 33 | public PostModel SelectedPostModel 34 | { 35 | get => selectedPostModel; 36 | set => this.RaiseAndSetIfChanged(ref selectedPostModel, value); 37 | } 38 | 39 | public ReactiveCommand OpenPostDetailCommand { get; } 40 | 41 | public ReactiveCommand OpenLinkCommand { get; } 42 | 43 | 44 | private void OpenPostDetailCommandExecute(PostModel postModel) 45 | { 46 | SelectedPostModel = postModel; 47 | } 48 | 49 | private Task OpenLinkCommandExecuteAsync(string url) 50 | { 51 | var uri = new UriBuilder(url).Uri; 52 | return Browser.OpenAsync(uri, BrowserLaunchMode.External); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/APIModels/Content.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos.APIModels 2 | { 3 | using System.Xml.Serialization; 4 | 5 | [XmlRoot(Namespace = "http://search.yahoo.com/mrss/")] 6 | public class Content 7 | { 8 | [XmlAttribute(AttributeName = "url")] 9 | public string Url { get; set; } 10 | 11 | [XmlAttribute(AttributeName = "width")] 12 | public int Width { get; set; } 13 | 14 | [XmlAttribute(AttributeName = "height")] 15 | public int Height { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/APIModels/Entry.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos.APIModels 2 | { 3 | using System.Xml.Serialization; 4 | 5 | [XmlRoot(Namespace = "http://www.w3.org/2005/Atom")] 6 | public class Entry 7 | { 8 | [XmlElement(ElementName = "videoId", Namespace = "http://www.youtube.com/xml/schemas/2015")] 9 | public string Id { get; set; } 10 | 11 | [XmlElement(ElementName = "title")] 12 | public string Title { get; set; } 13 | 14 | [XmlElement(ElementName = "link")] 15 | public Link Link { get; set; } 16 | 17 | [XmlElement(ElementName = "published")] 18 | public string Published { get; set; } 19 | 20 | [XmlElement(ElementName = "group", Namespace = "http://search.yahoo.com/mrss/")] 21 | public Media Media { get; set; } 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/APIModels/Feed.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos.APIModels 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Xml.Serialization; 6 | 7 | [XmlRoot(ElementName = "feed", Namespace = "http://www.w3.org/2005/Atom")] 8 | public class Feed 9 | { 10 | [XmlElement(ElementName = "entry")] 11 | public List Entries { get; set; } 12 | 13 | public IList ToVideos() 14 | { 15 | if (Entries == null) 16 | return null; 17 | 18 | List videos = new List(); 19 | foreach (var entry in Entries) 20 | { 21 | videos.Add(new VideoModel() 22 | { 23 | Id = entry.Id, 24 | Title = entry.Title, 25 | Description = entry.Media?.Description, 26 | CreationDate = DateTime.Parse(entry.Published, null, System.Globalization.DateTimeStyles.None), 27 | Url = entry.Link?.Url, 28 | Image = entry.Media?.Thumbnail?.Url, 29 | Width = entry?.Media?.Content?.Width ?? 0, 30 | Height = entry?.Media?.Content?.Height ?? 0, 31 | }); 32 | } 33 | 34 | return videos; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/APIModels/Link.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos.APIModels 2 | { 3 | using System.Xml.Serialization; 4 | 5 | [XmlRoot(Namespace = "http://www.w3.org/2005/Atom")] 6 | public class Link 7 | { 8 | [XmlAttribute(AttributeName = "href")] 9 | public string Url { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/APIModels/Media.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos.APIModels 2 | { 3 | using System.Xml.Serialization; 4 | 5 | [XmlRoot(Namespace = "http://search.yahoo.com/mrss/")] 6 | public class Media 7 | { 8 | [XmlElement(ElementName = "description")] 9 | public string Description { get; set; } 10 | 11 | [XmlElement(ElementName = "thumbnail")] 12 | public Thumbnail Thumbnail { get; set; } 13 | 14 | [XmlElement(ElementName = "content")] 15 | public Content Content { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/APIModels/Thumbnail.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos.APIModels 2 | { 3 | using System.Xml.Serialization; 4 | 5 | [XmlRoot(Namespace = "http://search.yahoo.com/mrss/")] 6 | public class Thumbnail 7 | { 8 | [XmlAttribute(AttributeName = "url")] 9 | public string Url { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/IYoutubeAPIService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos 2 | { 3 | using DevsDNA.Application.Features.Videos.APIModels; 4 | using Refit; 5 | using System; 6 | 7 | public interface IYouTubeAPIService 8 | { 9 | 10 | [Get("/feeds/videos.xml?channel_id={channel-id}")] 11 | IObservable GetChannelFeed([AliasAs("channel-id")] string channelId); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/IYoutubeService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public interface IYouTubeService 7 | { 8 | IObservable> GetVideos(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/VideoDetail/VideoDetailView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos 2 | { 3 | using ReactiveUI; 4 | using System; 5 | using System.Reactive; 6 | using System.Reactive.Disposables; 7 | using System.Reactive.Linq; 8 | using Xamarin.Forms; 9 | 10 | public partial class VideoDetailView 11 | { 12 | public VideoDetailView() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | protected override CompositeDisposable CreateBindings(CompositeDisposable disposables) 18 | { 19 | base.CreateBindings(disposables); 20 | 21 | IObservable> observableVideoReadyEvent = Observable.FromEventPattern(v => WebViewYoutube.OnVideoReady += v, v => WebViewYoutube.OnVideoReady -= v); 22 | disposables.Add(observableVideoReadyEvent.ObserveOn(RxApp.MainThreadScheduler).Subscribe(ep => OnVideoReady())); 23 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.VideoModel, v => v.WebViewYoutube.VideoModel)); 24 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.CloseCommand, v => v.ButtonClose.Command)); 25 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.VideoModel, v => v.WebViewYoutube.VideoModel)); 26 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.VideoModel, v => v.WebViewYoutube.IsVisible, videoModel => videoModel != null)); 27 | disposables.Add(this.OneWayBind(ViewModel, vm => vm.VideoModel, v => v.IndicatorVideoLoading.IsVisible, videoModel => videoModel != null)); 28 | 29 | return base.CreateBindings(disposables); 30 | } 31 | 32 | protected override void OnSizeAllocated(double width, double height) 33 | { 34 | WebViewYoutube.HeightRequest = (ViewModel.VideoModel.Height / ViewModel.VideoModel.Width) * width; 35 | base.OnSizeAllocated(width, height); 36 | } 37 | 38 | private void OnVideoReady() 39 | { 40 | IndicatorVideoLoading.IsVisible = false; 41 | IndicatorVideoLoading.IsRunning = false; 42 | ImageThumbnail.FadeTo(0); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/VideoDetail/VideoDetailViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos 2 | { 3 | using DevsDNA.Application.Base; 4 | using DevsDNA.Application.Services; 5 | using ReactiveUI; 6 | using System; 7 | using System.Reactive; 8 | using System.Threading.Tasks; 9 | using Xamarin.Forms; 10 | 11 | public class VideoDetailViewModel : BaseViewModel 12 | { 13 | public VideoDetailViewModel(IDependencyService dependencyService, VideoModel videoModel) : base(dependencyService) 14 | { 15 | VideoModel = videoModel; 16 | CloseCommand = ReactiveCommand.CreateFromTask(CloseCommandExecuteAsync); 17 | } 18 | 19 | public VideoDetailViewModel(VideoModel videoModel) : this(CustomDependencyService.Instance, videoModel) 20 | { 21 | } 22 | 23 | 24 | public VideoModel VideoModel { get; } 25 | 26 | public ReactiveCommand CloseCommand { get; } 27 | 28 | 29 | public override async Task AppearingAsync() 30 | { 31 | await base.AppearingAsync(); 32 | Disposables.Add(CloseCommand.ThrownExceptions.Subscribe(LogService.LogError, LogService.LogError)); 33 | } 34 | 35 | 36 | private Task CloseCommandExecuteAsync() 37 | { 38 | INavigation navigation = (Application.Current.MainPage as NavigationPage)?.Navigation; 39 | return navigation.PopAsync(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/VideoModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos 2 | { 3 | using System; 4 | 5 | public class VideoModel 6 | { 7 | public string Id { get; set; } 8 | public string Title { get; set; } 9 | public string Description { get; set; } 10 | public DateTime CreationDate { get; set; } 11 | public string Image { get; set; } 12 | public string Url { get; set; } 13 | public double Width { get; set; } 14 | public double Height { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/VideosViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Features.Videos 2 | { 3 | using DevsDNA.Application.Base; 4 | using DevsDNA.Application.Services; 5 | using Plugin.SharedTransitions; 6 | using ReactiveUI; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Reactive; 10 | using System.Reactive.Linq; 11 | using System.Threading.Tasks; 12 | using Xamarin.Essentials; 13 | using Xamarin.Forms; 14 | 15 | public class VideosViewModel : BaseViewModel 16 | { 17 | private IList videosModel; 18 | 19 | public VideosViewModel(IDependencyService dependencyService) : base(dependencyService) 20 | { 21 | OpenVideoCommand = ReactiveCommand.CreateFromTask(OpenVideoCommandExecuteAsync); 22 | ShareVideoCommand = ReactiveCommand.CreateFromTask(ShareVideoCommandExecuteAsync); 23 | Disposables.Add(dependencyService.Get().YouTubeVideosModel.ObserveOn(RxApp.MainThreadScheduler).Subscribe(v => VideosModel = v)); 24 | Disposables.Add(OpenVideoCommand.ThrownExceptions.Subscribe(LogService.LogError, LogService.LogError)); 25 | Disposables.Add(ShareVideoCommand.ThrownExceptions.Subscribe(LogService.LogError, LogService.LogError)); 26 | } 27 | 28 | public IList VideosModel 29 | { 30 | get => videosModel; 31 | set => this.RaiseAndSetIfChanged(ref videosModel, value); 32 | } 33 | 34 | public ReactiveCommand OpenVideoCommand { get; } 35 | public ReactiveCommand ShareVideoCommand { get; } 36 | 37 | 38 | private async Task OpenVideoCommandExecuteAsync(VideoModel videoModel) 39 | { 40 | INavigation navigation = (Application.Current.MainPage as NavigationPage)?.Navigation; 41 | SharedTransitionNavigationPage.SetTransitionSelectedGroup(navigation.NavigationStack[0], videoModel.Id); 42 | await navigation.PushAsync(new VideoDetailView() { ViewModel = new VideoDetailViewModel(videoModel) }); 43 | } 44 | 45 | private Task ShareVideoCommandExecuteAsync(VideoModel videoModel) 46 | { 47 | return Share.RequestAsync(new ShareTextRequest 48 | { 49 | Uri = videoModel.Url, 50 | Title = videoModel.Title, 51 | Text = videoModel.Title 52 | }); 53 | } 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Features/Videos/YoutubeService.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xamarin.Forms.Dependency(typeof(DevsDNA.Application.Features.Videos.YouTubeService))] 2 | namespace DevsDNA.Application.Features.Videos 3 | { 4 | using DevsDNA.Application.Common; 5 | using Refit; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Reactive.Linq; 9 | 10 | public class YouTubeService : IYouTubeService 11 | { 12 | private readonly IYouTubeAPIService youTubeAPIService; 13 | 14 | public YouTubeService() : this(RestService.For(SettingsKeyValues.YouTubeEndPoint, new RefitSettings(new XmlContentSerializer()))) 15 | { 16 | } 17 | 18 | public YouTubeService(IYouTubeAPIService youTubeAPIService) 19 | { 20 | this.youTubeAPIService = youTubeAPIService; 21 | } 22 | 23 | public IObservable> GetVideos() 24 | { 25 | return youTubeAPIService.GetChannelFeed(SettingsKeyValues.YouTubeChannelId).Select(v => v?.ToVideos()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Black.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Bold.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-ExtraBold.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Light.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Medium.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Regular.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/Heebo-Thin.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/SpaceMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/SpaceMono-Bold.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Messages/Orientation.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Messages 2 | { 3 | public enum Orientation 4 | { 5 | Portrait, 6 | Landscape 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Messages/OrientationMessage.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Messages 2 | { 3 | public class OrientationMessage 4 | { 5 | public OrientationMessage(Orientation orientation) 6 | { 7 | Orientation = orientation; 8 | } 9 | 10 | public Orientation Orientation { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/AccessibilityChecker/IAccessibilityCheckerService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | using System; 4 | 5 | public interface IAccessibilityCheckerService 6 | { 7 | bool IsVoiceAssistantActive(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/AppLogger/ILogService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | public interface ILogService 7 | { 8 | void Log(string message, [CallerMemberName] string callerMemberName = null); 9 | void Log(string message, string tag, [CallerMemberName] string callerMemberName = null); 10 | void LogError(Exception ex); 11 | void LogError(Exception ex, [CallerMemberName] string callerMemberName = null); 12 | void LogError(Exception ex, string tag, [CallerMemberName] string callerMemberName = null); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/CustomDependencyService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | using Xamarin.Forms; 4 | 5 | public class CustomDependencyService : IDependencyService 6 | { 7 | private static CustomDependencyService instance; 8 | 9 | private CustomDependencyService() 10 | { 11 | 12 | } 13 | 14 | public static IDependencyService Instance 15 | { 16 | get 17 | { 18 | instance ??= new CustomDependencyService(); 19 | return instance; 20 | } 21 | } 22 | 23 | public TService Get() where TService : class 24 | { 25 | return DependencyService.Get(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/DataService/DataType.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | public enum DataType 4 | { 5 | All, 6 | News, 7 | Videos, 8 | SocialNetwork 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/DataService/IDataService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | using DevsDNA.Application.Features.News; 4 | using DevsDNA.Application.Features.SocialNetwork; 5 | using DevsDNA.Application.Features.Videos; 6 | using System.Collections.Generic; 7 | using System.Reactive.Subjects; 8 | 9 | public interface IDataService 10 | { 11 | public ISubject> FacebookPostsModel { get; } 12 | 13 | public ISubject> YouTubeVideosModel { get; } 14 | 15 | public ISubject BlogModel { get; } 16 | 17 | public void Retrieve(DataType dataType); 18 | 19 | public void Clear(DataType dataType); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/IDependencyService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | public interface IDependencyService 4 | { 5 | TService Get() where TService : class; 6 | } 7 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/Notifications/INotificationManagerService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | using DevsDNA.Application.Services.Notifications; 4 | using System.Threading.Tasks; 5 | 6 | public interface INotificationManagerService 7 | { 8 | Task ProcessNotificationAsync(PushNotificationsType pushType); 9 | } 10 | } -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/Notifications/INotificationService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | public interface INotificationService 4 | { 5 | void EnableNotifications(); 6 | void DisableNotifications(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/Notifications/PushNotificationInfo.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services.Notifications 2 | { 3 | public class PushNotificationInfo 4 | { 5 | public string Title { get; set; } 6 | public string Message { get; set; } 7 | public PushNotificationsType Type { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/Notifications/PushNotificationsType.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services.Notifications 2 | { 3 | public enum PushNotificationsType 4 | { 5 | News = 0, 6 | Video = 1, 7 | SocialNetwork = 2, 8 | None = 999 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevsDNA.Application/DevsDNA.Application/DevsDNA.Application/Services/Track/ITrackService.cs: -------------------------------------------------------------------------------- 1 | namespace DevsDNA.Application.Services 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Runtime.CompilerServices; 6 | 7 | public interface ITrackService 8 | { 9 | void ConfigureAppCenter(); 10 | void TrackError(Exception ex, [CallerMemberName] string methodCaller = null); 11 | void TrackError(Exception ex, Dictionary properties, [CallerMemberName] string methodCaller = null); 12 | void TrackEvent(string message, [CallerMemberName] string methodCaller = null); 13 | void TrackEvent(string message, Dictionary properties, [CallerMemberName] string methodCaller = null); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/images/banner.png -------------------------------------------------------------------------------- /images/detailScreenAndroid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/images/detailScreenAndroid.jpg -------------------------------------------------------------------------------- /images/detailScreenIOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/images/detailScreenIOS.png -------------------------------------------------------------------------------- /images/mainScreenAndroid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/images/mainScreenAndroid.jpg -------------------------------------------------------------------------------- /images/mainScreenIOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevsDNA/DevsDNA-Application/5a96c12e3cc4e4b23ee9dd0960c3a6157ef3be06/images/mainScreenIOS.png --------------------------------------------------------------------------------