Merge remote-tracking branch 'origin/develop'
timw4mail/HummingBirdAnimeClient/pipeline/head This commit looks good Details

This commit is contained in:
Timothy Warren 2021-10-13 17:05:26 -04:00
commit 629f7f1045
19 changed files with 160 additions and 50 deletions

View File

@ -17,6 +17,13 @@ use function Aviat\AnimeClient\getLocalImg;
<td><?= $data['status'] ?></td>
</tr>
<?php if ( ! empty($data['airDate'])): ?>
<tr>
<td>Original Airing</td>
<td><?= $data['airDate'] ?></td>
</tr>
<?php endif ?>
<tr>
<td>Show Type</td>
<td><?= (strlen($data['show_type']) > 3) ? ucfirst(strtolower($data['show_type'])) : $data['show_type'] ?></td>
@ -122,8 +129,8 @@ use function Aviat\AnimeClient\getLocalImg;
&nbsp;&nbsp;<?= $link['meta']['name'] ?>
<?php endif ?>
</td>
<td><?= implode(', ', $link['subs']) ?></td>
<td><?= implode(', ', $link['dubs']) ?></td>
<td><?= implode(', ', array_map(fn ($sub) => Locale::getDisplayLanguage($sub, 'en'), $link['subs'])) ?></td>
<td><?= implode(', ', array_map(fn ($dub) => Locale::getDisplayLanguage($dub, 'en'), $link['dubs'])) ?></td>
</tr>
<?php endforeach ?>
</tbody>

View File

@ -628,6 +628,14 @@ picture.cover {
background-size: contain;
background-repeat: no-repeat;
}
/* There are two .name elements, just darken them both in this case! */
.media.search.disabled .name {
background-color: #000;
background-color: rgba(0, 0, 0, 0.75);
background-size: cover;
background-size: contain;
background-repeat: no-repeat;
}
.media.search > .row {
z-index: 6;

View File

@ -1,5 +1,5 @@
import _ from './anime-client.js'
import { renderAnimeSearchResults } from './template-helpers.js'
import { renderSearchResults } from './template-helpers.js'
const search = (query) => {
// Show the loader
@ -13,7 +13,7 @@ const search = (query) => {
_.hide('.cssload-loader');
// Show the results
_.$('#series-list')[ 0 ].innerHTML = renderAnimeSearchResults(searchResults);
_.$('#series-list')[ 0 ].innerHTML = renderSearchResults('anime', searchResults);
});
};

View File

@ -1,12 +1,12 @@
import _ from './anime-client.js'
import { renderMangaSearchResults } from './template-helpers.js'
import { renderSearchResults } from './template-helpers.js'
const search = (query) => {
_.show('.cssload-loader');
return _.get(_.url('/manga/search'), { query }, (searchResults, status) => {
searchResults = JSON.parse(searchResults);
_.hide('.cssload-loader');
_.$('#series-list')[ 0 ].innerHTML = renderMangaSearchResults(searchResults);
_.$('#series-list')[ 0 ].innerHTML = renderSearchResults('manga', searchResults);
});
};

View File

@ -7,52 +7,55 @@ _.on('main', 'change', '.big-check', (e) => {
document.getElementById(`mal_${id}`).checked = true;
});
export function renderAnimeSearchResults (data) {
return data.map(item => {
const titles = item.titles.join('<br />');
/**
* On search results with an existing library entry, this shows that fact, with an edit link for the existing
* library entry
*
* @param {'anime'|'manga'} type
* @param {Object} item
* @returns {String}
*/
function renderEditLink (type, item) {
if (item.libraryEntry === null) {
return '';
}
return `
<article class="media search">
<div class="name">
<input type="radio" class="mal-check" id="mal_${item.slug}" name="mal_id" value="${item.mal_id}" />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${item.id}" />
<label for="${item.slug}">
<picture width="220">
<source srcset="/public/images/anime/${item.id}.webp" type="image/webp" />
<source srcset="/public/images/anime/${item.id}.jpg" type="image/jpeg" />
<img src="/public/images/anime/${item.id}.jpg" alt="" width="220" />
</picture>
<span class="name">
${item.canonicalTitle}<br />
<small>${titles}</small>
</span>
</label>
</div>
<div class="table">
<div class="row">
<span class="edit">
<a class="bracketed" href="/anime/details/${item.slug}">Info Page</a>
</span>
</div>
</div>
</article>
`;
}).join('');
return `
<div class="row">
<span class="edit"><big>[ Already in List ]</big></span>
</div>
<div class="row">
<span class="edit">
<a class="bracketed" href="/${type}/edit/${item.libraryEntry.id}/${item.libraryEntry.status}">Edit</a>
</span>
</div>
<div class="row"><span class="edit">&nbsp;</span></div>
`
}
export function renderMangaSearchResults (data) {
/**
* Show the search results for a media item
*
* @param {'anime'|'manga'} type
* @param {Object} data
* @returns {String}
*/
export function renderSearchResults (type, data) {
return data.map(item => {
const titles = item.titles.join('<br />');
const disabled = item.libraryEntry !== null ? 'disabled' : '';
const editLink = renderEditLink(type, item);
return `
<article class="media search">
<article class="media search ${disabled}">
<div class="name">
<input type="radio" id="mal_${item.slug}" name="mal_id" value="${item.mal_id}" />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${item.id}" />
<input type="radio" class="mal-check" id="mal_${item.slug}" name="mal_id" value="${item.mal_id}" ${disabled} />
<input type="radio" class="big-check" id="${item.slug}" name="id" value="${item.id}" ${disabled} />
<label for="${item.slug}">
<picture width="220">
<source srcset="/public/images/manga/${item.id}.webp" type="image/webp" />
<source srcset="/public/images/manga/${item.id}.jpg" type="image/jpeg" />
<img src="/public/images/manga/${item.id}.jpg" alt="" width="220" />
<source srcset="/public/images/${type}/${item.id}.webp" type="image/webp" />
<source srcset="/public/images/${type}/${item.id}.jpg" type="image/jpeg" />
<img src="/public/images/${type}/${item.id}.jpg" alt="" width="220" />
</picture>
<span class="name">
${item.canonicalTitle}<br />
@ -61,9 +64,10 @@ export function renderMangaSearchResults (data) {
</label>
</div>
<div class="table">
${editLink}
<div class="row">
<span class="edit">
<a class="bracketed" href="/manga/details/${item.slug}">Info Page</a>
<a class="bracketed" href="/${type}/details/${item.slug}">Info Page</a>
</span>
</div>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -535,6 +535,7 @@ final class Model {
'slug' => $item['slug'],
'canonicalTitle' => $item['titles']['canonical'],
'titles' => array_values(K::getTitles($item['titles'])),
'libraryEntry' => $item['myLibraryEntry'],
];
// Search for MAL mapping

View File

@ -30,6 +30,12 @@ query ($slug: String!) {
canonical
localized
}
...on Anime {
episodeCount
}
...on Manga {
chapterCount
}
}
updatedAt
}

View File

@ -14,6 +14,10 @@ query ($query: String!) {
localized
alternatives
}
myLibraryEntry {
id
status
}
}
}
}

View File

@ -14,6 +14,10 @@ query ($query: String!) {
localized
alternatives
}
myLibraryEntry {
id
status
}
}
}
}

View File

@ -121,6 +121,7 @@ final class AnimeTransformer extends AbstractTransformer {
}
return AnimePage::from([
'airDate' => Kitsu::formatAirDates($base['startDate'], $base['endDate']),
'age_rating' => $base['ageRating'],
'age_rating_guide' => $base['ageRatingGuide'],
'characters' => $characters,

View File

@ -65,6 +65,7 @@ abstract class HistoryTransformer {
foreach ($base as $entry)
{
// Filter out other media types
if (strtolower($entry['media']['__typename']) !== $this->type)
{
continue;
@ -195,6 +196,19 @@ abstract class HistoryTransformer {
return NULL;
}
// Hide the last episode update (Anime)
foreach (['episodeCount', 'chapterCount'] as $count)
{
if ( ! empty($entry['media'][$count]))
{
$update = $entry['changedData']['progress'][1] ?? 0;
if ($update === $entry['media'][$count])
{
return NULL;
}
}
}
$action = ($this->isReconsuming($entry))
? "{$this->reconsumeAction} {$item}"
: "{$this->progressAction} {$item}";

View File

@ -68,6 +68,57 @@ final class Kitsu {
return AnimeAiringStatus::NOT_YET_AIRED;
}
/**
* Reformat the airing date range for an Anime
*
* @param string|null $startDate
* @param string|null $endDate
* @return string
*/
public static function formatAirDates(string $startDate = NULL, string $endDate = NULL): string
{
if (empty($startDate))
{
return '';
}
$monthMap = [
'01' => 'Jan',
'02' => 'Feb',
'03' => 'Mar',
'04' => 'Apr',
'05' => 'May',
'06' => 'Jun',
'07' => 'Jul',
'08' => 'Aug',
'09' => 'Sep',
'10' => 'Oct',
'11' => 'Nov',
'12' => 'Dec',
];
[$startYear, $startMonth, $startDay] = explode('-', $startDate);
if ($startDate === $endDate)
{
return "{$monthMap[$startMonth]} $startDay, $startYear";
}
if (empty($endDate))
{
return "{$monthMap[$startMonth]} {$startYear} - ";
}
[$endYear, $endMonth] = explode('-', $endDate);
if ($startYear === $endYear)
{
return "{$monthMap[$startMonth]} - {$monthMap[$endMonth]} $startYear";
}
return "{$monthMap[$startMonth]} {$startYear} - {$monthMap[$endMonth]} {$endYear}";
}
public static function getPublishingStatus(string $kitsuStatus, string $startDate = NULL, string $endDate = NULL): string
{
$startPubDate = new DateTimeImmutable($startDate ?? 'tomorrow');
@ -263,8 +314,15 @@ final class Kitsu {
if (array_key_exists('localized', $titles) && is_array($titles['localized']))
{
foreach($titles['localized'] as $alternateTitle)
foreach($titles['localized'] as $locale => $alternateTitle)
{
// Really don't care about languages that aren't english
// or Japanese for titles
if ( ! in_array($locale, ['en', 'en_us', 'en_jp', 'ja_jp']))
{
continue;
}
if (self::titleIsUnique($alternateTitle, $valid))
{
$valid[] = $alternateTitle;

View File

@ -25,4 +25,6 @@ final class AnimePage extends Anime {
public array $links = [];
public array $staff = [];
public ?string $airDate = '';
}

View File

@ -43,6 +43,7 @@ staff:
'Theme Song Lyrics, Inserted Song Performance': [{ id: '17751', name: mpi, image: { original: 'https://media.kitsu.io/people/images/17751/original.jpg?1533270888' }, slug: mpi }]
'Theme Song Lyrics, Theme Song Composition, Theme Song Arrangement': [{ id: '17299', name: Revo, image: { original: 'https://media.kitsu.io/people/images/17299/original.jpg?1533270886' }, slug: revo }]
'Theme Song Performance': [{ id: '18196', name: 'Cinema Staff', image: { original: 'https://media.kitsu.io/people/images/18196/original.jpg?1533273064' }, slug: cinema-staff }, { id: '8718', name: 'Linked Horizon', image: { original: 'https://media.kitsu.io/people/images/8718/original.jpg?1416270072' }, slug: linked-horizon }, { id: '6847', name: 'Yoko Hikasa', image: { original: 'https://media.kitsu.io/people/images/6847/original.jpg?1416268029' }, slug: yoko-hikasa }]
airDate: 'Apr - Sep 2013'
age_rating: R
age_rating_guide: 'Violence, Profanity'
cover_image: 'https://media.kitsu.io/anime/poster_images/7442/small.jpg?1597698856'