Beispiel #1
0
        /// <summary>
        /// Creates an <see cref="IAvatarProvider"/> based on the given
        /// <see cref="AvatarProvider"/> and <see cref="AvatarFallbackType"/> enum options.
        /// </summary>
        /// <returns>Returns an avatar provider that can be used to resolve user avatars.</returns>
        public static IAvatarProvider CreateAvatarProvider(
            AvatarProvider provider,
            AvatarFallbackType?fallbackType,
            IAvatarDownloader downloader = null)
        {
            // initialize download only if needed (some options, like local providers, don't need a downloader)
            // and use the downloader provided as parameter if possible.
            var lazyDownloader = new Lazy <IAvatarDownloader>(() => downloader ?? new AvatarDownloader());

            // build collection of (non-null) providers
            var providers = new[]
            {
                BuildMainProvider(),
                BuildFallbackProvider()
            }
            .Where(p => p != null)
            .ToArray();

            // only create chained avatar overhead if really needed
            return(providers.Length switch
            {
                0 => null,
                1 => providers[0],
                _ => new ChainedAvatarProvider(providers),
            });
Beispiel #2
0
        public ActorViewModel(ActorModel model)
        {
            Login = model?.Login ?? "[unknown]";

            if (model?.AvatarUrl != null)
            {
                try
                {
                    var uri = new Uri(model.AvatarUrl);

                    // Image requests to enterprise hosts over https always fail currently,
                    // so just display the default avatar. See #1547.
                    if (uri.Scheme != "https" ||
                        uri.Host.EndsWith("githubusercontent.com", StringComparison.OrdinalIgnoreCase))
                    {
                        AvatarUrl = model.AvatarUrl;
                        Avatar    = new BitmapImage(uri);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex, "Invalid avatar URL");
                }
            }

            if (AvatarUrl == null)
            {
                Avatar    = AvatarProvider.CreateBitmapImage(DefaultAvatar);
                AvatarUrl = DefaultAvatar;
            }
        }
Beispiel #3
0
 public ActorViewModel(ActorModel model)
 {
     Login  = model?.Login ?? "[unknown]";
     Avatar = model?.AvatarUrl != null ?
              new BitmapImage(new Uri(model.AvatarUrl)) :
              AvatarProvider.CreateBitmapImage(DefaultAvatar);
     AvatarUrl = model?.AvatarUrl ?? DefaultAvatar;
 }
        public void DoesNotThrowOnNullUserOrAvatarUrl()
        {
            var blobStore = Substitute.For <IBlobCache>();

            blobStore.Invalidate(null).Returns(_ => { throw new ArgumentNullException(); });
            var sharedCache = Substitute.For <ISharedCache>();

            sharedCache.LocalMachine.Returns(blobStore);

            var avatarProvider = new AvatarProvider(sharedCache, new TestImageCache());

            avatarProvider.InvalidateAvatar(null);
            avatarProvider.InvalidateAvatar(Substitute.For <IAvatarContainer>());
        }
        public void GetsBytesFromImage()
        {
            var image = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png");

            byte[] bytes;
            var    encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(image));
            using (var ms = new MemoryStream())
            {
                encoder.Save(ms);
                bytes = ms.ToArray();
            }

            Assert.NotNull(bytes);
            Assert.True(bytes.Length > 256);
        }
        public async Task RetrievesGitHubAvatar()
        {
            var expectedImage = AvatarProvider.CreateBitmapImage("pack://*****:*****@test.com&s=140");
            var blobCache     = new InMemoryBlobCache();
            var sharedCache   = Substitute.For <ISharedCache>();

            sharedCache.LocalMachine.Returns(blobCache);
            var imageCache = new TestImageCache();
            await imageCache.SeedImage(avatarUrl, expectedImage, DateTimeOffset.MaxValue);

            var avatarProvider  = new AvatarProvider(sharedCache, imageCache);
            var avatarContainer = Substitute.For <IAvatarContainer>();

            avatarContainer.AvatarUrl.Returns("https://avatars.githubusercontent.com/u/[email protected]&s=140");

            var retrieved = await avatarProvider.GetAvatar(avatarContainer);

            AssertSameImage(expectedImage, retrieved);
        }
        public async Task CanBeAccessedFromMultipleThreads()
        {
            var blobCache   = new InMemoryBlobCache();
            var sharedCache = Substitute.For <ISharedCache>();

            sharedCache.LocalMachine.Returns(blobCache);
            var imageCache     = new TestImageCache();
            var avatarProvider = new AvatarProvider(sharedCache, imageCache);
            var expected       = avatarProvider.DefaultUserBitmapImage.ToString();
            int mainThreadId   = Thread.CurrentThread.ManagedThreadId;
            int otherThreadId  = mainThreadId;

            var actual = await Task.Run(() =>
            {
                otherThreadId = Thread.CurrentThread.ManagedThreadId;
                return(avatarProvider.DefaultUserBitmapImage.ToString());
            });

            Assert.Equal(expected, actual);
            Assert.NotEqual(mainThreadId, otherThreadId);
        }
        public static IEnumerable <IPullRequestCheckViewModel> Build(IViewViewModelFactory viewViewModelFactory, PullRequestDetailModel pullRequest)
        {
            return(pullRequest.Statuses?.Select(model =>
            {
                PullRequestCheckStatus checkStatus;
                switch (model.State)
                {
                case StatusState.Expected:
                case StatusState.Error:
                case StatusState.Failure:
                    checkStatus = PullRequestCheckStatus.Failure;
                    break;

                case StatusState.Pending:
                    checkStatus = PullRequestCheckStatus.Pending;
                    break;

                case StatusState.Success:
                    checkStatus = PullRequestCheckStatus.Success;
                    break;

                default:
                    throw new InvalidOperationException("Unkown PullRequestCheckStatusEnum");
                }

                var pullRequestCheckViewModel = (PullRequestCheckViewModel)viewViewModelFactory.CreateViewModel <IPullRequestCheckViewModel>();
                pullRequestCheckViewModel.Title = model.Context;
                pullRequestCheckViewModel.Description = model.Description;
                pullRequestCheckViewModel.Status = checkStatus;
                pullRequestCheckViewModel.DetailsUrl = new Uri(model.TargetUrl);
                pullRequestCheckViewModel.AvatarUrl = model.AvatarUrl ?? DefaultAvatar;
                pullRequestCheckViewModel.Avatar = model.AvatarUrl != null
                    ? new BitmapImage(new Uri(model.AvatarUrl))
                    : AvatarProvider.CreateBitmapImage(DefaultAvatar);

                return pullRequestCheckViewModel;
            }) ?? new PullRequestCheckViewModel[0]);
        }
        public void CopyFromDoesNotLoseAvatar()
        {
            var userImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png");
            var orgImage  = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_org_avatar.png");

            var initialBitmapImageSubject = new Subject <BitmapImage>();

            var collectionEvent     = new ManualResetEvent(false);
            var avatarPropertyEvent = new ManualResetEvent(false);

            //Creating an initial account with an observable that returns immediately
            const string login = "******";
            const int    initialOwnedPrivateRepositoryCount = 1;

            var initialAccount = new Account(login, true, false, initialOwnedPrivateRepositoryCount, 0, initialBitmapImageSubject);

            //Creating the test collection
            var col = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare);

            col.Subscribe(account =>
            {
                collectionEvent.Set();
            }, () => { });

            //Adding that account to the TrackingCollection
            col.AddItem(initialAccount);

            //Waiting for the collection add the item
            collectionEvent.WaitOne();
            collectionEvent.Reset();

            //Checking some initial properties
            Assert.That(login, Is.EqualTo(col[0].Login));
            Assert.That(initialOwnedPrivateRepositoryCount, Is.EqualTo(col[0].OwnedPrivateRepos));

            //Demonstrating that the avatar is not yet present
            Assert.That(col[0].Avatar, Is.Null);

            //Adding a listener to check for the changing of the Avatar property
            initialAccount.Changed.Subscribe(args =>
            {
                if (args.PropertyName == "Avatar")
                {
                    avatarPropertyEvent.Set();
                }
            });

            //Providing the first avatar
            initialBitmapImageSubject.OnNext(userImage);
            initialBitmapImageSubject.OnCompleted();

            //Waiting for the avatar to be added
            avatarPropertyEvent.WaitOne();
            avatarPropertyEvent.Reset();

            //Demonstrating that the avatar is present
            Assert.That(col[0].Avatar, Is.Not.Null);
            Assert.True(BitmapSourcesAreEqual(col[0].Avatar, userImage));
            Assert.False(BitmapSourcesAreEqual(col[0].Avatar, orgImage));

            //Creating an account update
            const int updatedOwnedPrivateRepositoryCount = 2;
            var       updatedBitmapImageSubject          = new Subject <BitmapImage>();
            var       updatedAccount = new Account(login, true, false, updatedOwnedPrivateRepositoryCount, 0, updatedBitmapImageSubject);

            //Updating the account in the collection
            col.AddItem(updatedAccount);

            //Waiting for the collection to process the update
            collectionEvent.WaitOne();
            collectionEvent.Reset();

            //Providing the second avatar
            updatedBitmapImageSubject.OnNext(orgImage);
            updatedBitmapImageSubject.OnCompleted();

            //Waiting for the delayed bitmap image observable
            avatarPropertyEvent.WaitOne();
            avatarPropertyEvent.Reset();

            //Login is the id, so that should be the same
            Assert.That(login, Is.EqualTo(col[0].Login));

            //CopyFrom() should have updated this field
            Assert.That(updatedOwnedPrivateRepositoryCount, Is.EqualTo(col[0].OwnedPrivateRepos));

            //CopyFrom() should not cause a race condition here
            Assert.That(col[0].Avatar, Is.Not.Null);
            Assert.True(BitmapSourcesAreEqual(col[0].Avatar, orgImage));
            Assert.False(BitmapSourcesAreEqual(col[0].Avatar, userImage));
        }
        public async Task TestMethod1()
        {
            var uri = await AvatarProvider.GetAvatarUri();

            uri.Should().NotBeNullOrEmpty();
        }
Beispiel #11
0
 public ActorViewModelDesigner()
 {
     AvatarUrl = "pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png";
     Avatar    = AvatarProvider.CreateBitmapImage(AvatarUrl);
 }