├── .gitignore ├── Core ├── App.xaml ├── App.xaml.cs ├── Controls │ ├── AlwaysScrollView.cs │ ├── Badge.cs │ ├── CarouselView.cs │ ├── ChartView.cs │ ├── HVScrollGridView.cs │ ├── HorizontalViewNative.cs │ ├── ListView.cs │ ├── ParallaxScrollView.cs │ ├── WhatsAppImage.cs │ └── WhatsAppViewCell.cs ├── Converters │ ├── BooleanInverterConverter.cs │ ├── NubankDateTimeConverter.cs │ ├── NubankPriceToDollarConverter.cs │ ├── NubankPriceToLocalConverter.cs │ ├── NubankTagsToStringConverter.cs │ └── WhatsAppDateTimeConverter.cs ├── Core.csproj ├── CorePage.xaml ├── CorePage.xaml.cs ├── Effects │ └── TwoLinesLabelEffect.cs ├── Enums │ └── WhatsAppChatListMessageStatusEnum.cs ├── Externsions │ ├── DateTimeOffsetExtension.cs │ └── MovieExtension.cs ├── Interfaces │ ├── IMobileApp.cs │ ├── INetflix.cs │ ├── INubank.cs │ ├── ITwitch.cs │ └── IWhatsApp.cs ├── Models │ ├── MobileAppModel.cs │ ├── Netflix │ │ └── MovieModel.cs │ ├── Nubank │ │ ├── NubankHeaderInvoiceModel.cs │ │ ├── NubankHeaderModel.cs │ │ └── NubankHeaderSummaryModel.cs │ ├── NubankTimelineModel.cs │ ├── Twitch │ │ └── TwitchChannelModel.cs │ ├── WhatsApp │ │ ├── ChatModel.cs │ │ └── GroupChatModel.cs │ └── WhatsAppInfoModel.cs ├── Services │ ├── MobileAppService.cs │ ├── NetflixService.cs │ ├── NubankService.cs │ ├── TwitchService.cs │ └── WhatsAppService.cs ├── Templates │ ├── Nubank │ │ ├── HeaderInvoice.xaml │ │ ├── HeaderInvoice.xaml.cs │ │ ├── HeaderSummary.xaml │ │ └── HeaderSummary.xaml.cs │ ├── NubankHeaderTemplate.cs │ ├── WhatsAppChatList │ │ ├── GroupMessage.xaml │ │ ├── GroupMessage.xaml.cs │ │ ├── SingleMessage.xaml │ │ └── SingleMessage.xaml.cs │ └── WhatsAppChatListTemplate.cs ├── ViewModels │ ├── BaseViewModel.cs │ ├── MobileAppViewModel.cs │ ├── NetflixHomeViewModel.cs │ ├── NubankTimelineViewModel.cs │ ├── TwitchHomeViewModel.cs │ ├── WhatsAppChatListViewModel.cs │ └── WhatsAppInfoViewModel.cs └── Views │ ├── FacebookLoginView.xaml │ ├── FacebookLoginView.xaml.cs │ ├── MobileAppView.xaml │ ├── MobileAppView.xaml.cs │ ├── NetflixHomeView.xaml │ ├── NetflixHomeView.xaml.cs │ ├── NubankTimelineView.xaml │ ├── NubankTimelineView.xaml.cs │ ├── TwitchHomeView.xaml │ ├── TwitchHomeView.xaml.cs │ ├── WhatsAppChatListView.xaml │ ├── WhatsAppChatListView.xaml.cs │ ├── WhatsAppInfoView.xaml │ └── WhatsAppInfoView.xaml.cs ├── Droid ├── Assets │ ├── AboutAssets.txt │ ├── Gotham-Bold.ttf │ └── Gotham-Light.ttf ├── Core.Droid.csproj ├── Effects │ └── TwoLinesLabelEffect.cs ├── MainActivity.cs ├── Properties │ ├── AndroidManifest.xml │ └── AssemblyInfo.cs ├── Resources │ ├── AboutResources.txt │ ├── drawable-hdpi │ │ └── icon.png │ ├── drawable-xhdpi │ │ └── icon.png │ ├── drawable-xxhdpi │ │ └── icon.png │ ├── drawable │ │ ├── icon.png │ │ ├── nubank_cat_bullet_green.png │ │ ├── nubank_cat_bullet_red.png │ │ ├── nubank_cat_card.png │ │ ├── nubank_cat_eletronics.png │ │ ├── nubank_cat_play.png │ │ ├── nubank_cat_recreation.png │ │ ├── nubank_cat_restaurant.png │ │ ├── nubank_cat_services.png │ │ ├── nubank_cat_star.png │ │ ├── nubank_cat_transport.png │ │ ├── twitch_thumbnail.png │ │ ├── whatsapp_mute.png │ │ └── whatsapp_read.png │ ├── layout │ │ ├── Tabbar.axml │ │ └── Toolbar.axml │ └── values │ │ └── styles.xml └── packages.config ├── Interfaces.sln ├── LICENSE ├── README.md ├── art ├── nubank-timeline-android.png ├── nubank-timeline-ios.png ├── whatsapp-chat-list-android.png └── whatsapp-chat-list-ios.png └── iOS ├── AppDelegate.cs ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Core.iOS.csproj ├── Effects └── TwoLinesLabelEffect.cs ├── Entitlements.plist ├── Info.plist ├── LaunchScreen.storyboard ├── Main.cs ├── Renderers ├── AlwaysScrollViewRenderer.cs ├── WhatsAppViewCellRenderer.cs └── iOSHorizontalViewRenderer.cs ├── Resources ├── Gotham-Bold.otf ├── Gotham-Light.otf ├── nubank_cat_bullet_green.png ├── nubank_cat_bullet_red.png ├── nubank_cat_card.png ├── nubank_cat_eletronics.png ├── nubank_cat_play.png ├── nubank_cat_recreation.png ├── nubank_cat_restaurant.png ├── nubank_cat_services.png ├── nubank_cat_star.png ├── nubank_cat_transport.png ├── twitch_thumbnail.png ├── whatsapp_mute.png └── whatsapp_read.png └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | # Autosave files 2 | *~ 3 | 4 | # build 5 | [Oo]bj/ 6 | [Bb]in/ 7 | packages/ 8 | TestResults/ 9 | 10 | # globs 11 | Makefile.in 12 | *.DS_Store 13 | *.sln.cache 14 | *.suo 15 | *.cache 16 | *.pidb 17 | *.userprefs 18 | *.usertasks 19 | config.log 20 | config.make 21 | config.status 22 | aclocal.m4 23 | install-sh 24 | autom4te.cache/ 25 | *.user 26 | *.tar.gz 27 | tarballs/ 28 | test-results/ 29 | Thumbs.db 30 | .vs/ 31 | 32 | # Mac bundle stuff 33 | *.dmg 34 | *.app 35 | 36 | # resharper 37 | *_Resharper.* 38 | *.Resharper 39 | 40 | # dotCover 41 | *.dotCover 42 | 43 | # MFractor 44 | .mfractor 45 | 46 | # Project 47 | Droid/Resources/Resource.designer.cs 48 | -------------------------------------------------------------------------------- /Core/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 26 | 27 | 33 | 34 | #f7f7f7 35 | #808080 36 | #d5d5d5 37 | #00c0cd 38 | 39 | 45 | 46 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Core/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Core.Interfaces; 2 | using Core.Services; 3 | using Core.ViewModels; 4 | using Core.Views; 5 | using Prism; 6 | using Prism.DryIoc; 7 | using Prism.Ioc; 8 | using Xamarin.Forms; 9 | 10 | namespace Core 11 | { 12 | public partial class App : PrismApplication 13 | { 14 | public App() : base(null) {} 15 | public App(IPlatformInitializer platformInitializer) : base(platformInitializer) {} 16 | 17 | protected override async void OnInitialized() 18 | { 19 | InitializeComponent(); 20 | 21 | Device.SetFlags(new string[] { "MediaElement_Experimental", "Shapes_Experimental" }); 22 | 23 | await NavigationService.NavigateAsync("NavigationPage/MobileAppView"); 24 | } 25 | 26 | protected override void RegisterTypes(IContainerRegistry containerRegistry) 27 | { 28 | containerRegistry.RegisterForNavigation(); 29 | containerRegistry.RegisterForNavigation(); 30 | containerRegistry.RegisterForNavigation(); 31 | containerRegistry.RegisterForNavigation(); 32 | containerRegistry.RegisterForNavigation(); 33 | containerRegistry.RegisterForNavigation(); 34 | containerRegistry.RegisterForNavigation(); 35 | containerRegistry.RegisterForNavigation(); 36 | 37 | containerRegistry.RegisterSingleton(); 38 | containerRegistry.RegisterSingleton(); 39 | containerRegistry.RegisterSingleton(); 40 | containerRegistry.RegisterSingleton(); 41 | containerRegistry.RegisterSingleton(); 42 | } 43 | 44 | protected override void OnStart() 45 | { 46 | // Handle when your app starts 47 | } 48 | 49 | protected override void OnSleep() 50 | { 51 | // Handle when your app sleeps 52 | } 53 | 54 | protected override void OnResume() 55 | { 56 | // Handle when your app resumes 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Core/Controls/AlwaysScrollView.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace Core.Controls 4 | { 5 | public class AlwaysScrollView : ScrollView 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Core/Controls/Badge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | 4 | namespace Core.Controls 5 | { 6 | public class Badge : AbsoluteLayout 7 | { 8 | protected Label Label; 9 | protected BoxView Box; 10 | 11 | public static readonly BindableProperty TextProperty = 12 | BindableProperty.Create( 13 | "Text", 14 | typeof(String), 15 | typeof(Badge), 16 | "" 17 | ); 18 | 19 | //Box color property 20 | public static readonly BindableProperty BoxColorProperty = 21 | BindableProperty.Create( 22 | "BoxColor", 23 | typeof(Color), 24 | typeof(Badge), 25 | Color.Default 26 | ); 27 | 28 | 29 | public Badge() 30 | { 31 | var size = 20; 32 | var fontSize = 14; 33 | 34 | HeightRequest = size; 35 | WidthRequest = size; 36 | 37 | // Box 38 | Box = new BoxView 39 | { 40 | CornerRadius = HeightRequest / 2 41 | }; 42 | 43 | Box.SetBinding(BackgroundColorProperty, new Binding("BoxColor", source: this)); 44 | Children.Add(Box, new Rectangle(0, 0, 1.0, 1.0), AbsoluteLayoutFlags.All); 45 | 46 | // Label 47 | Label = new Label 48 | { 49 | TextColor = Color.White, 50 | FontSize = fontSize, 51 | FontAttributes = FontAttributes.Bold, 52 | HorizontalTextAlignment = TextAlignment.Center, 53 | VerticalTextAlignment = TextAlignment.Center 54 | }; 55 | 56 | Label.SetBinding(Label.TextProperty, new Binding("Text", BindingMode.OneWay, source: this)); 57 | 58 | Children.Add(Label, new Rectangle(0, 0, 1.0, 1.0), AbsoluteLayoutFlags.All); 59 | 60 | // Auto width 61 | SetBinding(WidthRequestProperty, new Binding("Text", BindingMode.OneWay, new BadgeWidthConverter(WidthRequest), source: this)); 62 | 63 | // If not value = hide 64 | SetBinding(IsVisibleProperty, new Binding("Text", BindingMode.OneWay, new BadgeVisibleValueConverter(), source: this)); 65 | 66 | // Default color 67 | BoxColor = Color.Red; 68 | } 69 | 70 | // Text 71 | public string Text 72 | { 73 | get { return (string)GetValue(TextProperty); } 74 | set { SetValue(TextProperty, value); } 75 | } 76 | 77 | // Color of the box 78 | public Color BoxColor 79 | { 80 | get { return (Color)GetValue(BoxColorProperty); } 81 | set { SetValue(BoxColorProperty, value); } 82 | } 83 | 84 | } 85 | 86 | class BadgeWidthConverter : IValueConverter 87 | { 88 | 89 | // Width ratio. 90 | const double widthRatio = 0.33; 91 | 92 | //Width of the base. 93 | readonly double baseWidth; 94 | 95 | public BadgeWidthConverter(double baseWidth) 96 | { 97 | this.baseWidth = baseWidth; 98 | } 99 | 100 | 101 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 102 | { 103 | var text = value as string; 104 | if ((text != null) && (text.Length > 1)) 105 | { 106 | return baseWidth * (1 + widthRatio * (text.Length - 1)); 107 | } 108 | return baseWidth; 109 | } 110 | 111 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 112 | { 113 | throw new NotImplementedException(); 114 | } 115 | } 116 | 117 | class BadgeVisibleValueConverter : IValueConverter 118 | { 119 | 120 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 121 | { 122 | var text = value as string; 123 | 124 | if (text == "0") 125 | return false; 126 | 127 | return !String.IsNullOrEmpty(text); 128 | } 129 | 130 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 131 | { 132 | throw new NotImplementedException(); 133 | } 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Core/Controls/CarouselView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CarouselView.FormsPlugin.Abstractions; 3 | 4 | namespace Core.Controls 5 | { 6 | public class CarouselView : CarouselViewControl 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Core/Controls/ChartView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Core.Controls 4 | { 5 | public class ChartView : Microcharts.Forms.ChartView 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Core/Controls/HVScrollGridView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Windows.Input; 5 | using Xamarin.Forms; 6 | 7 | namespace Core.Controls 8 | { 9 | public class HVScrollGridView : Grid 10 | { 11 | private ICommand _innerSelectedCommand; 12 | private readonly ScrollView _scrollView; 13 | private readonly StackLayout _itemsStackLayout; 14 | 15 | public event EventHandler SelectedItemChanged; 16 | 17 | public StackOrientation ListOrientation { get; set; } 18 | 19 | public double Spacing { get; set; } 20 | 21 | public static readonly BindableProperty SelectedCommandProperty = 22 | BindableProperty.Create("SelectedCommand", typeof(ICommand), typeof(HVScrollGridView), null); 23 | 24 | public static readonly BindableProperty ItemsSourceProperty = 25 | BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(HVScrollGridView), default(IEnumerable), BindingMode.TwoWay, propertyChanged: ItemsSourceChanged); 26 | 27 | public static readonly BindableProperty SelectedItemProperty = 28 | BindableProperty.Create("SelectedItem", typeof(object), typeof(HVScrollGridView), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged); 29 | 30 | public static readonly BindableProperty ItemTemplateProperty = 31 | BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(HVScrollGridView), default(DataTemplate)); 32 | 33 | public ICommand SelectedCommand 34 | { 35 | get { return (ICommand)GetValue(SelectedCommandProperty); } 36 | set { SetValue(SelectedCommandProperty, value); } 37 | } 38 | 39 | public IEnumerable ItemsSource 40 | { 41 | get { return (IEnumerable)GetValue(ItemsSourceProperty); } 42 | set { SetValue(ItemsSourceProperty, value); } 43 | } 44 | 45 | public object SelectedItem 46 | { 47 | get { return (object)GetValue(SelectedItemProperty); } 48 | set { SetValue(SelectedItemProperty, value); } 49 | } 50 | 51 | public DataTemplate ItemTemplate 52 | { 53 | get { return (DataTemplate)GetValue(ItemTemplateProperty); } 54 | set { SetValue(ItemTemplateProperty, value); } 55 | } 56 | 57 | private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue) 58 | { 59 | var itemsLayout = (HVScrollGridView)bindable; 60 | itemsLayout.SetItems(); 61 | } 62 | 63 | public HVScrollGridView() 64 | { 65 | _scrollView = new ScrollView(); 66 | 67 | _itemsStackLayout = new StackLayout 68 | { 69 | BackgroundColor = BackgroundColor, 70 | Padding = Padding, 71 | Spacing = Spacing, 72 | HorizontalOptions = LayoutOptions.FillAndExpand 73 | }; 74 | 75 | _scrollView.BackgroundColor = BackgroundColor; 76 | _scrollView.Content = _itemsStackLayout; 77 | Children.Add(_scrollView); 78 | } 79 | 80 | protected virtual void SetItems() 81 | { 82 | _itemsStackLayout.Children.Clear(); 83 | _itemsStackLayout.Spacing = Spacing; 84 | 85 | _innerSelectedCommand = new Command(view => 86 | { 87 | SelectedItem = view.BindingContext; 88 | SelectedItem = null; // Allowing item second time selection 89 | }); 90 | 91 | _itemsStackLayout.Orientation = ListOrientation; 92 | _scrollView.Orientation = ListOrientation == StackOrientation.Horizontal 93 | ? ScrollOrientation.Horizontal 94 | : ScrollOrientation.Vertical; 95 | 96 | if (ItemsSource == null) 97 | { 98 | return; 99 | } 100 | 101 | foreach (var item in ItemsSource) 102 | { 103 | _itemsStackLayout.Children.Add(GetItemView(item)); 104 | } 105 | 106 | _itemsStackLayout.BackgroundColor = BackgroundColor; 107 | SelectedItem = null; 108 | } 109 | 110 | protected virtual View GetItemView(object item) 111 | { 112 | var content = ItemTemplate.CreateContent(); 113 | var view = content as View; 114 | 115 | if (view == null) 116 | { 117 | return null; 118 | } 119 | 120 | view.BindingContext = item; 121 | 122 | var gesture = new TapGestureRecognizer 123 | { 124 | Command = _innerSelectedCommand, 125 | CommandParameter = view 126 | }; 127 | 128 | AddGesture(view, gesture); 129 | 130 | return view; 131 | } 132 | 133 | private void AddGesture(View view, TapGestureRecognizer gesture) 134 | { 135 | view.GestureRecognizers.Add(gesture); 136 | 137 | var layout = view as Layout; 138 | 139 | if (layout == null) 140 | { 141 | return; 142 | } 143 | 144 | foreach (var child in layout.Children) 145 | { 146 | AddGesture(child, gesture); 147 | } 148 | } 149 | 150 | private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue) 151 | { 152 | var itemsView = (HVScrollGridView)bindable; 153 | if (newValue == oldValue && newValue != null) 154 | { 155 | return; 156 | } 157 | 158 | itemsView.SelectedItemChanged?.Invoke(itemsView, EventArgs.Empty); 159 | 160 | if (itemsView.SelectedCommand?.CanExecute(newValue) ?? false) 161 | { 162 | itemsView.SelectedCommand?.Execute(newValue); 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /Core/Controls/HorizontalViewNative.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using Xamarin.Forms; 5 | 6 | namespace Core.Controls 7 | { 8 | public class HorizontalViewNative : View 9 | { 10 | public static readonly BindableProperty ItemsSourceProperty = 11 | BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(HorizontalViewNative), default(IEnumerable), BindingMode.TwoWay, propertyChanged: ItemsSourceChanged); 12 | 13 | public static readonly BindableProperty ItemTemplateProperty = 14 | BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(HVScrollGridView), default(DataTemplate)); 15 | 16 | public static readonly BindableProperty ItemHeightProperty = 17 | BindableProperty.Create("ItemHeight", typeof(int), typeof(HVScrollGridView), default(int)); 18 | 19 | public static readonly BindableProperty ItemWidthProperty = 20 | BindableProperty.Create("ItemWidth", typeof(int), typeof(HVScrollGridView), default(int)); 21 | 22 | public IEnumerable ItemsSource 23 | { 24 | get { return (IEnumerable)GetValue(ItemsSourceProperty); } 25 | set { SetValue(ItemsSourceProperty, value); } 26 | } 27 | 28 | public DataTemplate ItemTemplate 29 | { 30 | get { return (DataTemplate)GetValue(ItemTemplateProperty); } 31 | set { SetValue(ItemTemplateProperty, value); } 32 | } 33 | 34 | public int ItemHeight 35 | { 36 | get { return (int)GetValue(ItemHeightProperty); } 37 | set { SetValue(ItemHeightProperty, value); } 38 | } 39 | 40 | public int ItemWidth 41 | { 42 | get { return (int)GetValue(ItemWidthProperty); } 43 | set { SetValue(ItemWidthProperty, value); } 44 | } 45 | 46 | private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue) 47 | { 48 | var itemsLayout = (HorizontalViewNative)bindable; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Core/Controls/ListView.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using Xamarin.Forms; 3 | 4 | namespace Core.Controls 5 | { 6 | public class ListView : Xamarin.Forms.ListView 7 | { 8 | public static readonly BindableProperty ItemTappedCommandProperty = 9 | BindableProperty.Create( 10 | nameof(ItemTappedCommand), 11 | typeof(ICommand), 12 | typeof(ListView), 13 | null 14 | ); 15 | 16 | public ICommand ItemTappedCommand 17 | { 18 | get { return (ICommand)GetValue(ItemTappedCommandProperty); } 19 | set { SetValue(ItemTappedCommandProperty, value); } 20 | } 21 | 22 | public ListView() : base(ListViewCachingStrategy.RecycleElement) 23 | { 24 | ItemTapped += ListView_ItemTapped; 25 | } 26 | 27 | ~ListView() 28 | { 29 | ItemTapped -= ListView_ItemTapped; 30 | } 31 | 32 | private void ListView_ItemTapped(object sender, ItemTappedEventArgs e) 33 | { 34 | if (ItemTappedCommand != null && ItemTappedCommand.CanExecute(null)) 35 | ItemTappedCommand.Execute(e.Item); 36 | 37 | SelectedItem = null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Core/Controls/ParallaxScrollView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | 4 | namespace Core.Controls 5 | { 6 | public class ParallaxScrollView : AlwaysScrollView 7 | { 8 | public ParallaxScrollView() 9 | { 10 | Scrolled += (sender, e) => Parallax(); 11 | } 12 | 13 | public static readonly BindableProperty ParallaxViewProperty = 14 | BindableProperty.Create( 15 | nameof(ParallaxView), 16 | typeof(View), 17 | typeof(ParallaxScrollView), 18 | null 19 | ); 20 | 21 | public View ParallaxView 22 | { 23 | get { return (View)GetValue(ParallaxViewProperty); } 24 | set { SetValue(ParallaxViewProperty, value); } 25 | } 26 | 27 | double height; 28 | public void Parallax() 29 | { 30 | if (ParallaxView == null || Device.RuntimePlatform == Device.UWP) 31 | return; 32 | 33 | if (height <= 0) 34 | height = ParallaxView.Height; 35 | 36 | var y = -(int)((float)ScrollY / 2.5f); 37 | if (y < 0) 38 | { 39 | //Move the Image's Y coordinate a fraction of the ScrollView's Y position 40 | ParallaxView.Scale = 1; 41 | ParallaxView.TranslationY = y; 42 | } 43 | else if (Device.RuntimePlatform == Device.iOS) 44 | { 45 | //Calculate a scale that equalizes the height vs scroll 46 | double newHeight = height + (ScrollY * -1); 47 | ParallaxView.Scale = newHeight / height; 48 | ParallaxView.TranslationY = -(ScrollY / 2); 49 | } 50 | else 51 | { 52 | ParallaxView.Scale = 1; 53 | ParallaxView.TranslationY = 0; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Core/Controls/WhatsAppImage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using FFImageLoading.Forms; 3 | using FFImageLoading.Transformations; 4 | 5 | namespace Core.Controls 6 | { 7 | public class WhatsAppImage : CachedImage 8 | { 9 | public WhatsAppImage() 10 | { 11 | WidthRequest = 60; 12 | HeightRequest = 60; 13 | DownsampleToViewSize = true; 14 | 15 | Transformations.Add(new CircleTransformation()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Core/Controls/WhatsAppViewCell.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace Core.Controls 4 | { 5 | public class WhatsAppViewCell : ViewCell 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Core/Converters/BooleanInverterConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xamarin.Forms; 4 | 5 | namespace Core.Converters 6 | { 7 | public class BooleanInverterConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | var newValue = value as bool?; 12 | if (!newValue.HasValue) 13 | return false; 14 | 15 | return !newValue.Value; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Core/Converters/NubankDateTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xamarin.Forms; 4 | 5 | namespace Core.Converters 6 | { 7 | public class NubankDateTimeConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | var dateTime = value as DateTimeOffset?; 12 | if (!dateTime.HasValue) 13 | return string.Empty; 14 | 15 | var now = DateTimeOffset.Now; 16 | 17 | if (dateTime.Value.Year == now.Year) 18 | { 19 | if (dateTime.Value.Month == now.Month) 20 | { 21 | if (dateTime.Value.Day == now.Day) 22 | return dateTime.Value.ToString("HH:mm"); 23 | 24 | if (dateTime.Value.Day == now.AddDays(-1).Day) 25 | return "Ontem"; 26 | 27 | var dayOfWeek = dateTime.Value.DayOfWeek; 28 | string textDayOfWeek = string.Empty; 29 | 30 | switch (dayOfWeek) 31 | { 32 | case DayOfWeek.Sunday: 33 | textDayOfWeek = "Domingo"; 34 | break; 35 | case DayOfWeek.Monday: 36 | textDayOfWeek = "Segunda"; 37 | break; 38 | case DayOfWeek.Tuesday: 39 | textDayOfWeek = "Terça"; 40 | break; 41 | case DayOfWeek.Wednesday: 42 | textDayOfWeek = "Quarta"; 43 | break; 44 | case DayOfWeek.Thursday: 45 | textDayOfWeek = "Quinta"; 46 | break; 47 | case DayOfWeek.Friday: 48 | textDayOfWeek = "Sexta"; 49 | break; 50 | case DayOfWeek.Saturday: 51 | textDayOfWeek = "Sábado"; 52 | break; 53 | } 54 | 55 | if (dateTime.Value.Day >= now.AddDays(-6).Day) 56 | return textDayOfWeek; 57 | } 58 | 59 | return dateTime.Value.ToString("dd MMM"); 60 | } 61 | 62 | return dateTime.Value.ToString("dd MMM yyyy"); 63 | } 64 | 65 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 66 | { 67 | throw new NotImplementedException(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Core/Converters/NubankPriceToDollarConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xamarin.Forms; 4 | 5 | namespace Core.Converters 6 | { 7 | public class NubankPriceToDollarConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | var price = value as double?; 12 | if (!price.HasValue) 13 | return string.Empty; 14 | 15 | return price.Value.ToString("C2", new CultureInfo("en-US")); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Core/Converters/NubankPriceToLocalConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xamarin.Forms; 4 | 5 | namespace Core.Converters 6 | { 7 | public class NubankPriceToLocalConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | var price = value as double?; 12 | if (!price.HasValue) 13 | return string.Empty; 14 | 15 | return price.Value.ToString("C2", new CultureInfo("pt-BR")); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Core/Converters/NubankTagsToStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using Xamarin.Forms; 5 | 6 | namespace Core.Converters 7 | { 8 | public class NubankTagsToStringConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | var tags = value as List; 13 | if (tags == null) 14 | return string.Empty; 15 | 16 | var textTags = string.Empty; 17 | 18 | foreach (var tag in tags) 19 | textTags += $"#{tag} "; 20 | 21 | return textTags.Trim(); 22 | } 23 | 24 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Core/Converters/WhatsAppDateTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xamarin.Forms; 4 | 5 | namespace Core.Converters 6 | { 7 | public class WhatsAppDateTimeConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | var dateTime = value as DateTimeOffset?; 12 | if (!dateTime.HasValue) 13 | return string.Empty; 14 | 15 | var now = DateTimeOffset.Now; 16 | 17 | if (dateTime.Value.Date == DateTime.Today) 18 | return dateTime.Value.ToString("t"); 19 | 20 | var diffDays = (now.Date - dateTime.Value.Date).Days; 21 | if (diffDays <= 6) 22 | { 23 | if (diffDays == 1) 24 | { 25 | return "Ontem"; 26 | } 27 | 28 | switch (dateTime.Value.DayOfWeek) 29 | { 30 | case DayOfWeek.Sunday: 31 | return "Domingo"; 32 | case DayOfWeek.Monday: 33 | return "Segunda"; 34 | case DayOfWeek.Tuesday: 35 | return "Terça"; 36 | case DayOfWeek.Wednesday: 37 | return "Quarta"; 38 | case DayOfWeek.Thursday: 39 | return "Quinta"; 40 | case DayOfWeek.Friday: 41 | return "Sexta"; 42 | case DayOfWeek.Saturday: 43 | return "Sábado"; 44 | } 45 | } 46 | 47 | return dateTime.Value.ToString("d"); 48 | } 49 | 50 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 51 | { 52 | throw new NotImplementedException(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Core/Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | 5 | 6 | 7 | 8.0 8 | 9 | 10 | 8.0 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Core/CorePage.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | -------------------------------------------------------------------------------- /Core/CorePage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace Core 4 | { 5 | public partial class CorePage : ContentPage 6 | { 7 | public CorePage() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Core/Effects/TwoLinesLabelEffect.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | 3 | namespace Core.Effects 4 | { 5 | public class TwoLinesLabelEffect : RoutingEffect 6 | { 7 | public TwoLinesLabelEffect() : base("App.TwoLinesLabelEffect") 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/Enums/WhatsAppChatListMessageStatusEnum.cs: -------------------------------------------------------------------------------- 1 | namespace Core.Enums 2 | { 3 | public enum WhatsAppChatListMessageStatusEnum 4 | { 5 | None, 6 | Waiting, 7 | Sent, 8 | Read 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Core/Externsions/DateTimeOffsetExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Core.Externsions 4 | { 5 | public static class DateTimeOffsetExtension 6 | { 7 | public static string ToWhatsApp(this DateTimeOffset dateTime) 8 | { 9 | var now = DateTimeOffset.Now; 10 | 11 | if (dateTime.Date == DateTime.Today) 12 | return dateTime.ToString("t"); 13 | 14 | var diffDays = (now.Date - dateTime.Date).Days; 15 | if (diffDays <= 6) { 16 | if (diffDays == 1) { 17 | return "Ontem"; 18 | } 19 | 20 | switch (dateTime.DayOfWeek) 21 | { 22 | case DayOfWeek.Sunday: 23 | return "Domingo"; 24 | case DayOfWeek.Monday: 25 | return "Segunda"; 26 | case DayOfWeek.Tuesday: 27 | return "Terça"; 28 | case DayOfWeek.Wednesday: 29 | return "Quarta"; 30 | case DayOfWeek.Thursday: 31 | return "Quinta"; 32 | case DayOfWeek.Friday: 33 | return "Sexta"; 34 | case DayOfWeek.Saturday: 35 | return "Sábado"; 36 | } 37 | } 38 | 39 | return dateTime.ToString("d"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Core/Externsions/MovieExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Collections.Generic; 3 | using Core.Models.Netflix; 4 | 5 | namespace Core.Externsions 6 | { 7 | public static class MovieExtension 8 | { 9 | public static IList GroupByCategory( 10 | this IList movies) 11 | { 12 | return movies.GroupBy(m => m.Category) 13 | .Select( 14 | group => new GroupMovieModel( 15 | group.Key, 16 | group.ToList() 17 | ) 18 | ) 19 | .ToList(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/Interfaces/IMobileApp.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Core.Models; 3 | 4 | namespace Core.Interfaces 5 | { 6 | public interface IMobileApp 7 | { 8 | IList GetApps(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Core/Interfaces/INetflix.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Core.Models.Netflix; 4 | 5 | namespace Core.Interfaces 6 | { 7 | public interface INetflix 8 | { 9 | IList GetMovies(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/Interfaces/INubank.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Core.Models; 3 | using Core.Models.Nubank; 4 | 5 | namespace Core.Interfaces 6 | { 7 | public interface INubank 8 | { 9 | IList GetHeader(); 10 | IList GetTimeline(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Core/Interfaces/ITwitch.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Core.Models.Twitch; 3 | 4 | namespace Core.Interfaces 5 | { 6 | public interface ITwitch 7 | { 8 | IList GetChannels(); 9 | IList GetGroupedChannels(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/Interfaces/IWhatsApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Core.Models; 4 | using Core.Models.WhatsApp; 5 | 6 | namespace Core.Interfaces 7 | { 8 | public interface IWhatsApp 9 | { 10 | IList GetChats(); 11 | WhatsAppInfoModel GetInfo(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Core/Models/MobileAppModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Core.Models 4 | { 5 | public class MobileAppModel 6 | { 7 | public string ViewName { get; set; } 8 | public string Name { get; set; } 9 | public bool UseModalNavigation { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Core/Models/Netflix/MovieModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Core.Models.Netflix 5 | { 6 | public class MovieModel 7 | { 8 | public string Photo { get; set; } 9 | public string Category { get; set; } 10 | } 11 | 12 | public class GroupMovieModel : List 13 | { 14 | public string GroupName { get; set; } 15 | 16 | public GroupMovieModel(string groupName, IList movies) 17 | { 18 | GroupName = groupName; 19 | AddRange(movies); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Core/Models/Nubank/NubankHeaderInvoiceModel.cs: -------------------------------------------------------------------------------- 1 | namespace Core.Models.Nubank 2 | { 3 | public class NubankHeaderInvoiceModel : NubankHeaderModel 4 | { 5 | public double Total { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Core/Models/Nubank/NubankHeaderModel.cs: -------------------------------------------------------------------------------- 1 | namespace Core.Models.Nubank 2 | { 3 | public class NubankHeaderModel 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Core/Models/Nubank/NubankHeaderSummaryModel.cs: -------------------------------------------------------------------------------- 1 | using Microcharts; 2 | 3 | namespace Core.Models.Nubank 4 | { 5 | public class NubankHeaderSummaryModel : NubankHeaderModel 6 | { 7 | public LineChart Chart { get; set; } 8 | public string Description { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Core/Models/NubankTimelineModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Core.Models 5 | { 6 | public class NubankTimelineModel 7 | { 8 | public string Category { get; set; } 9 | public string CategoryIcon { get; set; } 10 | public string TextColor { get; set; } 11 | public string Description { get; set; } 12 | public double? LocalPrice { get; set; } 13 | public bool IsDollar { get; set; } 14 | public double? DollarPrice { get; set; } 15 | public bool IsInstallment { get; set; } 16 | public int? NumberOfInstallments { get; set; } 17 | public DateTimeOffset CreatedAt { get; set; } 18 | public bool IsReversed { get; set; } 19 | public IList Tags { get; set; } 20 | 21 | public NubankTimelineModel() 22 | { 23 | Tags = new List(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Core/Models/Twitch/TwitchChannelModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Core.Models.Twitch 5 | { 6 | public class TwitchChannelModel 7 | { 8 | public string Name { get; set; } 9 | public string Avatar { get; set; } 10 | public string Description { get; set; } 11 | public string Category { get; set; } 12 | public IList Tags { get; set; } 13 | public string GroupName { get; set; } 14 | public int TotalWatching { get; set; } 15 | 16 | public TwitchChannelModel() 17 | { 18 | Tags = new List(); 19 | } 20 | } 21 | 22 | public class GroupTwitchChannelModel : List 23 | { 24 | public string GroupName { get; set; } 25 | 26 | public GroupTwitchChannelModel(string groupName, List channels) 27 | { 28 | GroupName = groupName; 29 | AddRange(channels); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Core/Models/WhatsApp/ChatModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Core.Models.WhatsApp 4 | { 5 | public class ChatModel 6 | { 7 | public string Photo { get; set; } 8 | public string SentFrom { get; set; } 9 | public DateTimeOffset CreatedAt { get; set; } 10 | public string Message { get; set; } 11 | public string MessageIcon { get; set; } 12 | public bool IsMuted { get; set; } 13 | public int TotalUnread { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Core/Models/WhatsApp/GroupChatModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Core.Models.WhatsApp 4 | { 5 | public class GroupChatModel : ChatModel 6 | { 7 | public string GroupName { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Core/Models/WhatsAppInfoModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Core.Models 4 | { 5 | public class WhatsAppInfoModel 6 | { 7 | public string Photo { get; set; } 8 | public string Name { get; set; } 9 | public string Phone { get; set; } 10 | public string Status { get; set; } 11 | public DateTimeOffset StatusAt { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Core/Services/MobileAppService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Core.Interfaces; 4 | using Core.Models; 5 | using Core.ViewModels; 6 | using Core.Views; 7 | 8 | namespace Core.Services 9 | { 10 | public class MobileAppService : IMobileApp 11 | { 12 | private IList _apps; 13 | 14 | public MobileAppService() 15 | { 16 | _apps = new List(); 17 | 18 | _apps.Add(GetMobileApp( 19 | typeof(WhatsAppChatListView).Name, 20 | "WhatsApp - Lista chats", 21 | false 22 | )); 23 | 24 | _apps.Add(GetMobileApp( 25 | typeof(NubankTimelineView).Name, 26 | "Nubank - Timeline", 27 | false 28 | )); 29 | 30 | _apps.Add(GetMobileApp( 31 | typeof(WhatsAppInfoView).Name, 32 | "WhatsApp - Info", 33 | false 34 | )); 35 | 36 | _apps.Add(GetMobileApp( 37 | typeof(NetflixHomeView).Name, 38 | "Netflix - Home", 39 | false 40 | )); 41 | 42 | _apps.Add(GetMobileApp( 43 | $"NavigationPage/{typeof(TwitchHomeView).Name}", 44 | "Twitch - Home", 45 | true 46 | )); 47 | 48 | _apps.Add(GetMobileApp( 49 | typeof(FacebookLoginView).Name, 50 | "Facebook Login", 51 | false 52 | )); 53 | } 54 | 55 | private MobileAppModel GetMobileApp( 56 | string viewName, 57 | string name, 58 | bool useModalNavigation) 59 | { 60 | return new MobileAppModel() 61 | { 62 | ViewName = viewName, 63 | Name = name, 64 | UseModalNavigation = useModalNavigation 65 | }; 66 | } 67 | 68 | public IList GetApps() 69 | { 70 | return _apps; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Core/Services/NetflixService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Core.Interfaces; 4 | using Core.Models.Netflix; 5 | 6 | namespace Core.Services 7 | { 8 | public class NetflixService : INetflix 9 | { 10 | private IList _movies; 11 | 12 | public NetflixService() 13 | { 14 | _movies = new List(); 15 | 16 | _movies.Add(GetMovie( 17 | photo: "https://occ-0-999-1001.1.nflxso.net/art/98c02/fe062be973c1e5213a630913fce3e2422d198c02.jpg", 18 | category: "Continue Watching for Junior" 19 | )); 20 | 21 | _movies.Add(GetMovie( 22 | photo: "https://occ-0-299-300.1.nflxso.net/art/36f99/0a6572bd35a35792ed7eb6d1575b3d96b1436f99.jpg", 23 | category: "Continue Watching for Junior" 24 | )); 25 | 26 | _movies.Add(GetMovie( 27 | photo: "https://ia.media-imdb.com/images/M/MV5BZDNhNzhkNDctOTlmOS00NWNmLWEyODQtNWMxM2UzYmJiNGMyXkEyXkFqcGdeQXVyNTMxMjgxMzA@._V1_UY268_CR4,0,182,268_AL_.jpg", 28 | category: "Continue Watching for Junior" 29 | )); 30 | 31 | _movies.Add(GetMovie( 32 | photo: "https://www.ennetflix.pe/media/20/dr-house_70136117.jpg", 33 | category: "Continue Watching for Junior" 34 | )); 35 | 36 | _movies.Add(GetMovie( 37 | photo: "https://assets.nflxext.com/us/boxshots/ghd/80013773.jpg", 38 | category: "Watch It again" 39 | )); 40 | 41 | _movies.Add(GetMovie( 42 | photo: "https://assets.nflxext.com/us/boxshots/ghd/70257818.jpg", 43 | category: "Watch It again" 44 | )); 45 | 46 | _movies.Add(GetMovie( 47 | photo: "https://ia.media-imdb.com/images/M/MV5BMTkyMDkwNDIyMV5BMl5BanBnXkFtZTgwNDU1OTEwNjE@._V1_UX182_CR0,0,182,268_AL_.jpg", 48 | category: "Watch It again" 49 | )); 50 | 51 | _movies.Add(GetMovie( 52 | photo: "https://ia.media-imdb.com/images/M/MV5BMTg1ODg4NjUzNF5BMl5BanBnXkFtZTgwOTU5NDc3MTE@._V1_UX182_CR0,0,182,268_AL_.jpg", 53 | category: "Watch It again" 54 | )); 55 | 56 | _movies.Add(GetMovie( 57 | photo: "https://ia.media-imdb.com/images/M/MV5BMTM4NTc0Mzk5N15BMl5BanBnXkFtZTcwNDA4NDUyNg@@._V1_UX182_CR0,0,182,268_AL_.jpg", 58 | category: "Watch It again" 59 | )); 60 | 61 | _movies.Add(GetMovie( 62 | photo: "https://assets.nflxext.com/us/boxshots/ghd/60010932.jpg", 63 | category: "Watch It again" 64 | )); 65 | } 66 | 67 | private MovieModel GetMovie( 68 | string photo, 69 | string category) 70 | { 71 | return new MovieModel() 72 | { 73 | Photo = photo, 74 | Category = category 75 | }; 76 | } 77 | 78 | public IList GetMovies() 79 | { 80 | return _movies; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Core/Services/NubankService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Core.Interfaces; 4 | using Core.Models; 5 | using Core.Models.Nubank; 6 | using Microcharts; 7 | using SkiaSharp; 8 | 9 | namespace Core.Services 10 | { 11 | public class NubankService : INubank 12 | { 13 | private IList _items; 14 | private IList _headers; 15 | 16 | public NubankService() 17 | { 18 | _items = new List(); 19 | _headers = new List(); 20 | 21 | _items.Add(GetNubankTimelineModel( 22 | category: "Eletrônicos", 23 | categoryIcon: "nubank_cat_eletronics", 24 | textColor: "#000000", 25 | description: "Mercadopago", 26 | localPrice: 419.99, 27 | isDollar: false, 28 | dollarPrice: null, 29 | isInstallment: true, 30 | numberOfInstallments: 4, 31 | createdAt: DateTime.Now, 32 | isReversed: false, 33 | tags: new List() { "Compras" } 34 | )); 35 | 36 | _items.Add(GetNubankTimelineModel( 37 | category: "Restaurante", 38 | categoryIcon: "nubank_cat_restaurant", 39 | textColor: "#000000", 40 | description: "Tio Patinhas", 41 | localPrice: 16.90, 42 | isDollar: false, 43 | dollarPrice: null, 44 | isInstallment: false, 45 | numberOfInstallments: null, 46 | createdAt: DateTime.Now.AddHours(-3), 47 | isReversed: false, 48 | tags: new List() { "Almoço" } 49 | )); 50 | 51 | _items.Add(GetNubankTimelineModel( 52 | category: "Eletrônicos", 53 | categoryIcon: "nubank_cat_eletronics", 54 | textColor: "#000000", 55 | description: "Apl Appleonlinestoreus", 56 | localPrice: 387.56, 57 | isDollar: true, 58 | dollarPrice: 99.00, 59 | isInstallment: false, 60 | numberOfInstallments: null, 61 | createdAt: DateTime.Now.AddDays(-1), 62 | isReversed: false, 63 | tags: new List() 64 | )); 65 | 66 | _items.Add(GetNubankTimelineModel( 67 | category: "Serviços", 68 | categoryIcon: "nubank_cat_services", 69 | textColor: "#000000", 70 | description: "Apl* Itunes.Com/Bill", 71 | localPrice: 3.91, 72 | isDollar: true, 73 | dollarPrice: 1.00, 74 | isInstallment: false, 75 | numberOfInstallments: null, 76 | createdAt: DateTime.Now.AddDays(-1).AddHours(-1), 77 | isReversed: true, 78 | tags: new List() 79 | )); 80 | 81 | _items.Add(GetNubankTimelineModel( 82 | category: "Fatura Paga", 83 | categoryIcon: "nubank_cat_bullet_green", 84 | textColor: "#80cd00", 85 | description: null, 86 | localPrice: null, 87 | isDollar: false, 88 | dollarPrice: null, 89 | isInstallment: false, 90 | numberOfInstallments: null, 91 | createdAt: DateTime.Now.AddDays(-2).AddHours(-1), 92 | isReversed: false, 93 | tags: new List() 94 | )); 95 | 96 | _items.Add(GetNubankTimelineModel( 97 | category: "Pagamento recebido", 98 | categoryIcon: "nubank_cat_bullet_green", 99 | textColor: "#80cd00", 100 | description: null, 101 | localPrice: 1234.56, 102 | isDollar: false, 103 | dollarPrice: null, 104 | isInstallment: false, 105 | numberOfInstallments: null, 106 | createdAt: DateTime.Now.AddDays(-2).AddHours(-2), 107 | isReversed: false, 108 | tags: new List() 109 | )); 110 | 111 | _items.Add(GetNubankTimelineModel( 112 | category: "Transporte", 113 | categoryIcon: "nubank_cat_transport", 114 | textColor: "#000000", 115 | description: "Posto Cidade", 116 | localPrice: 9.35, 117 | isDollar: false, 118 | dollarPrice: null, 119 | isInstallment: false, 120 | numberOfInstallments: null, 121 | createdAt: DateTime.Now.AddDays(-3), 122 | isReversed: false, 123 | tags: new List() 124 | )); 125 | 126 | _items.Add(GetNubankTimelineModel( 127 | category: "Fatura Fechada", 128 | categoryIcon: "nubank_cat_bullet_red", 129 | textColor: "#f64d59", 130 | description: "Vence em 10/05, e hoje é o melhor dia para compras", 131 | localPrice: 1234.56, 132 | isDollar: false, 133 | dollarPrice: null, 134 | isInstallment: false, 135 | numberOfInstallments: null, 136 | createdAt: DateTime.Now.AddDays(-5), 137 | isReversed: false, 138 | tags: new List() 139 | )); 140 | 141 | _items.Add(GetNubankTimelineModel( 142 | category: "Restaurante", 143 | categoryIcon: "nubank_cat_restaurant", 144 | textColor: "#000000", 145 | description: "Ifood*Br", 146 | localPrice: 80.70, 147 | isDollar: false, 148 | dollarPrice: null, 149 | isInstallment: false, 150 | numberOfInstallments: null, 151 | createdAt: DateTime.Now.AddDays(-7), 152 | isReversed: false, 153 | tags: new List() {"Jantar", "Happy Hour"} 154 | )); 155 | 156 | _items.Add(GetNubankTimelineModel( 157 | category: "Serviços", 158 | categoryIcon: "nubank_cat_services", 159 | textColor: "#000000", 160 | description: "Netflix.Com", 161 | localPrice: 37.90, 162 | isDollar: false, 163 | dollarPrice: null, 164 | isInstallment: false, 165 | numberOfInstallments: null, 166 | createdAt: DateTime.Now.AddDays(-8), 167 | isReversed: false, 168 | tags: new List() 169 | )); 170 | 171 | _items.Add(GetNubankTimelineModel( 172 | category: "Lazer", 173 | categoryIcon: "nubank_cat_recreation", 174 | textColor: "#000000", 175 | description: "Toni Toys", 176 | localPrice: 291.98, 177 | isDollar: false, 178 | dollarPrice: null, 179 | isInstallment: true, 180 | numberOfInstallments: 2, 181 | createdAt: DateTime.Now.AddDays(-10), 182 | isReversed: false, 183 | tags: new List() 184 | )); 185 | 186 | _items.Add(GetNubankTimelineModel( 187 | category: "Seu Cartão Está", 188 | categoryIcon: "nubank_cat_card", 189 | textColor: "#000000", 190 | description: "Desbloqueado", 191 | localPrice: null, 192 | isDollar: false, 193 | dollarPrice: null, 194 | isInstallment: false, 195 | numberOfInstallments: null, 196 | createdAt: DateTime.Now.AddDays(-15), 197 | isReversed: false, 198 | tags: new List() 199 | )); 200 | 201 | _items.Add(GetNubankTimelineModel( 202 | category: "Limite Inicial", 203 | categoryIcon: "nubank_cat_bullet_green", 204 | textColor: "#80cd00", 205 | description: null, 206 | localPrice: 1000.00, 207 | isDollar: false, 208 | dollarPrice: null, 209 | isInstallment: false, 210 | numberOfInstallments: null, 211 | createdAt: DateTime.Now.AddDays(-15).AddHours(-1), 212 | isReversed: false, 213 | tags: new List() 214 | )); 215 | 216 | _items.Add(GetNubankTimelineModel( 217 | category: "Veja Como Funciona", 218 | categoryIcon: "nubank_cat_play", 219 | textColor: "#000000", 220 | description: null, 221 | localPrice: null, 222 | isDollar: false, 223 | dollarPrice: null, 224 | isInstallment: false, 225 | numberOfInstallments: null, 226 | createdAt: DateTime.Now.AddDays(-15).AddHours(-1), 227 | isReversed: false, 228 | tags: new List() 229 | )); 230 | 231 | _items.Add(GetNubankTimelineModel( 232 | category: "Bem-Vindo ao", 233 | categoryIcon: "nubank_cat_star", 234 | textColor: "#000000", 235 | description: "Nubank!", 236 | localPrice: null, 237 | isDollar: false, 238 | dollarPrice: null, 239 | isInstallment: false, 240 | numberOfInstallments: null, 241 | createdAt: DateTime.Now.AddDays(-15).AddHours(-2), 242 | isReversed: false, 243 | tags: new List() 244 | )); 245 | 246 | _headers.Add(GetHeader( 247 | description: "Você fez 51 compras nos últimos 30 dias, com um total de R$ 273,77" 248 | )); 249 | 250 | _headers.Add(GetHeader( 251 | total: 249.91 252 | )); 253 | } 254 | 255 | public IList GetHeader() 256 | { 257 | return _headers; 258 | } 259 | 260 | public IList GetTimeline() 261 | { 262 | return _items; 263 | } 264 | 265 | private NubankTimelineModel GetNubankTimelineModel( 266 | string category, 267 | string categoryIcon, 268 | string textColor, 269 | string description, 270 | double? localPrice, 271 | bool isDollar, 272 | double? dollarPrice, 273 | bool isInstallment, 274 | int? numberOfInstallments, 275 | DateTimeOffset createdAt, 276 | bool isReversed, 277 | IList tags 278 | ) { 279 | return new NubankTimelineModel() 280 | { 281 | Category = category, 282 | CategoryIcon = categoryIcon, 283 | TextColor = textColor, 284 | Description = description, 285 | LocalPrice = localPrice, 286 | IsDollar = isDollar, 287 | DollarPrice = dollarPrice, 288 | IsInstallment = isInstallment, 289 | NumberOfInstallments = numberOfInstallments, 290 | CreatedAt = createdAt, 291 | IsReversed = isReversed, 292 | Tags = tags 293 | }; 294 | } 295 | 296 | private ChartEntry GetEntry(float value) 297 | { 298 | var color = "#00c0cd"; 299 | 300 | return new ChartEntry(value) 301 | { 302 | Color = SKColor.Parse(color), 303 | TextColor = SKColor.Parse(color) 304 | }; 305 | } 306 | private NubankHeaderModel GetHeader( 307 | string description) 308 | { 309 | var entries = new[] 310 | { 311 | GetEntry(0), 312 | GetEntry(50), 313 | GetEntry(0), 314 | GetEntry(15), 315 | GetEntry(0), 316 | GetEntry(15), 317 | GetEntry(0), 318 | GetEntry(70), 319 | GetEntry(-20), 320 | GetEntry(110), 321 | GetEntry(10), 322 | GetEntry(30), 323 | GetEntry(15), 324 | GetEntry(20), 325 | GetEntry(110), 326 | GetEntry(50), 327 | GetEntry(20), 328 | GetEntry(50), 329 | GetEntry(5), 330 | GetEntry(15) 331 | }; 332 | 333 | var chart = new LineChart() 334 | { 335 | Entries = entries, 336 | LineMode = LineMode.Straight, 337 | PointMode = PointMode.None, 338 | LineSize = 4, 339 | BackgroundColor = SKColors.Transparent 340 | }; 341 | 342 | return new NubankHeaderSummaryModel() 343 | { 344 | Chart = chart, 345 | Description = description 346 | }; 347 | } 348 | 349 | private NubankHeaderModel GetHeader( 350 | double total) 351 | { 352 | return new NubankHeaderInvoiceModel() 353 | { 354 | Total = total 355 | }; 356 | } 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /Core/Services/TwitchService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Core.Interfaces; 3 | using Core.Models.Twitch; 4 | using System.Linq; 5 | 6 | namespace Core.Services 7 | { 8 | public class TwitchService : ITwitch 9 | { 10 | private IList _channels; 11 | 12 | public TwitchService() 13 | { 14 | _channels = new List(); 15 | 16 | _channels.Add(new TwitchChannelModel 17 | { 18 | Name = "Vovo_Tibiano", 19 | Avatar = "", 20 | Description = "🔞 Vovô Tibiano 19/07.2929 joganto Tibia", 21 | Category = "Tibia", 22 | Tags = new List { "Portuguese" }, 23 | GroupName = "LIVE CHANNELS", 24 | TotalWatching = 59 25 | }); 26 | 27 | _channels.Add(new TwitchChannelModel 28 | { 29 | Name = "Leshrot", 30 | Avatar = "", 31 | Description = "[DA Study] Fazendo comida em live", 32 | Category = "Art", 33 | Tags = new List { "Portuguese" }, 34 | GroupName = "RECOMMENDED CHANNELS", 35 | TotalWatching = 10 36 | }); 37 | 38 | _channels.Add(new TwitchChannelModel 39 | { 40 | Name = "rinconhacking", 41 | Avatar = "", 42 | Description = "UHC - Ultimate Hacking", 43 | Category = "Science & Technology", 44 | Tags = new List { "Portuguese" }, 45 | GroupName = "RECOMMENDED CHANNELS", 46 | TotalWatching = 24 47 | }); 48 | 49 | _channels.Add(new TwitchChannelModel 50 | { 51 | Name = "VapeJuiceJordan", 52 | Avatar = "", 53 | Description = "FAANG Staff Software Engineer building frontend app // !today", 54 | Category = "Science & Technology", 55 | Tags = new List { "English", "Programming", "Web Development", "Software Development" }, 56 | GroupName = "RECOMMENDED CHANNELS", 57 | TotalWatching = 138 58 | }); 59 | 60 | _channels.Add(new TwitchChannelModel 61 | { 62 | Name = "JdotW", 63 | Avatar = "", 64 | Description = "[Swift+React+NodeJS] | GOD THE JOB", 65 | Category = "Science & Technology", 66 | Tags = new List { "English" }, 67 | GroupName = "RECOMMENDED CHANNELS", 68 | TotalWatching = 171 69 | }); 70 | 71 | _channels.Add(new TwitchChannelModel 72 | { 73 | Name = "Leshrot", 74 | Avatar = "", 75 | Description = "[DA Study] Fazendo comida em live", 76 | Category = "Art", 77 | Tags = new List { "Portuguese" }, 78 | GroupName = "RECOMMENDED CHANNELS", 79 | TotalWatching = 10 80 | }); 81 | 82 | _channels.Add(new TwitchChannelModel 83 | { 84 | Name = "rinconhacking", 85 | Avatar = "", 86 | Description = "UHC - Ultimate Hacking", 87 | Category = "Science & Technology", 88 | Tags = new List { "Portuguese" }, 89 | GroupName = "RECOMMENDED CHANNELS", 90 | TotalWatching = 24 91 | }); 92 | 93 | _channels.Add(new TwitchChannelModel 94 | { 95 | Name = "VapeJuiceJordan", 96 | Avatar = "", 97 | Description = "FAANG Staff Software Engineer building frontend app // !today", 98 | Category = "Science & Technology", 99 | Tags = new List { "English", "Programming", "Web Development", "Software Development" }, 100 | GroupName = "RECOMMENDED CHANNELS", 101 | TotalWatching = 138 102 | }); 103 | 104 | _channels.Add(new TwitchChannelModel 105 | { 106 | Name = "JdotW", 107 | Avatar = "", 108 | Description = "[Swift+React+NodeJS] | GOD THE JOB", 109 | Category = "Science & Technology", 110 | Tags = new List { "English" }, 111 | GroupName = "RECOMMENDED CHANNELS", 112 | TotalWatching = 171 113 | }); 114 | } 115 | 116 | public IList GetChannels() 117 | { 118 | return _channels; 119 | } 120 | 121 | public IList GetGroupedChannels() 122 | { 123 | return _channels 124 | .GroupBy(x => x.GroupName) 125 | .Select(x => new GroupTwitchChannelModel(x.Key, x.ToList())) 126 | .ToList(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Core/Services/WhatsAppService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Core.Interfaces; 4 | using Core.Models; 5 | using Core.Models.WhatsApp; 6 | 7 | namespace Core.Services 8 | { 9 | public class WhatsAppService : IWhatsApp 10 | { 11 | private IList _chats; 12 | private WhatsAppInfoModel _info; 13 | 14 | public WhatsAppService() 15 | { 16 | _chats = new List(); 17 | 18 | _chats.Add(GetChat( 19 | photo: "http://www.maisopiniao.com/wp-content/uploads/bola_futebol-150x150.jpg", 20 | groupName: "Patota", 21 | sentFrom: "Luiz Pereira:", 22 | createdAt: DateTimeOffset.Now, 23 | message: "O jogo ficou confirmado para quarta??", 24 | messageIcon: string.Empty, 25 | isMuted: true, 26 | totalUnread: 9 27 | )); 28 | 29 | _chats.Add(GetChat( 30 | photo: "https://i.imgflip.com/2/e4t4k.jpg", 31 | groupName: null, 32 | sentFrom: "Marty McFly", 33 | createdAt: DateTimeOffset.Now.AddDays(-1), 34 | message: "If you put your mind to it, you can accomplish anything.", 35 | messageIcon: string.Empty, 36 | isMuted: false, 37 | totalUnread: 0 38 | )); 39 | 40 | _chats.Add(GetChat( 41 | photo: "http://www.georgefiorini.eu/images/ritorno-al-futuro/doc-brown.jpg", 42 | groupName: null, 43 | sentFrom: "Dr. Emmett Brown", 44 | createdAt: DateTimeOffset.Now.AddDays(-2), 45 | message: "Roads? Where we are going we don`t need roads", 46 | messageIcon: string.Empty, 47 | isMuted: false, 48 | totalUnread: 3 49 | )); 50 | 51 | _chats.Add(GetChat( 52 | photo: "http://helixholidays.com/wp-content/uploads/2016/01/family-shutter2-1-150x150.jpg", 53 | groupName: "Família", 54 | sentFrom: "+55 11 98877-6655:", 55 | createdAt: DateTimeOffset.Now.AddDays(-3), 56 | message: "Bom dia!", 57 | messageIcon: string.Empty, 58 | isMuted: true, 59 | totalUnread: 73 60 | )); 61 | 62 | _chats.Add(GetChat( 63 | photo: "https://www.deveserisso.com.br/blog/wp-content/uploads/2016/12/series-anos-90-um-maluco-no-pedaco-150x150.jpg", 64 | groupName: null, 65 | sentFrom: "Will", 66 | createdAt: DateTimeOffset.Now.AddDays(-4), 67 | message: "Cara, to precisando passar uns dias ai em bell-air", 68 | messageIcon: "whatsapp_read", 69 | isMuted: false, 70 | totalUnread: 0 71 | )); 72 | 73 | _chats.Add(GetChat( 74 | photo: "http://rederecord.r7.com/wp-content/blogs.dir/21/files/veja-as-caras-e-bocas-que-so-a-rochelle-consegue-fazer/9.jpg", 75 | groupName: null, 76 | sentFrom: "Rochelle", 77 | createdAt: DateTimeOffset.Now.AddDays(-5), 78 | message: "Eu não preciso disso, meu marido tem 2 empregos, EU ME DEMIIIITOO", 79 | messageIcon: string.Empty, 80 | isMuted: false, 81 | totalUnread: 0 82 | )); 83 | 84 | 85 | // info 86 | _info = new WhatsAppInfoModel() 87 | { 88 | Phone = "http://profetirando.com.br/wp-content/uploads/2015/10/de-volta-para-o-futuro-profetirando6.jpg", 89 | Name = "Marty McFly", 90 | Photo = "+1 11 9943-2424", 91 | Status = "Available", 92 | StatusAt = DateTimeOffset.Now.AddDays(131433) 93 | }; 94 | } 95 | 96 | //private WhatsAppChatListModel GetChat( 97 | // string photo, 98 | // bool isGroup, 99 | // string groupName, 100 | // string sentFrom, 101 | // DateTimeOffset createdAt, 102 | // string message, 103 | // bool isMuted, 104 | // bool isRead, 105 | // int totalUnread, 106 | // bool isMessageSent, 107 | // WhatsAppChatListMessageStatusEnum messageStatusEnum) 108 | //{ 109 | // return new WhatsAppChatListModel() 110 | // { 111 | // Photo = photo, 112 | // IsGroup = isGroup, 113 | // GroupName = groupName, 114 | // SentFrom = sentFrom, 115 | // CreatedAt = createdAt, 116 | // Message = message, 117 | // IsMuted = isMuted, 118 | // IsRead = isRead, 119 | // TotalUnread = totalUnread, 120 | // IsMessageSent = isMessageSent, 121 | // MessageSentStatus = messageStatusEnum 122 | // }; 123 | //} 124 | 125 | private ChatModel GetChat( 126 | string photo, 127 | string sentFrom, 128 | DateTimeOffset createdAt, 129 | string message, 130 | string messageIcon, 131 | bool isMuted, 132 | int totalUnread, 133 | string groupName) 134 | { 135 | ChatModel chatModel = null; 136 | 137 | if (groupName != null) 138 | chatModel = new GroupChatModel() { GroupName = groupName }; 139 | 140 | if (chatModel == null) 141 | chatModel = new ChatModel(); 142 | 143 | chatModel.Photo = photo; 144 | chatModel.SentFrom = sentFrom; 145 | chatModel.CreatedAt = createdAt; 146 | chatModel.Message = message; 147 | chatModel.MessageIcon = messageIcon; 148 | chatModel.IsMuted = isMuted; 149 | chatModel.TotalUnread = totalUnread; 150 | 151 | return chatModel; 152 | } 153 | 154 | public IList GetChats() 155 | { 156 | return _chats; 157 | } 158 | 159 | public WhatsAppInfoModel GetInfo() 160 | { 161 | return _info; 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Core/Templates/Nubank/HeaderInvoice.xaml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 22 |