void RenderItem(MidiDirectScrollItemController item, Storage.Protos.Api.MidiProto midi)
        {
            item.nameText.text     = midi.name;
            item.authorText.text   = midi.artistName;
            item.uploaderText.text = "upload by " + midi.uploaderName;
            item.albumText.text    = midi.album == null ? midi.sourceAlbumName : midi.album.name.TranslateArtifact();
            item.songText.text     = midi.song == null ? midi.sourceSongName : midi.song.name.TranslateArtifact();

            if (midi.coverUrl != null)
            {
                web.LoadTexture(midi.coverUrl, job => {
                    item.coverImageCutter.Cut(job.GetKey(), job.GetData());
                });
            }
            else
            {
                item.coverImageCutter.Cut(item.defaultTexture.name, item.defaultTexture);
            }

            item.downloadButton.onClick.RemoveAllListeners();
            item.downloadButton.onClick.AddListener(() => DownloadMidi(item, midi));

            if (web.CheckUrlFileExists(midi.hash))
            {
                item.coverImageCutter.image.color = new Color(1, 1, 1, .5f);
                item.iconText.text = FontAwesome.Solid.CheckCircle;
            }
            else
            {
                item.coverImageCutter.image.color = new Color(1, 1, 1, 1);
                item.iconText.text = FontAwesome.Solid.CloudDownloadAlt;
            }
        }
        public void DownloadMidi(MidiDirectScrollItemController item, Storage.Protos.Api.MidiProto midiProto)
        {
            string hash = midiProto.hash;

            if (web.CheckUrlFileExists(hash))
            {
                return;
            }

            item.iconText.text = FontAwesome.Solid.Spinner;
            anim.New(item)
            .RotateTo(item.iconText.transform, 360, 1, EsType.BackOut).Then()
            .RotateTo(item.iconText.transform, 0, 1, EsType.BackOut).Then().Repeat();

            net.ClAppMidiDownload(hash, (error, data) => {
                var loadJob = web.LoadNull(hash, (string)data, job => {
                    db.WriteDoc(LocalDb.COLLECTION_MIDIS, midiProto._id, midiProto);
                    if (midiProto.song != null)
                    {
                        db.WriteDoc(LocalDb.COLLECTION_SONGS, midiProto.song._id, midiProto.song);
                    }
                    if (midiProto.album != null)
                    {
                        db.WriteDoc(LocalDb.COLLECTION_ALBUMS, midiProto.album._id, midiProto.album);
                    }
                    if (midiProto.author != null)
                    {
                        db.WriteDoc(LocalDb.COLLECTION_PERSONS, midiProto.author._id, midiProto.author);
                    }
                    if (midiProto.composer != null)
                    {
                        db.WriteDoc(LocalDb.COLLECTION_PERSONS, midiProto.composer._id, midiProto.composer);
                    }
                    job.GetData();
                    anim.Clear(item);
                    item.coverImageCutter.image.color     = new Color(1, 1, 1, .5f);
                    item.iconText.transform.localRotation = Quaternion.identity;
                    item.iconText.text = FontAwesome.Solid.CheckCircle;
                });

                anim.Clear(item);
                game.ExecuteOnMain(() => item.iconText.transform.localRotation = Quaternion.identity);
                anim.New(item).Wait(.001f).Then().Call(() => {
                    item.iconText.text = string.Format("<size=16>{0:P0}</size>", loadJob.GetProgress());
                }).Repeat();
            });
        }