Skip to content

Commit

Permalink
Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
naweed committed Aug 24, 2022
1 parent 46e7d60 commit 9330fee
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 22 deletions.
4 changes: 3 additions & 1 deletion src/MauiTubePlayer/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@
global using System.Net;
global using Maui.Apps.Framework.Services;
global using MauiTubePlayer.Views.Base;
global using Maui.Apps.Framework.Exceptions;
global using Maui.Apps.Framework.Exceptions;
global using CommunityToolkit.Mvvm.ComponentModel;
global using System.Collections.ObjectModel;
1 change: 1 addition & 0 deletions src/MauiTubePlayer/IServices/IApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ namespace MauiTubePlayer.IServices;
public interface IApiService
{
Task<VideoSearchResult> SearchVideos(string searchQuery, string nextPageToken = "");
Task<ChannelSearchResult> GetChannels(string channelIDs);
}

3 changes: 3 additions & 0 deletions src/MauiTubePlayer/MauiTubePlayer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
<MauiXaml Update="Views\Base\PageBase.xaml">
<SubType></SubType>
</MauiXaml>
<MauiXaml Update="ViewControls\VideoCell.xaml">
<SubType></SubType>
</MauiXaml>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Maui.Apps.Framework\Maui.Apps.Framework.csproj" />
Expand Down
22 changes: 22 additions & 0 deletions src/MauiTubePlayer/Models/YoutubeModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public class Snippet

[JsonPropertyName("channelTitle")]
public string ChannelTitle { get; set; }

public string ChannelImageURL { get; set; }
}

public class Thumbnails
Expand All @@ -76,3 +78,23 @@ public class Thumbnail
public string Url { get; set; }
}

//Channel related models

public class ChannelSearchResult
{
[JsonPropertyName("items")]
public List<Channel> Items { get; set; }
}

public class Channel
{
[JsonPropertyName("id")]
public string Id { get; set; }

[JsonPropertyName("snippet")]
public Snippet Snippet { get; set; }

//[JsonPropertyName("statistics")]
//public Statistics Statistics { get; set; }

}
9 changes: 9 additions & 0 deletions src/MauiTubePlayer/Services/YoutubeService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,14 @@ public async Task<VideoSearchResult> SearchVideos(string searchQuery, string nex

return result;
}

public async Task<ChannelSearchResult> GetChannels(string channelIDs)
{
var resourceUri = $"channels?part=snippet,statistics&maxResults=10&key={Constants.ApiKey}&id={channelIDs}";

var result = await GetAsync<ChannelSearchResult>(resourceUri, 4); //Cached for 4 hours

return result;
}
}

116 changes: 116 additions & 0 deletions src/MauiTubePlayer/ViewControls/VideoCell.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:models="clr-namespace:MauiTubePlayer.Models"
x:DataType="models:YoutubeVideo"
x:Name="VideoCellRoot"
x:Class="MauiTubePlayer.ViewControls.VideoCell">

<Border
BackgroundColor="{StaticResource DarkColor}"
StrokeShape="RoundRectangle 12"
Padding="6">

<Grid
RowSpacing="12"
RowDefinitions="*,Auto">

<!-- Thumbnail -->
<Frame
Grid.Row="0"
HasShadow="True"
CornerRadius="8"
HorizontalOptions="Fill"
VerticalOptions="Fill"
IsClippedToBounds="True"
Padding="0"
Margin="0,0,2,2">
<Image
HorizontalOptions="Fill"
VerticalOptions="Fill"
Aspect="AspectFill">
<Image.Source>
<UriImageSource
Uri="{Binding Snippet.Thumbnails.High.Url, Mode=OneWay}"
CacheValidity="1:00:00.0" />
</Image.Source>
</Image>
</Frame>

<!-- Video Details -->
<Grid
Grid.Row="1"
ColumnSpacing="12"
ColumnDefinitions="Auto,*,Auto"
RowDefinitions="Auto,Auto">

<!-- Channel Pic -->
<Border
WidthRequest="36"
HeightRequest="36"
VerticalOptions="Center"
Stroke="{StaticResource LightBorderColor}"
StrokeThickness="2"
StrokeShape="RoundRectangle 18"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0">

<Image
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="32"
HeightRequest="32">

<Image.Clip>
<EllipseGeometry
Center="16,16"
RadiusX="16"
RadiusY="16"/>
</Image.Clip>

<Image.Source>
<UriImageSource
Uri="{Binding Snippet.ChannelImageURL, Mode=OneWay}"
CacheValidity="1:00:00.0" />
</Image.Source>
</Image>

</Border>


<!-- Channel Name -->
<Label
Style="{StaticResource MediumLightText18}"
Grid.Row="0"
Grid.Column="1"
Text="{Binding Snippet.ChannelTitle, Mode=OneWay}" />

<!-- Video Title -->
<Label
Style="{StaticResource RegularLightText14}"
Grid.Row="1"
Grid.Column="1"
Text="{Binding Snippet.Title, Mode=OneWay}" />

<!-- Next Arrow -->
<Image
Source="imgarrow.png"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="2"
WidthRequest="32"
HeightRequest="32"
Aspect="AspectFill"
VerticalOptions="Center" />

</Grid>

</Grid>

</Border>


</ContentView>

9 changes: 9 additions & 0 deletions src/MauiTubePlayer/ViewControls/VideoCell.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace MauiTubePlayer.ViewControls;

public partial class VideoCell : ContentView
{
public VideoCell()
{
InitializeComponent();
}
}
69 changes: 56 additions & 13 deletions src/MauiTubePlayer/ViewModels/StartPageViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,41 @@
namespace MauiTubePlayer.ViewModels;
using Maui.Apps.Framework.Extensions;

namespace MauiTubePlayer.ViewModels;

public class StartPageViewModel : AppViewModelBase
public partial class StartPageViewModel : AppViewModelBase
{
public StartPageViewModel(IApiService appApiService) : base(appApiService)
private string nextToken = string.Empty;
private string searchTerm = "iPhone 14";

[ObservableProperty]
private ObservableCollection<YoutubeVideo> youtubeVideos;


public StartPageViewModel(IApiService appApiService) : base(appApiService)
{
this.Title = "TUBE PLAYER";
}

public override async void OnNavigatedTo(object parameters)
{
SetDataLodingIndicators(true);
Search();
}

LoadingText = "Hold on, we are loading";
private async void Search()
{
SetDataLodingIndicators(true);

try
{
await Task.Delay(5000);
LoadingText = "Hold on while we search for Youtube videos...";

//throw new Exception("Unable to reach Google Youtube API Service");
YoutubeVideos = new();

this.DataLoaded = true;
}
try
{
//Search for videos
await GetYouTubeVideo();

this.DataLoaded = true;
}
catch (InternetConnectionException iex)
{
this.IsErrorState = true;
Expand All @@ -35,8 +50,36 @@ public override async void OnNavigatedTo(object parameters)
}
finally
{
SetDataLodingIndicators(false);
}
SetDataLodingIndicators(false);
}
}

private async Task GetYouTubeVideo()
{
//Search the videos
var videoSearchResult = await _appApiService.SearchVideos(searchTerm, nextToken);

nextToken = videoSearchResult.NextPageToken;

//Get Channel URLs
var channelIDs = string.Join(",",
videoSearchResult.Items.Select(video => video.Snippet.ChannelId).Distinct());

var channelSearchResult = await _appApiService.GetChannels(channelIDs);

//Set Channel URL in the Video
videoSearchResult.Items.ForEach(video =>
video.Snippet.ChannelImageURL = channelSearchResult.Items.Where(channel =>
channel.Id == video.Snippet.ChannelId).First().Snippet.Thumbnails.High.Url);

//Add the Videos for Display
YoutubeVideos.AddRange(videoSearchResult.Items);
}

[RelayCommand]
private async void OpenSettingPage()
{
await PageService.DisplayAlert("Setting", "This implemention is outside the scope of this course.", "Got it!");
}
}

43 changes: 36 additions & 7 deletions src/MauiTubePlayer/Views/StartPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:baseviews="clr-namespace:MauiTubePlayer.Views.Base"
xmlns:viewmodels="clr-namespace:MauiTubePlayer.ViewModels"
xmlns:models="clr-namespace:MauiTubePlayer.Models"
xmlns:controls="clr-namespace:MauiTubePlayer.ViewControls"
x:Class="MauiTubePlayer.Views.StartPage"
x:TypeArguments="viewmodels:StartPageViewModel"
x:DataType="viewmodels:StartPageViewModel"
Expand All @@ -15,17 +17,44 @@
<baseviews:ViewBase.PageIcons>
<ImageButton
Style="{StaticResource IconButtonStyle}"
Source="icnsettings.png" />
Source="icnsettings.png"
Command="{Binding OpenSettingPageCommand, Mode=OneWay}" />
</baseviews:ViewBase.PageIcons>

<baseviews:ViewBase.PageContent>

<Label
Style="{StaticResource MediumLightText20}"
IsVisible="{Binding DataLoaded, Mode=OneWay}"
VerticalOptions="Center"
HorizontalOptions="Center"
Text="Data has been loaded" />
<CollectionView
x:Name="lstVideos"
Margin="16,4,16,0"
ItemsSource="{Binding YoutubeVideos, Mode=OneWay}">

<CollectionView.ItemsLayout>
<LinearItemsLayout
Orientation="Vertical"
ItemSpacing="12" />
</CollectionView.ItemsLayout>

<CollectionView.Header>
<ContentView>
<Label
Text="Search box will appear here"
Style="{StaticResource RegularLightText16}" />

</ContentView>
</CollectionView.Header>

<CollectionView.ItemTemplate>
<DataTemplate
x:DataType="models:YoutubeVideo">

<controls:VideoCell
HorizontalOptions="Fill"
HeightRequest="{Binding ItemsHeight, Source={x:Reference RootPage}}"/>

</DataTemplate>
</CollectionView.ItemTemplate>

</CollectionView>

</baseviews:ViewBase.PageContent>

Expand Down
23 changes: 22 additions & 1 deletion src/MauiTubePlayer/Views/StartPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@

public partial class StartPage : ViewBase<StartPageViewModel>
{
public StartPage()
public static BindableProperty ItemsHeightProperty = BindableProperty.Create(
nameof(ItemsHeight),
typeof(double),
typeof(StartPage),
null,
BindingMode.OneWay);

public double ItemsHeight
{
get => (double)GetValue(ItemsHeightProperty);
set => SetValue(ItemsHeightProperty, value);
}


public StartPage()
{
InitializeComponent();
}

protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);

ItemsHeight = 60d + (width - lstVideos.Margin.Right - lstVideos.Margin.Left) / 1.8d;
}
}

0 comments on commit 9330fee

Please sign in to comment.