Flickering when updating the datacontext in background - xaml

I'm studying UWP by Windows 10 development for absolute beginners, and I meet some problems.
Reflash my ObservableCollection<> data will cause the screen to flash. How do I fix it?
The program details are in UWP beginner
//CS FILE CODE
public sealed partial class FinancialPage : Page
{
ObservableCollection<NewsItem> NewsItems;
public FinancialPage()
{
NewsItems = new ObservableCollection<NewsItem>();
this.InitializeComponent();
GetNewsItemManager.GetNewItemsByCategory(NewsItems, "Financial");
}
}
// XAML FILE CODE
<GridView ItemsSource="{x:Bind NewsItems}" Background="LightGray">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:NewsItem">
<local:NewsContentControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
//MODELS NEWSITEMS CLASS FILE
public static void GetNewItemsByCategory(ObservableCollection<NewsItem> NewsItems, string Category)
{
var allnewsitems = getNewsItems();
var filteredNewsItems = allnewsitems.Where(p => p.Category == Category && IsExist(NewsItems, p.Id)).ToList();
filteredNewsItems.ForEach(p => NewsItems.Add(p));
}
private static Boolean IsExist(ObservableCollection<NewsItem> NewsItems, int Id)
{
return NewsItems.ToList().TrueForAll(p => Id == p.Id);
}
private static List<NewsItem> getNewsItems()
{
var items = new List<NewsItem>();
items.Add(new NewsItem() { Id = 1, Category = "Financial", Headline = "Lorem Ipsum", Subhead = "doro sit amet", DateLine = "Nunc tristique nec", Image = "Assets/Financial1.png" });
items.Add(new NewsItem() { Id = 2, Category = "Financial", Headline = "Etiam ac felis viverra", Subhead = "vulputate nisl ac, aliquet nisi", DateLine = "tortor porttitor, eu fermentum ante congue", Image = "Assets/Financial2.png" });
items.Add(new NewsItem() { Id = 3, Category = "Financial", Headline = "Integer sed turpis erat", Subhead = "Sed quis hendrerit lorem, quis interdum dolor", DateLine = "in viverra metus facilisis sed", Image = "Assets/Financial3.png" });
items.Add(new NewsItem() { Id = 4, Category = "Financial", Headline = "Proin sem neque", Subhead = "aliquet quis ipsum tincidunt", DateLine = "Integer eleifend", Image = "Assets/Financial4.png" }); items.Add(new NewsItem() { Id = 5, Category = "Financial", Headline = "Mauris bibendum non leo vitae tempor", Subhead = "In nisl tortor, eleifend sed ipsum eget", DateLine = "Curabitur dictum augue vitae elementum ultrices", Image = "Assets/Financial5.png" });
items.Add(new NewsItem() { Id = 6, Category = "Food", Headline = "Lorem ipsum", Subhead = "dolor sit amet", DateLine = "Nunc tristique nec", Image = "Assets/Food1.png" });
items.Add(new NewsItem() { Id = 7, Category = "Food", Headline = "Etiam ac felis viverra", Subhead = "vulputate nisl ac, aliquet nisi", DateLine = "tortor porttitor, eu fermentum ante congue", Image = "Assets/Food2.png" });
items.Add(new NewsItem() { Id = 8, Category = "Food", Headline = "Integer sed turpis erat", Subhead = "Sed quis hendrerit lorem, quis interdum dolor", DateLine = "in viverra metus facilisis sed", Image = "Assets/Food3.png" });
items.Add(new NewsItem() { Id = 9, Category = "Food", Headline = "Proin sem neque", Subhead = "aliquet quis ipsum tincidunt", DateLine = "Integer eleifend", Image = "Assets/Food4.png" });
items.Add(new NewsItem() { Id = 10, Category = "Food", Headline = "Mauris bibendum non leo vitae tempor", Subhead = "In nisl tortor, eleifend sed ipsum eget", DateLine = "Curabitur dictum augue vitae elementum ultrices", Image = "Assets/Food5.png" });
return items;
}

Assuming
NewsItem.Clear();
filteredNewsItems.ForEach(p => NewsItem.Add(p));
should be
NewsItems.Clear();
filteredNewsItems.ForEach(p => NewsItems.Add(p));
I assume the "flash" you are seeing (can't be certain as you haven't provided a full repro) is due to what you're doing to show the updated list.
Yes, removing everything and then adding a new (mostly similar) list back can create what some people describe as a "flash".
A better approach would be to remove the items you don't want displayed any more and then add in any extra ones you do.
Something like this:
foreach (var newsItem in NewsItems.Reverse())
{
if (newsItem.Category != Category)
{
NewsItems.Remove(newsItem);
}
}
foreach (var fni in filteredNewsItems)
{
if (!NewsItems.Contains(fni))
{
NewsItems.Add(fni);
}
}

OK... I think I've found a solution for you.
Instead of updating the bindings in your user control with the lambda expression, try it this way:
public NewsContentControl()
{
this.InitializeComponent();
this.DataContextChanged += OnDataCtxChanged; //+= (s, e) => Bindings.Update();
}
private void OnDataCtxChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
System.Diagnostics.Debug.WriteLine("context 'changed'");
if(NewsItem != args.NewValue as NewsItem)
{
Bindings.Update();
}
}
This triggers the update only if the value is actually different. Additionally, you can use "Binding" instead of x:Bind.
None of this answers for me why the datacontext is changing... but this should get rid of your flicker.

Related

How to set a timer to update API data periodically in Flutter

I'm getting data from an API and load it to a listview. My listview is showing the result of the query without any problem. I want to update my listview by periodically getting data from API. What is the best way to do this?
This is how I'm calling API method in initState of Home Screen.
#override
void initState() {
// TODO: implement initState
super.initState();
_fixtureData = getFixture();
}
Future<List<Fixtures>> getFixture() async {
fixtureList = await FootballApi.getFixtureData();
return fixtureList;
}
This is the code which I render ListView by FutureBuilder in Home Screen.
FutureBuilder<List<Fixtures>>(
future: _fixtureData,
builder: (context, snapshot) {
if (snapshot.hasData) {
fixtureList = snapshot.data;
return AppListView(
matchList: fixtureList,
//callback function brings the matchCounter value from ListView class
onChange: (value) {
setState(() {
matchCounter = value;
});
},
finalBetList: (value) {
setState(() {
betList = value;
});
},
);
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'Awaiting result...',
style: TextStyle(color: Colors.white),
),
)
],
);
},
),
And this snippet is the API method that I call.
static Future<List<Fixtures>> getFixtureData() async {
Map<String, String> queryParameters = {
'league': '79',
'next': '5',
};
http.Response response = await http.get(
getUrl('fixtures', queryParameters),
headers: requestHeaders,
);
if (response.statusCode == 200) {
String data = response.body;
List<dynamic> result = jsonDecode(data)['response'];
for (int i = 0; i < result.length; i++) {
Fixtures fixture = Fixtures();
fixture.leagueID = jsonDecode(data)['response'][i]['league']['id'];
fixture.country = jsonDecode(data)['response'][i]['league']['country'];
fixture.leagueName = jsonDecode(data)['response'][i]['league']['name'];
fixture.fixtureID = jsonDecode(data)['response'][i]['fixture']['id'];
//get Odds to match with fixtures by fixtureID
await getOddsData(fixture.fixtureID);
fixture.dateTime =
DateTime.parse(jsonDecode(data)['response'][i]['fixture']['date']);
fixture.homeTeam =
jsonDecode(data)['response'][i]['teams']['home']['name'];
fixture.awayTeam =
jsonDecode(data)['response'][i]['teams']['away']['name'];
fixture.status =
jsonDecode(data)['response'][i]['fixture']['status']['long'];
fixture.homeGoals = jsonDecode(data)['response'][i]['goals']['home'];
fixture.awayGoals = jsonDecode(data)['response'][i]['goals']['away'];
fixture.htScoreHome =
jsonDecode(data)['response'][i]['score']['halftime']['home'];
fixture.htScoreAway =
jsonDecode(data)['response'][i]['score']['halftime']['away'];
fixture.ftScoreHome =
jsonDecode(data)['response'][i]['score']['fulltime']['home'];
fixture.ftScoreAway =
jsonDecode(data)['response'][i]['score']['fulltime']['away'];
if (oddsList.length > 0) {
for (int j = 0; j < oddsList.length; j++) {
if (oddsList[j].fixtureID == fixture.fixtureID) {
fixture.homeOdds = oddsList[j].homeOdds;
fixture.drawOdds = oddsList[j].drawOdds;
fixture.awayOdds = oddsList[j].awayOdds;
fixture.bookmakerName = oddsList[j].bookmakerName;
FootballApi.fixtureList.add(
fixture);
}
}
}
}
} else {
print('statusCode: ' + response.statusCode.toString());
}
return FootballApi.fixtureList;
}
A timer would be a nice choice.
Start a timer once your state is initialized and dispose of once the widget is disposed.
Inside the timer, you call the API and setState for the widget.
#override
void initState() {
getFixture();
_timer = new Timer.periodic(Duration(seconds: 30),
(_) => getFixture());
super.initState();
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}

How to migrate HttpWebRequest for Multipart file to HttpClient

I am working on an ASP.Net Core 2.0 API and one of the services I need to create is to upload files to a 3rd party site via their API. The examples for their API uses HttpWebRequest and I need to migrate this to use HttpClient.
Below is the relevant portion of their example code for a file upload.
var url = "https://localhost:44636/api/uploads";
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
var credentialCache = new CredentialCache();
var username = "APIUser";
var password = "APIUserPassword";
credentialCache.Add(new Uri(url), "Basic", new NetworkCredential(username, password));
request.Credentials = credentialCache;
request.PreAuthenticate = true;
request.Accept = "application/json";
request.AllowWriteStreamBuffering = true;
var uploadFileRequest = new UploadFileRequest();
uploadFileRequest.environment = "DEV";
uploadFileRequest.filename = filename;
uploadFileRequest.multipartFile = File.ReadAllText(filepath + #"\" + filename, UTF8Encoding.UTF8);
var boundaryText = "--ACI-XFER";
var bodyText = new StringBuilder();
bodyText.Append("--" + boundaryText + "\r\n");
bodyText.Append("Content-Disposition: form-data; name=\"filename\"" + "\r\n\r\n");
bodyText.Append(uploadFileRequest.filename + "\r\n");
bodyText.Append("--" + boundaryText + "\r\n");
bodyText.Append("Content-Disposition: form-data; name=\"environment\"" + "\r\n\r\n");
bodyText.Append(uploadFileRequest.environment + "\r\n");
bodyText.Append("--" + boundaryText + "\r\n");
bodyText.Append("Content-Disposition: form-data; name=\"multipartFile\"; filename=\"" +
uploadFileRequest.filename + "\"" + "\r\n");
bodyText.Append("Content-Type: text/plain" + "\r\n\r\n");
bodyText.Append(uploadFileRequest.multipartFile + "\r\n");
bodyText.Append("--" + boundaryText + "--");
var bodyBytes = UTF8Encoding.UTF8.GetBytes(bodyText.ToString());
request.ContentType = "multipart/form-data; boundary=" + boundaryText;
request.ContentLength = bodyBytes.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(bodyBytes, 0, bodyBytes.Length);
requestStream.Close();
using (var webResponse = (HttpWebResponse)request.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
using (var responseReader = new StreamReader(webResponse.GetResponseStream()))
{
var responseText = responseReader.ReadToEnd();
if (logger.IsDebugEnabled)
{
logger.Debug("HttpWebResponse: \r\n" + responseText + "\r\n");
}
}
return true;
}
else
{
if (logger.IsErrorEnabled)
{
logger.Error("HttpWebResponse Error UploadProcessFile(), Server: " +
webResponse.Server + ", StatusCode: " + webResponse.StatusCode + ", StatusDescription: " +
webResponse.StatusDescription);
}
return false;
}
}
}
In ASP.NET Core 2.0 using the HttpClient, I have come up with this code, but when I try to upload the file, I get a 400 error stating "Please select a file to upload"
boundryText = "ACI-XFER"
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44636");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string relativeUrl = "api/uploads";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, relativeUrl);
var byteArray = new UTF8Encoding().GetBytes("APIUser:APIUserPassword");
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
using (var content = new MultipartFormDataContent(boundryText))
{
content.Add(new StringContent(uploadFileRequestDto.FileName + "\r\n"), "filename");
content.Add(new StringContent(uploadFileRequestDto.PdxEnvironment + "\r\n"), "environment");
Encoding encNoBoM = new UTF8Encoding(false);
content.Add(new StringContent(uploadFileRequestDto.TextFile + "\"" + "\r\n", encNoBoM, "text/plain"), "multipartfile", uploadFileRequestDto.FileName);
request.Content = content;
response = await client.SendAsync(request);
}
}
if (response.IsSuccessStatusCode)
{
string jsonResult = response.Content.ReadAsStringAsync().Result;
uploadFileResponseDto = (uploadFileResponseDto)JsonConvert.DeserializeObject(jsonResult);
uploadFileResponseDto.Success = true;
uploadFileResponseDto.StatusCode = 200;
return uploadFileResponseDto;
}
_logger.LogError("File upload for Id [{ID}] failed. Reason: {ReasonPhrase}", uploadFileRequestDto.Id, response.ReasonPhrase);
uploadFileResponseDto.Success = false;
uploadFileResponseDto.Reason = string.Format($"Status Code: [{response.StatusCode}], Reason: [{response.ReasonPhrase}]");
uploadFileResponseDto.StatusCode = 500;
return uploadFileResponseDto;
Here is the request as it looks in Fiddler;
**Headers**
POST /api/uploads HTTP/1.1
Connection: Keep-Alive
Content-Type: multipart/form-data; boundary="--ACI-XFER"
Accept: application/json
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXX
x-ms-request-root-id: 4f112b3-4c33c20cb1d76dec
x-ms-request-id: |4f112b3-4c33c20cb1d76dec.1.
Request-Id: |4f112b3-4c33c20cb1d76dec.1.1.
Content-Length: 325354
Host: localhost:44636
Content
----ACI-XFER
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=filename
test1upload.txt
----ACI-XFER
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=environment
DEV
----ACI-XFER
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=multipartfile; filename=test1upload.txt; filename*=utf-8''test1upload.txt
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
I feel that the problem is coming from how I am doing this line in my code, which sets up the text file content to upload;
content.Add(new StringContent(uploadFileRequestDto.TextFile + "\"" + "\r\n", encNoBoM, "text/plain"), "multipartfile", uploadFileRequestDto.FileName);
I had first tried it like this, without the added and slashes and carriage return line feed, but got the same error.
content.Add(new StringContent(uploadFileRequestDto.TextFile, encNoBoM, "text/plain"), "multipartfile", uploadFileRequestDto.FileName);
But I am having difficulty finding a good example of how to do this.
Any ideas?

Can't stream PDF file (.net core 2.0)

For a few days I have no idea how to solve my problem.
I need return to user PDF document dynamically generated based on ID. I use for this NReco.PdfGenerator.LT. When I running a project directly from VS2017 everything works fine and the file is downloaded. But if I publish a project on an IIS server and then try clicking on the button, will open a page that does not exist (HTTP ERROR 404).
Button:
<a asp-controller="Dokumenty" asp-action="PobierzPotwierdzenieDokPdf" asp-route-DokID="#item.Dok_DokID" class="btn btn-warning btn-sm"><i class="glyphicon glyphicon-print" title="Drukuj PDF"></i></a>
Controller:
public async Task<FileResult> PobierzPotwierdzenieDokPdf(int DokID)
{
var dokument = _context.Dokumenty.FirstOrDefault(i => i.Dok_DokID == DokID);
var notatki = _context.DokumentyNotatki.Where(d => d.DokNot_DokID == DokID);
viewDokumentPotwierdzeniePdf viewDokumentPotwierdzeniePdf = new viewDokumentPotwierdzeniePdf()
{
Dokument = dokument,
DokumentNotatka = notatki
};
var htmlContent = await _viewRenderService.RenderToStringAsync("Dokumenty/DokumentPotwierdzeniePdf", viewDokumentPotwierdzeniePdf);
var htmlToPdf = new HtmlToPdfConverter
{
PageHeight = 210,
PageWidth = 148,
Margins = new PageMargins() { Bottom = 5, Left = 5, Right = 5, Top = 5 },
Orientation = PageOrientation.Landscape,
PageFooterHtml = "<div style='font-family: Verdana, Geneva, Tahoma, sans-serif; font-size: 10px; text-align: center; color: grey;'>Strona <span class='page'></span> z <span class='topage'></span> | Operator drukujÄ…cy: " + HttpContext.Session.GetString("Ope_Nazwisko") + " | Data wydruku: " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + " | <b>System ERP Polimer</b></div>"
};
htmlToPdf.License.SetLicenseKey("PDF_Generator_Bin_Examples_Pack_0000000000", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
htmlToPdf.PdfToolPath = #"C:\Program Files\wkhtmltopdf\bin\";
byte[] pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
FileResult fileResult = new FileContentResult(pdfBytes, "application/pdf")
{
FileDownloadName = dokument.Dok_NrKancelaryjny.Replace("/", "_") + ".pdf"
};
dokument.Dok_Wydruk = 1;
_context.Entry(dokument).State = EntityState.Modified;
await _context.SaveChangesAsync();
return fileResult;
}
IIS is trying to open the url http://domainname.int/Dokumenty/PobierzPotwierdzenieDokPdf?DokID=77 where the number at the end is the ID. But that page does not physically exist.
Please help. What am I doing wrong?
P.S. sorry for my English :)

How to Display Show Attachment in Info Window

I am using below code to display identifier popup.if I click on particular point it will display all the information about that point in info window(popup).but even if I specify show attachments true it will not display the attachments.In Map server I have an image for points.so I need to display info window as well as the image.
map.on("load", mapReady);
var parcelsURL = "MY MAP SERVER";
//map.addLayer(new ArcGISDynamicMapServiceLayer(parcelsURL,
// { opacity: 20 }));
function mapReady() {
map.on("click", executeIdentifyTask);
//create identify tasks and setup parameters
identifyTask = new IdentifyTask(parcelsURL);
identifyParams = new IdentifyParameters();
identifyParams.tolerance = 3;
identifyParams.returnGeometry = true;
identifyParams.layerIds = [0];
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;
identifyParams.width = map.width;
identifyParams.height = map.height;
}
function executeIdentifyTask(event) {
identifyParams.geometry = event.mapPoint;
identifyParams.mapExtent = map.extent;
var deferred = identifyTask
.execute(identifyParams)
.addCallback(function (response) {
// response is an array of identify result objects
// Let's return an array of features.
return arrayUtils.map(response, function (result) {
var feature = result.feature;
var layerName = result.layerName;
feature.attributes.layerName = layerName;
if (layerName === 'GridPoint') {
var popupTemplate = new PopupTemplate({
title: "",
fieldInfos: [
{
fieldName: "XX",
visible: true,
label: "XX"
},
{
fieldName: "YY",
visible: true,
label: "YY"
}
],
showAttachments: true
});
//var taxParcelTemplate = new InfoTemplate("",
// "XX: ${XX} <br/> YY: ${YY} <br/> Sample Point Number: ${Sample Point Number} <br/> Point Collected: ${Point Collected} <br/> Major Rabi Crops: ${ Major Rabi Crops} <br/> Major Summer Crop: ${Major Summer Crop} <br/> Soil Type: ${Soil Type} <br/> Major Kharif Crops: ${Major Kharif Crops}");
feature.setInfoTemplate(popupTemplate);
}
//else if (layerName === 'Grid') {
// console.log(feature.attributes.objectid);
// var buildingFootprintTemplate = new InfoTemplate("",
// "OBJECTID: ${OBJECTID}");
// feature.setInfoTemplate(buildingFootprintTemplate);
//}
return feature;
});
});
map.infoWindow.setFeatures([deferred]);
map.infoWindow.show(event.mapPoint);
}
});
someone please help me to display attachments(image) in info window.

How best to traverse API information with iOS

Is there any easier way of traversing array/dictionaries without creating a lot of separate NSArrays/NSDictionaries? I know you can traverse nested dictionaries with dot notation and value at keypath, but what about when arrays are involved?
For example:
At the moment if I want to get at the object at feed.entry.link[4].href in the API result below, I have to define an array at keypath "feed.entry", then assign its first entry as a dictionary, then define an array at keypath "link" and access its fourth entry as a dictionary, and then access its value at "href".
Is this normal?
received {
encoding = "UTF-8";
feed = {
entry = (
{
author = (
{
name = {
"$t" = swdestiny;
};
uri = {
"$t" = "https://gdata.youtube.com/feeds/api/users/swdestiny";
};
}
);
category = (
{
scheme = "http://schemas.google.com/g/2005#kind";
term = "http://gdata.youtube.com/schemas/2007#video";
},
{
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
term = Entertainment;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Star;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Wars;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Episode;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = 3;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Revenge;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = of;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = the;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Sith;
}
);
content = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = text;
};
"gd$comments" = {
"gd$feedLink" = {
countHint = 1567;
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/comments";
rel = "http://gdata.youtube.com/schemas/2007#comments";
};
};
"gd$rating" = {
average = "4.7729683";
max = 5;
min = 1;
numRaters = 1132;
rel = "http://schemas.google.com/g/2005#overall";
};
id = {
"$t" = "http://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
};
link = (
{
href = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata";
rel = alternate;
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/responses";
rel = "http://gdata.youtube.com/schemas/2007#video.responses";
type = "application/atom+xml";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/related";
rel = "http://gdata.youtube.com/schemas/2007#video.related";
type = "application/atom+xml";
},
{
href = "https://m.youtube.com/details?v=9kdEsZH5ohc";
rel = "http://gdata.youtube.com/schemas/2007#mobile";
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
rel = self;
type = "application/atom+xml";
}
);
"media$group" = {
"media$category" = (
{
"$t" = Entertainment;
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
}
);
"media$content" = (
{
duration = 151;
expression = full;
isDefault = true;
medium = video;
type = "application/x-shockwave-flash";
url = "https://www.youtube.com/v/9kdEsZH5ohc?version=3&f=videos&app=youtube_gdata";
"yt$format" = 5;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache4.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 1;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache5.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 6;
}
);
"media$description" = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = plain;
};
"media$keywords" = {
"$t" = "Star, Wars, Episode, 3, Revenge, of, the, Sith";
};
"media$player" = (
{
url = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata_player";
}
);
"media$thumbnail" = (
{
height = 360;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/0.jpg";
width = 480;
},
{
height = 90;
time = "00:00:37.750";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/1.jpg";
width = 120;
},
{
height = 90;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/2.jpg";
width = 120;
},
{
height = 90;
time = "00:01:53.250";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/3.jpg";
width = 120;
}
);
"media$title" = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = plain;
};
"yt$duration" = {
seconds = 151;
};
};
published = {
"$t" = "2007-05-23T03:31:54.000Z";
};
title = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = text;
};
updated = {
"$t" = "2012-02-20T17:14:37.000Z";
};
"yt$statistics" = {
favoriteCount = 763;
viewCount = 796719;
};
}
);
xmlns = "http://www.w3.org/2005/Atom";
"xmlns$gd" = "http://schemas.google.com/g/2005";
"xmlns$media" = "http://search.yahoo.com/mrss/";
"xmlns$yt" = "http://gdata.youtube.com/schemas/2007";
};
version = "1.0";
}