├── .dockerignore ├── .github └── workflows │ ├── codeql-analysis.yml │ ├── podcast-api.yml │ ├── podcast-dotnet-maui-blazor-cd.yml │ ├── podcast-dotnet-maui-blazor-ci.yml │ ├── podcast-dotnet-maui-cd.yml │ ├── podcast-dotnet-maui-ci.yml │ ├── podcast-hub.yml │ ├── podcast-loadtest.yml │ ├── podcast-web.yml │ ├── template-api.yml │ ├── template-dotnet-maui-cd.yml │ ├── template-dotnet-maui-ci.yml │ ├── template-hub.yml │ └── template-web.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── NetPodcast.Services.sln ├── NetPodcast.sln ├── NuGet.config ├── Podcast.Web.sln ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── Test ├── ARMTemplate │ ├── parameters.json │ └── template.json ├── DemoPodcastTest.jmx ├── Shows.csv ├── config.yml └── jmeter-plugins-functions-2.2.jar ├── deploy ├── Android │ └── android-keystore-test.jks.gpg ├── Images │ ├── Covers │ │ ├── .NET Rocks!.jpg │ │ ├── .future.png │ │ ├── Adventures in .NET – Devchat.tv.jpg │ │ ├── Adventures in .NET.jpg │ │ ├── Asp.Net Monsters.jpg │ │ ├── Away From The Keyboard.png │ │ ├── CodeNewbie.png │ │ ├── Gone Mobile.jpg │ │ ├── Hanselminutes with Scott Hanselman.jpg │ │ ├── Hello World (Audio) - Channel 9.jpg │ │ ├── Last Week in .NET.jpg │ │ ├── MS Dev Show.png │ │ ├── Merge Conflict.jpg │ │ ├── Microsoft 365 Developer Podcast.jpg │ │ ├── Microsoft Mechanics Podcast.png │ │ ├── Null Pointers.jpg │ │ ├── Paths Uncovered.jpg │ │ ├── RunAs Radio.jpg │ │ ├── The .NET Core Podcast.jpg │ │ ├── The .NET MAUI Podcast.jpg │ │ ├── The Unhandled Exception Podcast.jpeg │ │ ├── Upwards.png │ │ ├── intrazone.png │ │ └── no dogma podcast.jpg │ ├── Deploy-Images.ps1 │ └── Readme.md ├── Services │ ├── acr.bicep │ ├── api.bicep │ └── hub.bicep └── Web │ ├── web.bicep │ └── web.json ├── docker-compose.arm64.yml ├── docker-compose.dcproj ├── docker-compose.override.yml ├── docker-compose.yml ├── docs ├── demos │ ├── aspnetcore-blazor │ │ └── README.md │ ├── authentication │ │ ├── README.md │ │ └── images │ │ │ ├── add-swagger-authorization.png │ │ │ ├── authorize-swagger.png │ │ │ ├── create-app-role.png │ │ │ ├── delete-feed.png │ │ │ ├── generated-token.png │ │ │ ├── get-feeds.png │ │ │ ├── provide-application-name.png │ │ │ ├── select-active-directory.png │ │ │ ├── select-app-registrations.png │ │ │ ├── select-app-roles.png │ │ │ ├── select-create-app-role.png │ │ │ └── select-new-registration.png │ ├── azure-load-testing │ │ └── README.md │ ├── azure-monitor │ │ └── README.md │ ├── azurecontainerapps │ │ ├── MessageCount.ps1 │ │ ├── Readme.md │ │ ├── Simulate-Feed-Requests.ps1 │ │ ├── feeds.json │ │ ├── scale-out-demo-0.png │ │ ├── scale-out-demo-1.png │ │ └── scale-out-demo-2.png │ ├── blazor-hybrid │ │ └── README.md │ ├── dotnet-maui │ │ └── README.md │ ├── playwright-tests │ │ └── README.md │ └── powerapps │ │ ├── README.md │ │ └── assets │ │ ├── customconnector.jpg │ │ ├── editpowerapp.jpg │ │ ├── onstart.jpg │ │ ├── powerapp.jpg │ │ └── refreshbutton.jpg ├── deploy-websites-services.md └── images │ ├── Enable-Workflow.png │ ├── all-workflow-runs.png │ ├── arch_diagram_podcast.png │ ├── azure-secret-add.png │ ├── docker-app-config.png │ ├── docker-services-config.png │ ├── gh-configured-secrets.png │ ├── github-repo-settings.png │ ├── net-podcasts.png │ ├── podcast-api-ci-run.png │ └── select-secrets.png └── src ├── Lib └── SharedMauiLib │ ├── INativeAudioService.cs │ ├── Platforms │ ├── Android │ │ ├── CurrentActivity │ │ │ ├── ActivityEvent.cs │ │ │ ├── ActivityEventArgs.cs │ │ │ ├── CrossCurrentActivity.cs │ │ │ ├── CurrentActivityImplementation.cs │ │ │ └── ICurrentActivity.cs │ │ ├── EventHandlers.cs │ │ ├── IAudioActivity.cs │ │ ├── MediaPlayerService.cs │ │ ├── MediaPlayerServiceConnection.cs │ │ ├── NativeAudioService.cs │ │ ├── NotificationHelper.cs │ │ └── RemoteControlBroadcastReceiver.cs │ ├── MacCatalyst │ │ └── NativeAudioService.cs │ ├── Windows │ │ └── NativeAudioService.cs │ └── iOS │ │ └── NativeAudioService.cs │ ├── Resources │ └── Images │ │ └── player_play.svg │ └── SharedMauiLib.csproj ├── Mobile ├── .editorconfig ├── App.xaml ├── App.xaml.cs ├── Blazor │ └── ListenTogetherComponent.razor ├── Config.cs ├── Controls │ ├── HeaderControl.xaml │ ├── HeaderControl.xaml.cs │ ├── Player.xaml │ └── Player.xaml.cs ├── Converters │ ├── DurationConverter.cs │ ├── IsNullConverter.cs │ └── TextToTypeTextConverter.cs ├── GlobalUsings.cs ├── Helpers │ ├── Settings.cs │ └── TheTheme.cs ├── MauiProgram.cs ├── MauiWindow.cs ├── Messaging │ ├── ChangeThemeNotification.cs │ └── LeaveRoomNotification.cs ├── Microsoft.NetConf2021.Maui.csproj ├── Models │ ├── AppSection.cs │ ├── Category.cs │ ├── Episode.cs │ ├── Responses │ │ ├── CategoryResponse.cs │ │ ├── EpisodeResponse.cs │ │ └── ShowResponse.cs │ ├── Show.cs │ └── ShowGroup.cs ├── Pages │ ├── CategoriesPage.xaml │ ├── CategoriesPage.xaml.cs │ ├── CategoryPage.xaml │ ├── CategoryPage.xaml.cs │ ├── DesktopShell.xaml │ ├── DesktopShell.xaml.cs │ ├── DiscoverPage.xaml │ ├── DiscoverPage.xaml.cs │ ├── EpisodeDetailPage.xaml │ ├── EpisodeDetailPage.xaml.cs │ ├── ListenLaterPage.xaml │ ├── ListenLaterPage.xaml.cs │ ├── ListenTogetherPage.xaml │ ├── ListenTogetherPage.xaml.cs │ ├── MobileShell.xaml │ ├── MobileShell.xaml.cs │ ├── PagesExtensions.cs │ ├── SettingsPage.xaml │ ├── SettingsPage.xaml.cs │ ├── ShowDetailPage.xaml │ ├── ShowDetailPage.xaml.cs │ ├── SubscriptionsPage.xaml │ └── SubscriptionsPage.xaml.cs ├── Platforms │ ├── Android │ │ ├── AndroidManifest.xml │ │ ├── MainActivity.cs │ │ ├── MainApplication.cs │ │ └── Resources │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── network_security_config.xml │ ├── MacCatalyst │ │ ├── AppDelegate.cs │ │ ├── ConnectivityService.cs │ │ ├── Info.plist │ │ └── Program.cs │ ├── Windows │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Package.appxmanifest │ │ └── app.manifest │ └── iOS │ │ ├── AppDelegate.cs │ │ ├── Entitlements.plist │ │ ├── Info.plist │ │ └── Program.cs ├── Podcasts.DotnetMaui.sln ├── Properties │ └── launchSettings.json ├── README.md ├── Resources │ ├── Fonts │ │ ├── Segoe-Ui-Bold.ttf │ │ ├── Segoe-Ui-Regular.ttf │ │ ├── Segoe-Ui-Semibold.ttf │ │ └── Segoe-Ui-Semilight.ttf │ ├── Images │ │ ├── clock.svg │ │ ├── clock_dark.svg │ │ ├── clockpink.svg │ │ ├── default_podcast_image.svg │ │ ├── discover.svg │ │ ├── discover_dark.svg │ │ ├── dotnet_bot.svg │ │ ├── empty_collection.png │ │ ├── listenlaterfilled.svg │ │ ├── listentogether.svg │ │ ├── listentogether_dark.svg │ │ ├── lists.svg │ │ ├── logo_color_horizontal_darkmode.svg │ │ ├── logo_header_horizontal.svg │ │ ├── player_pause.svg │ │ ├── sare_button.svg │ │ ├── search.svg │ │ ├── settings.svg │ │ ├── settings_dark.svg │ │ ├── subscriptions.svg │ │ ├── subscriptions_dark.svg │ │ ├── suscribed.svg │ │ ├── tab_home.svg │ │ └── tab_home_on.svg │ ├── Strings │ │ ├── AppResource.Designer.cs │ │ └── AppResource.resx │ ├── Styles │ │ ├── DefaultTheme.xaml │ │ └── DefaultTheme.xaml.cs │ ├── appicon.svg │ ├── appiconfg.svg │ └── splash.svg ├── Services │ ├── ImageProcessingService.cs │ ├── ListenLaterService.cs │ ├── PlayerService.cs │ ├── ServicesExtensions.cs │ ├── ServicesProvider.cs │ ├── ShowsService.cs │ ├── SubscriptionsService.cs │ └── WifiOptionsService.cs ├── ViewModels │ ├── CategoriesViewModel.cs │ ├── CategoryViewModel.cs │ ├── DiscoverViewModel.cs │ ├── EpisodeDetailViewModel.cs │ ├── EpisodeViewModel.cs │ ├── ListenLaterViewModel.cs │ ├── SettingsViewModel.cs │ ├── ShellViewModel.cs │ ├── ShowDetailViewModel.cs │ ├── ShowViewModel.cs │ ├── SubscriptionsViewModel.cs │ ├── ViewModelBase.cs │ └── ViewModelExtensions.cs ├── Views │ ├── EpisodeItemView.xaml │ ├── EpisodeItemView.xaml.cs │ ├── ShowItemView.xaml │ └── ShowItemView.xaml.cs ├── _Imports.razor └── wwwroot │ └── index.html ├── MobileBlazor ├── Podcast.DotnetMaui.Blazor.sln ├── README.md └── mauiapp │ ├── App.xaml │ ├── App.xaml.cs │ ├── Main.razor │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ ├── MauiProgram.cs │ ├── NetPodsMauiBlazor.csproj │ ├── Pages │ └── Index.razor │ ├── Platforms │ ├── Android │ │ ├── AndroidManifest.xml │ │ ├── MainActivity.cs │ │ ├── MainApplication.cs │ │ └── Resources │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── network_security_config.xml │ ├── MacCatalyst │ │ ├── AppDelegate.cs │ │ ├── Info.plist │ │ └── Program.cs │ ├── Windows │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Package.appxmanifest │ │ └── app.manifest │ └── iOS │ │ ├── AppDelegate.cs │ │ ├── Info.plist │ │ ├── Program.cs │ │ └── Resources │ │ └── LaunchScreen.xib │ ├── Properties │ └── launchSettings.json │ ├── Resources │ ├── Images │ │ └── dotnet_bot.svg │ ├── appicon.svg │ ├── appiconfg.svg │ └── splash.svg │ ├── Services │ └── AudioInteropService.cs │ ├── _Imports.razor │ └── wwwroot │ ├── appsettings.Development.json │ ├── appsettings.json │ └── index.html ├── PowerApps ├── README.md ├── Solution.zip └── assets │ ├── devapi.jpg │ ├── devresources.jpg │ └── powerapp.jpg ├── Services ├── ListenTogether │ ├── ListenTogether.Application │ │ ├── Grains │ │ │ └── RoomGrain.cs │ │ ├── Interfaces │ │ │ ├── IApplicationDbContext.cs │ │ │ ├── IEpisodesClient.cs │ │ │ ├── IRequest.cs │ │ │ ├── IRequestHandler.cs │ │ │ └── IRoomGrain.cs │ │ ├── ListenTogether.Application.csproj │ │ ├── Rooms │ │ │ ├── GetRoomsQueryHandler.cs │ │ │ ├── GetUserRoomQueryHandler.cs │ │ │ ├── JoinRoomRequestHandler.cs │ │ │ ├── LeaveRoomRequestHandler.cs │ │ │ ├── OpenRoomRequestHandler.cs │ │ │ └── UpdatePlayerRequestHandler.cs │ │ └── ServiceCollectionsExtensions.cs │ ├── ListenTogether.Domain │ │ ├── Episode.cs │ │ ├── ListenTogether.Domain.csproj │ │ ├── PlayerState.cs │ │ ├── Room.cs │ │ ├── Show.cs │ │ └── User.cs │ ├── ListenTogether.Hub │ │ ├── Dockerfile │ │ ├── GlobalUsings.cs │ │ ├── Hubs │ │ │ └── ListenTogetherHub.cs │ │ ├── ListenTogether.Hub.csproj │ │ ├── OrleansExtensions.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── README.md │ │ ├── ServiceCollectionsExtensions.cs │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ └── ListenTogether.Infrastructure │ │ ├── Data │ │ ├── ListenTogetherDbContext.cs │ │ └── Migrations │ │ │ ├── 20211111150042_InitialCreate.Designer.cs │ │ │ ├── 20211111150042_InitialCreate.cs │ │ │ └── ListenTogetherDbContextModelSnapshot.cs │ │ ├── Http │ │ └── EpisodesHttpClient.cs │ │ ├── ListenTogether.Infrastructure.csproj │ │ └── ServiceCollectionsExtensions.cs └── Podcasts │ ├── Podcast.API │ ├── Dockerfile │ ├── GlobalUsings.cs │ ├── Podcast.API.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── README.md │ ├── Routes │ │ ├── CategoriesApi.cs │ │ ├── EpisodesApi.cs │ │ ├── FeedsApi.cs │ │ └── ShowsApi.cs │ ├── appsettings.Development.json │ └── appsettings.json │ ├── Podcast.Infrastructure │ ├── Data │ │ ├── DTOs │ │ │ ├── CategoryDto.cs │ │ │ ├── EpisodeDto.cs │ │ │ ├── ShowDto.cs │ │ │ └── UserSubmittedFeedDto.cs │ │ ├── Migrations │ │ │ ├── 20211123085635_InitialCreate.Designer.cs │ │ │ ├── 20211123085635_InitialCreate.cs │ │ │ ├── 20220324201931_feed-approval.Designer.cs │ │ │ ├── 20220324201931_feed-approval.cs │ │ │ └── PodcastDbContextModelSnapshot.cs │ │ ├── Models │ │ │ ├── Category.cs │ │ │ ├── Episode.cs │ │ │ ├── Feed.cs │ │ │ ├── FeedCategory.cs │ │ │ ├── Show.cs │ │ │ └── UserSubmittedFeed.cs │ │ ├── PodcastDbContext.cs │ │ └── Seed.cs │ ├── Http │ │ ├── Feeds │ │ │ ├── FeedClient.cs │ │ │ ├── IFeedClient.cs │ │ │ ├── Mapper.cs │ │ │ ├── Rss.cs │ │ │ └── RssHelper.cs │ │ └── ShowClient.cs │ ├── Podcast.Infrastructure.csproj │ └── Queues │ │ └── Messages │ │ └── NewFeedRequested.cs │ ├── Podcast.Ingestion.Worker │ ├── Dockerfile │ ├── GlobalUsings.cs │ ├── Podcast.Ingestion.Worker.csproj │ ├── PodcastIngestionHandler.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Worker.cs │ ├── appsettings.Development.json │ └── appsettings.json │ └── Podcast.Updater.Worker │ ├── Dockerfile │ ├── GlobalUsings.cs │ ├── Podcast.Updater.Worker.csproj │ ├── PodcastUpdateHandler.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Worker.cs │ ├── appsettings.Development.json │ └── appsettings.json └── Web ├── Client ├── App.razor ├── Podcast.Client.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── _Imports.razor └── wwwroot │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── images │ ├── icon-192x192.png │ ├── icon-256x256.png │ ├── icon-384x384.png │ └── icon-512x512.png │ ├── manifest.json │ ├── service-worker.js │ └── service-worker.published.js ├── Components ├── AudioInterop.cs ├── ClipboardInterop.cs ├── Enums │ └── Theme.cs ├── Events │ └── EventHandlers.cs ├── Extensions │ └── TimeSpanExtensions.cs ├── IAudioInterop.cs ├── ListenTogether │ ├── Emojis │ │ ├── EmojiPanel.razor │ │ ├── EmojiPanel.razor.css │ │ ├── EmojiPanelButton.razor │ │ └── EmojiPanelButton.razor.css │ ├── ListenTogether.razor │ ├── ListenTogether.razor.css │ ├── ListenTogetherEmptyRoom.razor │ ├── ListenTogetherEmptyRoom.razor.css │ ├── ListenTogetherEpisode.razor │ ├── ListenTogetherEpisode.razor.css │ ├── ListenTogetherInvite.razor │ ├── ListenTogetherInvite.razor.css │ ├── ListenTogetherJoinRoom.razor │ ├── ListenTogetherJoinRoom.razor.css │ ├── ListenTogetherRoom.razor │ ├── ListenTogetherRoom.razor.css │ ├── UsernameForm.razor │ └── UsernameForm.razor.css ├── ListenTogetherHubClient.cs ├── LocalStorageInterop.cs ├── Models │ ├── PlayerState.cs │ ├── Room.cs │ ├── RoomEpisode.cs │ ├── RoomShow.cs │ └── User.cs ├── Player │ ├── FloatingPlayer.razor │ └── FloatingPlayer.razor.css ├── Podcast.Components.csproj ├── Shared │ ├── Emojis │ │ ├── ClappingHandsEmoji.razor │ │ ├── CryingFaceEmoji.razor │ │ ├── FaceTearsOfJoyEmoji.razor │ │ ├── HeartEmoji.razor │ │ ├── ThumbsDownEmoji.razor │ │ └── ThumbsUpEmoji.razor │ ├── Grid │ │ ├── Card.razor │ │ ├── Card.razor.css │ │ ├── Grid.razor │ │ └── Grid.razor.css │ ├── Modal.razor │ ├── Modal.razor.css │ ├── NoResults.razor │ ├── NoResults.razor.css │ ├── Picture.razor │ ├── Picture.razor.css │ ├── PlayerBars.razor │ ├── PlayerBars.razor.css │ ├── Spinner.razor │ ├── Spinner.razor.css │ ├── SubtitlePage.razor │ ├── SubtitlePage.razor.css │ ├── Tags.razor │ ├── Tags.razor.css │ ├── TitlePage.razor │ ├── TitlePage.razor.css │ ├── ToggleSwitch.razor │ ├── ToggleSwitch.razor.css │ ├── Tooltip.razor │ └── Tooltip.razor.css ├── ThemeInterop.cs ├── _Imports.razor └── wwwroot │ ├── audioJsInterop.js │ ├── css │ ├── button.css │ ├── fonts │ │ ├── SegoeUI.woff │ │ ├── SegoeUIBold.woff │ │ ├── SegoeUILight.woff │ │ ├── SegoeUISemibold.woff │ │ └── SegoeUISemilight.woff │ ├── icons │ │ ├── fonts │ │ │ ├── podcast-icons.svg │ │ │ ├── podcast-icons.ttf │ │ │ └── podcast-icons.woff │ │ └── style.css │ ├── input.css │ ├── reset.css │ ├── site.css │ ├── splash.css │ └── styles.css │ ├── images │ ├── bg-splash.jpg │ ├── bot-wait.svg │ ├── empty-results.png │ └── logo-icon.svg │ └── themeJsInterop.js ├── E2E ├── package-lock.json ├── package.json ├── playwright.config.ts └── tests │ ├── discover.spec.ts │ ├── listen-later.spec.ts │ ├── listen-together.spec.ts │ ├── login.spec.ts │ ├── podcast-perspective.spec.ts │ ├── settings.spec.ts │ └── subscriptions.spec.ts ├── Pages ├── Data │ ├── ListenLaterService.cs │ ├── PlayerService.cs │ └── SubscriptionsService.cs ├── Events │ ├── DurationChangeEventArgs.cs │ ├── EventHandlers.cs │ ├── PlaybackRateChangeEventArgs.cs │ └── TimeUpdateEventArgs.cs ├── Models │ ├── EpisodeInfo.cs │ └── ShowInfo.cs ├── Pages │ ├── CategoriesPage.razor │ ├── CategoriesPage.razor.css │ ├── CategoryPage.razor │ ├── DiscoverPage.razor │ ├── DiscoverPage.razor.css │ ├── ListenLaterPage.razor │ ├── ListenTogetherPage.razor │ ├── SettingsPage.razor │ ├── SettingsPage.razor.css │ ├── ShowPage.razor │ ├── ShowPage.razor.css │ └── SubscriptionsPage.razor ├── Podcast.Pages.csproj ├── Shared │ ├── Cards │ │ └── ShowCard.razor │ ├── Header.razor │ ├── Header.razor.css │ ├── Lists │ │ ├── EpisodeListItem.razor │ │ └── EpisodeListItem.razor.css │ ├── MainLayout.razor │ ├── MainLayout.razor.css │ ├── NavMenu.razor │ ├── NavMenu.razor.css │ ├── Player │ │ ├── Audio.razor │ │ └── PlayerBar.razor │ ├── SearchBar.razor │ ├── SearchBar.razor.css │ ├── ShowResume.razor │ └── ShowResume.razor.css ├── _Imports.razor └── wwwroot │ ├── images │ ├── logo-flat.svg │ ├── no-listen-later.png │ └── no-subscriptions.png │ └── js │ ├── customEvents.js │ └── theme.js ├── README.md ├── Server ├── Dockerfile ├── Pages │ ├── Error.cshtml │ ├── Error.cshtml.cs │ ├── Landing.cshtml │ ├── Landing.cshtml.cs │ ├── _Host.cshtml │ └── _Layout.cshtml ├── Podcast.Server.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── css │ ├── layout.css │ ├── reset.css │ └── styles.css │ ├── favicon.png │ ├── fonts │ ├── SegoeUI.woff │ ├── SegoeUIBold.woff │ ├── SegoeUILight.woff │ ├── SegoeUISemibold.woff │ └── SegoeUISemilight.woff │ ├── images │ ├── available-android.svg │ ├── available-apple.svg │ ├── available-web.svg │ ├── available-windows.svg │ ├── device_Android.png │ ├── device_Screen_home.png │ ├── device_iPhone.png │ ├── download-app_store.png │ ├── download-google_play.png │ ├── download-microsoft.png │ ├── features-01.png │ ├── features-02.png │ ├── features-03.png │ ├── features-04.png │ ├── features-05.png │ ├── hero_landing_image.jpg │ ├── logo-color.svg │ ├── logo-white-flat.svg │ ├── logo-white.svg │ ├── microsoft-logo.svg │ ├── waves1.png │ ├── waves2.png │ ├── waves3.png │ └── waves4.png │ └── js │ └── scripts.js ├── Shared ├── Category.cs ├── Episode.cs ├── Podcast.Shared.csproj ├── PodcastService.cs └── Show.cs └── docs └── screens ├── desktop ├── discover-dark.jpeg ├── discover.jpeg ├── full-landing.jpeg ├── listen-later.jpeg ├── listen-together-room.jpeg ├── listen-together.jpeg ├── podcast-detail.jpeg ├── settings.jpeg └── subscriptions.jpeg └── mobile ├── discover.jpeg ├── listen-together-room.jpeg ├── listen-together.jpeg ├── podcast-detail.jpeg └── settings.jpeg /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | schedule: 9 | - cron: '15 21 * * 0' 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ 'csharp', 'javascript' ] 24 | 25 | steps: 26 | - name: Checkout repository 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v1 31 | with: 32 | languages: ${{ matrix.language }} 33 | 34 | - name: Autobuild 35 | uses: github/codeql-action/autobuild@v1 36 | 37 | - name: Perform CodeQL Analysis 38 | uses: github/codeql-action/analyze@v1 39 | -------------------------------------------------------------------------------- /.github/workflows/podcast-api.yml: -------------------------------------------------------------------------------- 1 | name: Podcast API CICD 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | paths: 7 | - "src/Services/Podcasts/**" 8 | - "deploy/Services/api.bicep" 9 | - ".github/workflows/podcast-api.yml" 10 | pull_request: 11 | branches: [main] 12 | paths: 13 | - "src/Services/Podcasts/**" 14 | - ".github/workflows/podcast-api.yml" 15 | 16 | workflow_dispatch: 17 | 18 | jobs: 19 | buildPushDeployStaging: 20 | name: "staging" 21 | if: "!contains(github.ref, 'refs/heads/main')" 22 | uses: ./.github/workflows/template-api.yml 23 | concurrency: 24 | group: staging-api 25 | cancel-in-progress: true 26 | secrets: inherit 27 | with: 28 | environment: staging 29 | 30 | buildPushDeployProd: 31 | name: "prod" 32 | if: contains(github.ref, 'refs/heads/main') 33 | uses: ./.github/workflows/template-api.yml 34 | concurrency: 35 | group: prod-api 36 | cancel-in-progress: true 37 | secrets: inherit 38 | with: 39 | environment: prod 40 | -------------------------------------------------------------------------------- /.github/workflows/podcast-dotnet-maui-blazor-cd.yml: -------------------------------------------------------------------------------- 1 | name: Podcast .NET MAUI Blazor CD 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths: 7 | - 'src/MobileBlazor/**' 8 | - '**/*build.props' 9 | - '.github/workflows/podcast-dotnet-maui-blazor-cd.yml' 10 | - '.github/workflows/template-dotnet-maui-cd.yml' 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | jobs: 16 | build-mobile: 17 | uses: ./.github/workflows/template-dotnet-maui-cd.yml 18 | with: 19 | csproj: src/MobileBlazor/mauiapp/NetPodsMauiBlazor.csproj 20 | root_path: src/MobileBlazor/mauiapp/ 21 | encrypted_keystore_path: deploy/Android/android-keystore-test.jks.gpg 22 | keystore_path: android-keystore-test.keystore 23 | secrets: 24 | android_keystore_gpg_pass: ${{secrets.ANDROID_KEYSTORE_GPG_PASSWORD}} 25 | android_signing_store_pass: ${{secrets.ANDROID_SIGNING_STORE_PASS}} 26 | android_signing_key_alias: ${{secrets.ANDROID_SIGNING_KEY_ALIAS}} 27 | android_signing_key_pass: ${{secrets.ANDROID_SIGNING_KEY_PASS}} 28 | -------------------------------------------------------------------------------- /.github/workflows/podcast-dotnet-maui-blazor-ci.yml: -------------------------------------------------------------------------------- 1 | name: Podcast .NET MAUI Blazor CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths: 7 | - 'src/MobileBlazor/**' 8 | - 'src/Web/Components/**' 9 | - '**/*build.props' 10 | - '.github/workflows/podcast-dotnet-maui-blazor-ci.yml' 11 | - '.github/workflows/template-dotnet-maui-ci.yml' 12 | pull_request: 13 | branches: 14 | - '**' 15 | paths: 16 | - 'src/MobileBlazor/**' 17 | - 'src/Web/Components/**' 18 | - '**/*build.props' 19 | - '.github/workflows/podcast-dotnet-maui-blazor-ci.yml' 20 | - '.github/workflows/template-dotnet-maui-ci.yml' 21 | 22 | # Allows you to run this workflow manually from the Actions tab 23 | workflow_dispatch: 24 | 25 | jobs: 26 | build-mobile: 27 | uses: ./.github/workflows/template-dotnet-maui-ci.yml 28 | with: 29 | csproj: src/MobileBlazor/mauiapp/NetPodsMauiBlazor.csproj -------------------------------------------------------------------------------- /.github/workflows/podcast-dotnet-maui-cd.yml: -------------------------------------------------------------------------------- 1 | name: Podcast .NET MAUI CD 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths: 7 | - 'src/Mobile/**' 8 | - '**/*build.props' 9 | - '.github/workflows/podcast-dotnet-maui-cd.yml' 10 | - '.github/workflows/template-dotnet-maui-cd.yml' 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | jobs: 16 | build-mobile: 17 | uses: ./.github/workflows/template-dotnet-maui-cd.yml 18 | with: 19 | csproj: src/Mobile/Microsoft.NetConf2021.Maui.csproj 20 | root_path: src/Mobile/ 21 | encrypted_keystore_path: deploy/Android/android-keystore-test.jks.gpg 22 | keystore_path: android-keystore-test.keystore 23 | secrets: 24 | android_keystore_gpg_pass: ${{secrets.ANDROID_KEYSTORE_GPG_PASSWORD}} 25 | android_signing_store_pass: ${{secrets.ANDROID_SIGNING_STORE_PASS}} 26 | android_signing_key_alias: ${{secrets.ANDROID_SIGNING_KEY_ALIAS}} 27 | android_signing_key_pass: ${{secrets.ANDROID_SIGNING_KEY_PASS}} -------------------------------------------------------------------------------- /.github/workflows/podcast-dotnet-maui-ci.yml: -------------------------------------------------------------------------------- 1 | name: Podcast .NET MAUI CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths: 7 | - 'src/Mobile/**' 8 | - 'src/Web/Components/**' 9 | - '**/*build.props' 10 | - '.github/workflows/podcast-dotnet-maui-ci.yml' 11 | - '.github/workflows/template-dotnet-maui-ci.yml' 12 | pull_request: 13 | branches: 14 | - '**' 15 | paths: 16 | - 'src/Mobile/**' 17 | - 'src/Web/Components/**' 18 | - '**/*build.props' 19 | - '.github/workflows/podcast-dotnet-maui-ci.yml' 20 | - '.github/workflows/template-dotnet-maui-ci.yml' 21 | 22 | # Allows you to run this workflow manually from the Actions tab 23 | workflow_dispatch: 24 | 25 | jobs: 26 | build-mobile: 27 | uses: ./.github/workflows/template-dotnet-maui-ci.yml 28 | with: 29 | csproj: src/Mobile/Microsoft.NetConf2021.Maui.csproj -------------------------------------------------------------------------------- /.github/workflows/template-dotnet-maui-ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_call: 3 | inputs: 4 | csproj: 5 | required: true 6 | type: string 7 | 8 | jobs: 9 | build-mobile: 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Setup .NET 16 | uses: actions/setup-dotnet@v2 17 | with: 18 | dotnet-version: 7.0.x 19 | include-prerelease: true 20 | 21 | - name: Install MAUI Workloads 22 | run: | 23 | dotnet workload install maui --source https://api.nuget.org/v3/index.json 24 | 25 | - name: Build MAUI Mobile app 26 | shell: pwsh 27 | run: | 28 | dotnet build ${{inputs.csproj}} -bl:mobile.binlog 29 | 30 | - name: Archive build log 31 | uses: actions/upload-artifact@v2 32 | with: 33 | name: logs 34 | path: '*.binlog' 35 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 7 | feature request as a new Issue. 8 | 9 | ## Microsoft Support Policy 10 | 11 | Support for this sample app is limited to the resources listed above. 12 | -------------------------------------------------------------------------------- /Test/ARMTemplate/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "name": { 6 | "value": "" 7 | }, 8 | "location": { 9 | "value": "" 10 | }, 11 | "tags": { 12 | "value": {} 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Test/ARMTemplate/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2019-08-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "name": { 6 | "type": "String" 7 | }, 8 | "location": { 9 | "type": "String" 10 | }, 11 | "tags": { 12 | "type": "Object" 13 | } 14 | }, 15 | "resources": [ 16 | { 17 | "type": "Microsoft.LoadTestService/loadtests", 18 | "apiVersion": "2021-12-01-preview", 19 | "name": "[parameters('name')]", 20 | "location": "[parameters('location')]", 21 | "tags": "[parameters('tags')]", 22 | "identity": { 23 | "type": "SystemAssigned" 24 | } 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /Test/Shows.csv: -------------------------------------------------------------------------------- 1 | Merge,facd94eb-8ef9-414a-e72a-08dae7f770f7 2 | Rocks,f3bfb1cf-395a-4c15-e724-08dae7f770f7 3 | CodeNewbie,191e2d48-6722-4f75-e728-08dae7f770f7 4 | Hanselminutes,e5a6f6c9-feec-4883-e722-08dae7f770f7 5 | Mobile,4d812eab-e7c6-4ed9-e71c-08dae7f770f7 6 | Adventures,9c4751d2-d102-4947-e71f-08dae7f770f7 7 | future,01c23abf-8211-422a-e72b-08dae7f770f7 8 | MAUI,8617def2-5021-49e7-e726-08dae7f770f7 9 | Monsters,0befb23c-5991-4e2c-e727-08dae7f770f7 10 | Microsoft,e0f61f7f-79c4-47a6-e723-08dae7f770f7 -------------------------------------------------------------------------------- /Test/config.yml: -------------------------------------------------------------------------------- 1 | testId: MyGitHubPodcastTest 2 | displayName: My GitHub podcast test 3 | testPlan: DemoPodcastTest.jmx 4 | description: '' 5 | engineInstances: 5 6 | configurationFiles: 7 | - jmeter-plugins-functions-2.2.jar 8 | - Shows.csv 9 | splitAllCSVs: True 10 | failureCriteria: 11 | - Podcast page: p90(response_time_ms) > 10000 12 | - Homepage: p90(response_time_ms) > 60000 13 | - percentage(error) > 10 14 | -------------------------------------------------------------------------------- /Test/jmeter-plugins-functions-2.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/Test/jmeter-plugins-functions-2.2.jar -------------------------------------------------------------------------------- /deploy/Android/android-keystore-test.jks.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Android/android-keystore-test.jks.gpg -------------------------------------------------------------------------------- /deploy/Images/Covers/.NET Rocks!.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/.NET Rocks!.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/.future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/.future.png -------------------------------------------------------------------------------- /deploy/Images/Covers/Adventures in .NET – Devchat.tv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Adventures in .NET – Devchat.tv.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Adventures in .NET.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Adventures in .NET.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Asp.Net Monsters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Asp.Net Monsters.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Away From The Keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Away From The Keyboard.png -------------------------------------------------------------------------------- /deploy/Images/Covers/CodeNewbie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/CodeNewbie.png -------------------------------------------------------------------------------- /deploy/Images/Covers/Gone Mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Gone Mobile.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Hanselminutes with Scott Hanselman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Hanselminutes with Scott Hanselman.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Hello World (Audio) - Channel 9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Hello World (Audio) - Channel 9.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Last Week in .NET.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Last Week in .NET.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/MS Dev Show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/MS Dev Show.png -------------------------------------------------------------------------------- /deploy/Images/Covers/Merge Conflict.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Merge Conflict.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Microsoft 365 Developer Podcast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Microsoft 365 Developer Podcast.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Microsoft Mechanics Podcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Microsoft Mechanics Podcast.png -------------------------------------------------------------------------------- /deploy/Images/Covers/Null Pointers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Null Pointers.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/Paths Uncovered.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Paths Uncovered.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/RunAs Radio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/RunAs Radio.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/The .NET Core Podcast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/The .NET Core Podcast.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/The .NET MAUI Podcast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/The .NET MAUI Podcast.jpg -------------------------------------------------------------------------------- /deploy/Images/Covers/The Unhandled Exception Podcast.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/The Unhandled Exception Podcast.jpeg -------------------------------------------------------------------------------- /deploy/Images/Covers/Upwards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/Upwards.png -------------------------------------------------------------------------------- /deploy/Images/Covers/intrazone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/intrazone.png -------------------------------------------------------------------------------- /deploy/Images/Covers/no dogma podcast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/deploy/Images/Covers/no dogma podcast.jpg -------------------------------------------------------------------------------- /deploy/Images/Readme.md: -------------------------------------------------------------------------------- 1 | # Deploy Images 2 | 3 | The `Covers` folder contains all shows pictures resized to 225x255. Images of this folder are deployed to an Azure Blob Storage container with the script [`/Deploy-Images.ps1`](/deploy/Images/Deploy-Images.ps1) and executed in [`podcast-api.yml`](/.github/workflows/podcast-api.yml) workflow. 4 | -------------------------------------------------------------------------------- /deploy/Services/acr.bicep: -------------------------------------------------------------------------------- 1 | @description('Name of the azure container registry (must be globally unique)') 2 | @minLength(5) 3 | @maxLength(50) 4 | param acrName string 5 | 6 | @description('Enable an admin user that has push/pull permission to the registry.') 7 | param acrAdminUserEnabled bool = true 8 | 9 | @description('Location for all resources.') 10 | param location string = resourceGroup().location 11 | 12 | @description('Tier of your Azure Container Registry.') 13 | @allowed([ 14 | 'Basic' 15 | 'Standard' 16 | 'Premium' 17 | ]) 18 | param acrSku string = 'Basic' 19 | 20 | resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' = { 21 | name: acrName 22 | location: location 23 | tags: { 24 | displayName: 'Container Registry' 25 | 'container.registry': acrName 26 | } 27 | sku: { 28 | name: acrSku 29 | } 30 | properties: { 31 | adminUserEnabled: acrAdminUserEnabled 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docker-compose.dcproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.1 5 | Linux 6 | 00e1d6c6-1f3e-44d4-8ea6-b33f5e3aabf6 7 | LaunchBrowser 8 | {Scheme}://localhost:{ServicePort}/swagger 9 | podcast.api 10 | 11 | 12 | 13 | docker-compose.yml 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/demos/authentication/images/add-swagger-authorization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/add-swagger-authorization.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/authorize-swagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/authorize-swagger.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/create-app-role.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/create-app-role.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/delete-feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/delete-feed.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/generated-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/generated-token.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/get-feeds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/get-feeds.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/provide-application-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/provide-application-name.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/select-active-directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/select-active-directory.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/select-app-registrations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/select-app-registrations.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/select-app-roles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/select-app-roles.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/select-create-app-role.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/select-create-app-role.png -------------------------------------------------------------------------------- /docs/demos/authentication/images/select-new-registration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/authentication/images/select-new-registration.png -------------------------------------------------------------------------------- /docs/demos/azurecontainerapps/Simulate-Feed-Requests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [parameter(Mandatory=$false)][string]$baseUrl = "" 3 | ) 4 | 5 | class FeedRequest 6 | { 7 | [string] $Title 8 | [string] $Url 9 | [System.Collections.Generic.List[String]] $Categories 10 | } 11 | 12 | function SimulateRequest { 13 | Param( 14 | [int]$sleep = 100, 15 | [string]$baseUrl 16 | ) 17 | 18 | $feeds = [System.Collections.Generic.List[FeedRequest]](Get-Content './feeds.json' | Out-String | ConvertFrom-Json) 19 | 20 | $feeds | ForEach-Object -ThrottleLimit 20 -Parallel { 21 | Write-Host "> Requesting feed" $_.Title 22 | 23 | Invoke-WebRequest -Method POST -Uri $using:baseUrl"v1/feeds" ` 24 | -Body ($_|ConvertTo-Json) ` 25 | -ContentType application/json 26 | 27 | [System.Threading.Thread]::Sleep($sleep) 28 | } 29 | } 30 | 31 | SimulateRequest -baseUrl $baseUrl 32 | -------------------------------------------------------------------------------- /docs/demos/azurecontainerapps/scale-out-demo-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/azurecontainerapps/scale-out-demo-0.png -------------------------------------------------------------------------------- /docs/demos/azurecontainerapps/scale-out-demo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/azurecontainerapps/scale-out-demo-1.png -------------------------------------------------------------------------------- /docs/demos/azurecontainerapps/scale-out-demo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/azurecontainerapps/scale-out-demo-2.png -------------------------------------------------------------------------------- /docs/demos/blazor-hybrid/README.md: -------------------------------------------------------------------------------- 1 | ### Blazor Hybrid + .NET MAUI Setup 2 | 3 | The .NET MAUI & Blazor Hybrid apps are setup to run locally against the APIs running in Docker. If you are unable to deploy locally, you can use these pre-deployed services: 4 | 5 | Open `src/MobileBlazor/mauiapp/MauiProgram.cs` and enter 6 | 7 | ```csharp 8 | public static string BaseWeb = $"https://dotnetpodcasts.azurewebsites.net/"; 9 | public static string APIUrl = $"https://podcastapica.ashyhill-df3dfdf5.eastus.azurecontainerapps.io"; 10 | public static string ListenTogetherUrl = $"https://dotnetpodcasts-listentogether-hub.azurewebsites.net/listentogether"; 11 | ``` 12 | 13 | Watch the .NET Conf 2021 demo of Blaozry Hybrid & .NET MAUI here: https://youtu.be/gYQxBHjRNr0?t=3999 14 | -------------------------------------------------------------------------------- /docs/demos/dotnet-maui/README.md: -------------------------------------------------------------------------------- 1 | ## .NET MAUI Configuration 2 | 3 | The .NET MAUI apps are setup to run locally against the APIs running in Docker. If you are unable to deploy locally, you can use these pre-deployed services: 4 | 5 | Open `src/Mobile/Config.cs` and enter 6 | 7 | ```csharp 8 | public static string BaseWeb = $"https://dotnetpodcasts.azurewebsites.net/"; 9 | public static string APIUrl = $"https://podcastapica.ashyhill-df3dfdf5.eastus.azurecontainerapps.io/"; 10 | public static string ListenTogetherUrl = $"https://dotnetpodcasts-listentogether-hub.azurewebsites.net/listentogether"; 11 | ``` 12 | 13 | Watch the .NET Conf 2021 demo of .NET MAUI here: https://youtu.be/gYQxBHjRNr0?t=3357 14 | -------------------------------------------------------------------------------- /docs/demos/powerapps/assets/customconnector.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/powerapps/assets/customconnector.jpg -------------------------------------------------------------------------------- /docs/demos/powerapps/assets/editpowerapp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/powerapps/assets/editpowerapp.jpg -------------------------------------------------------------------------------- /docs/demos/powerapps/assets/onstart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/powerapps/assets/onstart.jpg -------------------------------------------------------------------------------- /docs/demos/powerapps/assets/powerapp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/powerapps/assets/powerapp.jpg -------------------------------------------------------------------------------- /docs/demos/powerapps/assets/refreshbutton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/demos/powerapps/assets/refreshbutton.jpg -------------------------------------------------------------------------------- /docs/images/Enable-Workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/Enable-Workflow.png -------------------------------------------------------------------------------- /docs/images/all-workflow-runs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/all-workflow-runs.png -------------------------------------------------------------------------------- /docs/images/arch_diagram_podcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/arch_diagram_podcast.png -------------------------------------------------------------------------------- /docs/images/azure-secret-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/azure-secret-add.png -------------------------------------------------------------------------------- /docs/images/docker-app-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/docker-app-config.png -------------------------------------------------------------------------------- /docs/images/docker-services-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/docker-services-config.png -------------------------------------------------------------------------------- /docs/images/gh-configured-secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/gh-configured-secrets.png -------------------------------------------------------------------------------- /docs/images/github-repo-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/github-repo-settings.png -------------------------------------------------------------------------------- /docs/images/net-podcasts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/net-podcasts.png -------------------------------------------------------------------------------- /docs/images/podcast-api-ci-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/podcast-api-ci-run.png -------------------------------------------------------------------------------- /docs/images/select-secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-podcasts/5ee8be2990b81eb681bbd100875c263aaa5ab68a/docs/images/select-secrets.png -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/INativeAudioService.cs: -------------------------------------------------------------------------------- 1 | namespace SharedMauiLib; 2 | 3 | public interface INativeAudioService 4 | { 5 | Task InitializeAsync(string audioURI); 6 | 7 | Task PlayAsync(double position = 0); 8 | 9 | Task PauseAsync(); 10 | 11 | Task SetMuted(bool value); 12 | 13 | Task SetVolume(int value); 14 | 15 | Task SetCurrentTime(double value); 16 | 17 | ValueTask DisposeAsync(); 18 | 19 | bool IsPlaying { get; } 20 | 21 | double CurrentPosition { get; } 22 | 23 | event EventHandler IsPlayingChanged; 24 | } -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/Platforms/Android/CurrentActivity/ActivityEvent.cs: -------------------------------------------------------------------------------- 1 | namespace SharedMauiLib.Platforms.Android.CurrentActivity 2 | { 3 | public enum ActivityEvent 4 | { 5 | Created, 6 | Resumed, 7 | Paused, 8 | Destroyed, 9 | SaveInstanceState, 10 | Started, 11 | Stopped 12 | } 13 | } -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/Platforms/Android/CurrentActivity/ActivityEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | 3 | namespace SharedMauiLib.Platforms.Android.CurrentActivity 4 | { 5 | public class ActivityEventArgs : EventArgs 6 | { 7 | internal ActivityEventArgs(Activity activity, ActivityEvent ev) 8 | { 9 | Event = ev; 10 | Activity = activity; 11 | } 12 | 13 | public ActivityEvent Event { get; } 14 | public Activity Activity { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/Platforms/Android/EventHandlers.cs: -------------------------------------------------------------------------------- 1 | namespace SharedMauiLib.Platforms.Android; 2 | 3 | public delegate void StatusChangedEventHandler(object sender, EventArgs e); 4 | 5 | public delegate void BufferingEventHandler(object sender, EventArgs e); 6 | 7 | public delegate void CoverReloadedEventHandler(object sender, EventArgs e); 8 | 9 | public delegate void PlayingEventHandler(object sender, EventArgs e); 10 | 11 | public delegate void PlayingChangedEventHandler(object sender, bool e); -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/Platforms/Android/IAudioActivity.cs: -------------------------------------------------------------------------------- 1 | namespace SharedMauiLib.Platforms.Android 2 | { 3 | public interface IAudioActivity 4 | { 5 | public MediaPlayerServiceBinder Binder { get; set; } 6 | 7 | public event StatusChangedEventHandler StatusChanged; 8 | 9 | public event CoverReloadedEventHandler CoverReloaded; 10 | 11 | public event PlayingEventHandler Playing; 12 | 13 | public event BufferingEventHandler Buffering; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/Resources/Images/player_play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Lib/SharedMauiLib/SharedMauiLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0;net7.0-android;net7.0-ios;net7.0-maccatalyst 5 | $(TargetFrameworks);net7.0-windows10.0.19041.0 6 | true 7 | true 8 | enable 9 | 10 | 14.2 11 | 14.0 12 | 21.0 13 | 10.0.17763.0 14 | 10.0.17763.0 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Mobile/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Mobile/Config.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui; 2 | 3 | public static class Config 4 | { 5 | public static bool ListenTogetherIsVisible => true; 6 | 7 | public static bool Desktop 8 | { 9 | get 10 | { 11 | #if WINDOWS || MACCATALYST 12 | return true; 13 | #else 14 | return false; 15 | #endif 16 | } 17 | } 18 | 19 | public static string BaseWeb = $"{Base}:5002/"; 20 | public static string Base = DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2" : "http://localhost"; 21 | public static string APIUrl = $"{Base}:5003/"; 22 | public static string ListenTogetherUrl = $"{Base}:5001/listentogether"; 23 | } 24 | -------------------------------------------------------------------------------- /src/Mobile/Converters/DurationConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace Microsoft.NetConf2021.Maui.Converters 4 | { 5 | class DurationConverter : IValueConverter 6 | { 7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 8 | { 9 | if (value == null) 10 | return value; 11 | var result = string.Empty; 12 | 13 | if (value is string stringValue){ 14 | try 15 | { 16 | var duration = TimeSpan.Parse(stringValue); 17 | result = $"{duration.TotalMinutes.ToString("N0")} min"; 18 | } 19 | finally 20 | { 21 | } 22 | } 23 | 24 | return result; 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Mobile/Converters/IsNullConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace Microsoft.NetConf2021.Maui.Converters 4 | { 5 | class IsNullConverter : IValueConverter 6 | { 7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 8 | { 9 | if(parameter == null) 10 | { 11 | return value == null; 12 | } 13 | else 14 | { 15 | return value != null; 16 | } 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mobile/Converters/TextToTypeTextConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Microsoft.NetConf2021.Maui.Converters; 5 | 6 | class TextToTypeTextConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 9 | { 10 | var isHtml = ContainsHTML(value as string); 11 | 12 | return isHtml 13 | ? TextType.Html 14 | : TextType.Text; 15 | } 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | 22 | private bool ContainsHTML(string text) 23 | { 24 | return !string.IsNullOrWhiteSpace(text) && Regex.IsMatch(text, "<(.|\n)*?>"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mobile/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using CommunityToolkit.Mvvm.ComponentModel; 2 | global using CommunityToolkit.Mvvm.Input; 3 | global using Microsoft.Extensions.DependencyInjection.Extensions; 4 | global using Microsoft.NetConf2021.Maui.Models; 5 | global using Microsoft.NetConf2021.Maui.Pages; 6 | global using Microsoft.NetConf2021.Maui.Services; 7 | global using Microsoft.NetConf2021.Maui.ViewModels; 8 | global using System.Windows.Input; 9 | global using System.Collections.ObjectModel; 10 | global using Microsoft.NetConf2021.Maui.Helpers; 11 | 12 | -------------------------------------------------------------------------------- /src/Mobile/Helpers/TheTheme.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.Messaging; 2 | using Microsoft.NetConf2021.Maui.Messaging; 3 | 4 | namespace Microsoft.NetConf2021.Maui.Helpers; 5 | 6 | public static class TheTheme 7 | { 8 | public static void SetTheme() 9 | { 10 | switch (Settings.Theme) 11 | { 12 | default: 13 | case AppTheme.Light: 14 | App.Current.UserAppTheme = AppTheme.Light; 15 | break; 16 | case AppTheme.Dark: 17 | App.Current.UserAppTheme = AppTheme.Dark; 18 | break; 19 | 20 | } 21 | 22 | WeakReferenceMessenger.Default.Send(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mobile/MauiProgram.cs: -------------------------------------------------------------------------------- 1 | using MonkeyCache.FileStore; 2 | 3 | namespace Microsoft.NetConf2021.Maui; 4 | 5 | public static class MauiProgram 6 | { 7 | public static MauiApp CreateMauiApp() 8 | { 9 | var builder = MauiApp.CreateBuilder(); 10 | builder 11 | .UseMauiApp() 12 | .ConfigureEssentials() 13 | .ConfigureServices() 14 | .ConfigurePages() 15 | .ConfigureViewModels() 16 | .ConfigureFonts(fonts => 17 | { 18 | fonts.AddFont("Segoe-Ui-Bold.ttf", "SegoeUiBold"); 19 | fonts.AddFont("Segoe-Ui-Regular.ttf", "SegoeUiRegular"); 20 | fonts.AddFont("Segoe-Ui-Semibold.ttf", "SegoeUiSemibold"); 21 | fonts.AddFont("Segoe-Ui-Semilight.ttf", "SegoeUiSemilight"); 22 | }); 23 | 24 | Barrel.ApplicationId = "dotnetpodcasts"; 25 | 26 | builder.Services.AddMauiBlazorWebView(); 27 | return builder.Build(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Mobile/Messaging/ChangeThemeNotification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace Microsoft.NetConf2021.Maui.Messaging; 3 | 4 | public class ChangeThemeNotification 5 | { 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/Mobile/Messaging/LeaveRoomNotification.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Messaging; 2 | 3 | public class LeaveRoomNotification 4 | { 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/Mobile/Models/AppSection.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Models; 2 | 3 | public class AppSection 4 | { 5 | public string Title { get; set; } 6 | public string Icon { get; set; } 7 | public string IconDark { get; set; } 8 | public Type TargetType { get; set; } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/Mobile/Models/Category.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.NetConf2021.Maui.Models.Responses; 2 | 3 | namespace Microsoft.NetConf2021.Maui.Models; 4 | 5 | public class Category 6 | { 7 | public Category(CategoryResponse response) 8 | { 9 | Id = response.Id; 10 | Genre = response.Genre; 11 | } 12 | 13 | public Guid Id { get; set; } 14 | 15 | public string Genre { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mobile/Models/Responses/CategoryResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Models.Responses; 2 | 3 | public class CategoryResponse 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string Genre { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Mobile/Models/Responses/EpisodeResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Models.Responses; 2 | 3 | public class EpisodeResponse 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string Title { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public DateTime Published { get; set; } 12 | 13 | public string Duration { get; set; } 14 | 15 | public Uri Url { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mobile/Models/Responses/ShowResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Models.Responses; 2 | 3 | public class ShowResponse 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string Title { get; set; } 8 | 9 | public string Author { get; set; } 10 | 11 | public string Description { get; set; } 12 | 13 | public Uri Image { get; set; } 14 | 15 | public DateTime Updated { get; set; } 16 | 17 | public Uri Link { get; set; } 18 | 19 | public string Email { get; set; } 20 | 21 | public string Language { get; set; } 22 | 23 | public bool IsFeatured { get; set; } 24 | 25 | public CategoryResponse[] Categories { get; set; } 26 | 27 | public EpisodeResponse[] Episodes { get; set; } 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Mobile/Models/ShowGroup.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Models; 2 | 3 | public class ShowGroup : List 4 | { 5 | public string Name { get; private set; } 6 | 7 | public ShowGroup(string name, List show) : base(show) 8 | { 9 | Name = name; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Mobile/Pages/CategoriesPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class CategoriesPage : ContentPage 4 | { 5 | CategoriesViewModel vm => BindingContext as CategoriesViewModel; 6 | public CategoriesPage(CategoriesViewModel vm) 7 | { 8 | InitializeComponent(); 9 | BindingContext = vm; 10 | } 11 | 12 | protected override async void OnAppearing() 13 | { 14 | base.OnAppearing(); 15 | await vm.InitializeAsync(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Mobile/Pages/CategoryPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class CategoryPage : ContentPage 4 | { 5 | CategoryViewModel vm => BindingContext as CategoryViewModel; 6 | public CategoryPage(CategoryViewModel vm) 7 | { 8 | InitializeComponent(); 9 | BindingContext = vm; 10 | } 11 | 12 | protected override async void OnAppearing() 13 | { 14 | base.OnAppearing(); 15 | await vm.InitializeAsync(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Mobile/Pages/DesktopShell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages 2 | { 3 | public partial class DesktopShell 4 | { 5 | public DesktopShell() 6 | { 7 | InitializeComponent(); 8 | 9 | BindingContext = new ShellViewModel(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mobile/Pages/DiscoverPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class DiscoverPage : ContentPage 4 | { 5 | private DiscoverViewModel viewModel => BindingContext as DiscoverViewModel; 6 | 7 | public DiscoverPage(DiscoverViewModel vm) 8 | { 9 | InitializeComponent(); 10 | BindingContext = vm; 11 | } 12 | 13 | protected override async void OnAppearing() 14 | { 15 | base.OnAppearing(); 16 | player.OnAppearing(); 17 | await viewModel.InitializeAsync(); 18 | } 19 | 20 | 21 | protected override void OnDisappearing() 22 | { 23 | player.OnDisappearing(); 24 | base.OnDisappearing(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mobile/Pages/EpisodeDetailPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages 2 | { 3 | public partial class EpisodeDetailPage 4 | { 5 | private EpisodeDetailViewModel viewModel => BindingContext as EpisodeDetailViewModel; 6 | 7 | public EpisodeDetailPage(EpisodeDetailViewModel vm) 8 | { 9 | InitializeComponent(); 10 | BindingContext = vm; 11 | } 12 | 13 | protected override async void OnAppearing() 14 | { 15 | base.OnAppearing(); 16 | this.player.OnAppearing(); 17 | await viewModel.InitializeAsync(); 18 | } 19 | 20 | protected override void OnDisappearing() 21 | { 22 | this.player.OnDisappearing(); 23 | base.OnDisappearing(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mobile/Pages/ListenLaterPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class ListenLaterPage : ContentPage 4 | { 5 | ListenLaterViewModel viewModel => BindingContext as ListenLaterViewModel; 6 | 7 | public ListenLaterPage(ListenLaterViewModel vm) 8 | { 9 | InitializeComponent(); 10 | BindingContext = vm; 11 | } 12 | 13 | protected override async void OnAppearing() 14 | { 15 | base.OnAppearing(); 16 | player.OnAppearing(); 17 | await viewModel.InitializeAsync(); 18 | } 19 | 20 | protected override void OnDisappearing() 21 | { 22 | this.player.OnDisappearing(); 23 | base.OnDisappearing(); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/Mobile/Pages/ListenTogetherPage.xaml.cs: -------------------------------------------------------------------------------- 1 |  2 | using CommunityToolkit.Mvvm.Messaging; 3 | using Microsoft.NetConf2021.Maui.Messaging; 4 | 5 | namespace Microsoft.NetConf2021.Maui.Pages 6 | { 7 | public partial class ListenTogetherPage 8 | { 9 | public ListenTogetherPage() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | protected override void OnAppearing() 15 | { 16 | base.OnAppearing(); 17 | player.OnAppearing(); 18 | } 19 | 20 | protected override void OnDisappearing() 21 | { 22 | player.OnDisappearing(); 23 | 24 | WeakReferenceMessenger.Default.Send(); 25 | 26 | base.OnDisappearing(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Mobile/Pages/MobileShell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages 2 | { 3 | public partial class MobileShell 4 | { 5 | public MobileShell() 6 | { 7 | InitializeComponent(); 8 | 9 | BindingContext = new ShellViewModel(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Mobile/Pages/PagesExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public static class PagesExtensions 4 | { 5 | public static MauiAppBuilder ConfigurePages(this MauiAppBuilder builder) 6 | { 7 | // main tabs of the app 8 | builder.Services.AddSingleton(); 9 | builder.Services.AddSingleton(); 10 | builder.Services.AddSingleton(); 11 | builder.Services.AddSingleton(); 12 | builder.Services.AddSingleton(); 13 | 14 | // pages that are navigated to 15 | builder.Services.AddTransient(); 16 | builder.Services.AddTransient(); 17 | builder.Services.AddTransient(); 18 | builder.Services.AddTransient(); 19 | 20 | return builder; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Mobile/Pages/SettingsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class SettingsPage 4 | { 5 | public SettingsPage(SettingsViewModel vm) 6 | { 7 | InitializeComponent(); 8 | BindingContext = vm; 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /src/Mobile/Pages/ShowDetailPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class ShowDetailPage : ContentPage 4 | { 5 | private ShowDetailViewModel viewModel => BindingContext as ShowDetailViewModel; 6 | 7 | public ShowDetailPage(ShowDetailViewModel vm) 8 | { 9 | InitializeComponent(); 10 | BindingContext = vm; 11 | } 12 | 13 | protected override async void OnAppearing() 14 | { 15 | base.OnAppearing(); 16 | this.player.OnAppearing(); 17 | await viewModel.InitializeAsync(); 18 | } 19 | 20 | protected override void OnDisappearing() 21 | { 22 | this.player.OnDisappearing(); 23 | base.OnDisappearing(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Mobile/Pages/SubscriptionsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.NetConf2021.Maui.Pages; 2 | 3 | public partial class SubscriptionsPage: ContentPage 4 | { 5 | SubscriptionsViewModel viewModel => BindingContext as SubscriptionsViewModel; 6 | public SubscriptionsPage(SubscriptionsViewModel vm) 7 | { 8 | InitializeComponent(); 9 | BindingContext = vm; 10 | } 11 | 12 | protected override async void OnAppearing() 13 | { 14 | base.OnAppearing(); 15 | await viewModel.InitializeAsync(); 16 | this.player.OnAppearing(); 17 | } 18 | 19 | protected override void OnDisappearing() 20 | { 21 | this.player.OnDisappearing(); 22 | base.OnDisappearing(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mobile/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Mobile/Platforms/Android/MainApplication.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Runtime; 3 | 4 | namespace Microsoft.NetConf2021.Maui; 5 | 6 | [Application] 7 | public class MainApplication : MauiApplication 8 | { 9 | public MainApplication(IntPtr handle, JniHandleOwnership ownership) 10 | : base(handle, ownership) 11 | { 12 | } 13 | 14 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 15 | } 16 | -------------------------------------------------------------------------------- /src/Mobile/Platforms/Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #C00CC0 4 | #C00CC0 5 | #C00CC0 6 | -------------------------------------------------------------------------------- /src/Mobile/Platforms/Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Application = Microsoft.Maui.Controls.Application; 2 | 3 | namespace NetPodsMauiBlazor; 4 | 5 | public partial class App : Application 6 | { 7 | public App() 8 | { 9 | InitializeComponent(); 10 | 11 | MainPage = new MainPage(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/Main.razor: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 |

Sorry, there's nothing at this address.

9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace NetPodsMauiBlazor; 2 | 3 | public partial class MainPage : ContentPage 4 | { 5 | public MainPage() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @inject NavigationManager NavigationManager 3 | 4 | @code { 5 | protected override void OnInitialized() 6 | { 7 | NavigationManager.NavigateTo("/discover"); 8 | } 9 | } -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/Platforms/Android/MainApplication.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Runtime; 3 | 4 | namespace NetPodsMauiBlazor; 5 | 6 | [Application] 7 | public class MainApplication : MauiApplication 8 | { 9 | public MainApplication(IntPtr handle, JniHandleOwnership ownership) 10 | : base(handle, ownership) 11 | { 12 | } 13 | 14 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 15 | } 16 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/Platforms/Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #C00CC0 4 | #C00CC0 5 | #C00CC0 6 | -------------------------------------------------------------------------------- /src/MobileBlazor/mauiapp/Platforms/Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |