diff options
-rw-r--r-- | data/style.css | 42 | ||||
-rw-r--r-- | lib/VNDB/Handler/Producers.pm | 165 | ||||
-rw-r--r-- | lib/VNWeb/Producers/Page.pm | 174 | ||||
-rw-r--r-- | lib/VNWeb/Releases/Lib.pm | 68 | ||||
-rw-r--r-- | lib/VNWeb/VN/Page.pm | 59 |
5 files changed, 265 insertions, 243 deletions
diff --git a/data/style.css b/data/style.css index dd4f8726..60b1455b 100644 --- a/data/style.css +++ b/data/style.css @@ -413,6 +413,18 @@ div.postsearch td.tc2 { width: 65px; } div.postsearch td.tc3 { width: 90px; } +/***** Release listings on VN & producer pages */ + +.releases { width: 100%; } +.releases tr.lang td, +.releases tr.vn td { background: $boxbg$; font-weight: bold; } +.releases td.tc1 { padding-left: 30px; width: 80px; white-space: nowrap } +.releases td.tc2 { text-align: center; width: 50px; white-space: nowrap } +.releases td.tc3 { text-align: right; padding: 0; width: 120px; } +.releases td.tc_icons { padding: 0 4px } +.releases td.tc_prod { color: $grayedout$; white-space: nowrap; width: 50px } +.releases td.tc5 { width: 70px; text-align: right } +.releases td.tc6 { text-align: right; width: 25px; padding: 0; white-space: nowrap } /***** VN page *******/ @@ -471,16 +483,8 @@ div#vntags { margin: 0 30px 0 30px; border-top: 1px solid $bo /* end of tag filter machinery */ -.releases table, #screenshots table { width: 100%; } -.releases tr.lang td, #screenshots tr.rel td { background: $boxbg$; font-weight: bold; } -.releases td.tc1 { padding-left: 30px; width: 80px; white-space: nowrap } -.releases td.tc2 { text-align: center; width: 50px; white-space: nowrap } -.releases td.tc3 { text-align: right; padding: 0; width: 90px; } -.releases td.tc_icons { padding: 0 4px } -.releases td.tc5 { width: 70px; text-align: right } -.releases td.tc6 { text-align: right; width: 25px; padding: 0; white-space: nowrap } #screenshots p.rel { background: $boxbg$; @@ -581,22 +585,14 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: -/***** Producer page/list *******/ +/***** Producer page *******/ + +.prodvns { list-style-type: none } +.prodvns li span:first-child { display: inline-block; width: 80px; text-align: right; padding-right: 15px } +.prodvns li span:last-child { color: $grayedout$; padding-left: 15px } + -#prodrel { width: 100%; } -#prodrel tr.vn td { background: $boxbg$; font-weight: bold; } -#prodrel tr.vn i, -#prodrel tr.vn span { display: none } -#prodrel.collapse tr.vn td { padding: 1px; background: none; font-weight: normal } -#prodrel.collapse tr.vn i { font-style: normal; display: block; float: left; width: 80px; padding: 0 0 0 40px; } -#prodrel.collapse tr.vn span { display: inline; font-weight: normal; color: $grayedout$; padding: 0 0 0 5px } -#prodrel.collapse tr.rel { display: none } -#prodrel td.tc1 { width: 80px; padding-left: 30px; white-space: nowrap } -#prodrel td.tc2 { width: 50px; text-align: center; white-space: nowrap } -#prodrel td.tc3 { width: 120px; text-align: right; padding: 0; } -#prodrel td.tc5 { width: 120px; color: $grayedout$; } -#prodrel td.tc6 { width: 25px; text-align: right; padding: 0; white-space: nowrap } -#expandprodrel { float: right; font-weight: bold; padding-bottom: 2px; border: none } +/***** Producer list ******/ div.producerbrowse { padding-bottom: 10px } .producerbrowse ul { float: left; margin-top: -5px; margin-left: 3%; width: 28%; } diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 4457c9b6..d8b2cea1 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -3,14 +3,12 @@ package VNDB::Handler::Producers; use strict; use warnings; -use TUWF ':html', ':xml', 'xml_escape', 'html_escape'; +use TUWF ':html', ':xml'; use VNDB::Func; use VNDB::Types; -use VNDB::ExtLinks; TUWF::register( - qr{p([1-9]\d*)(?:\.([1-9]\d*))?} => \&page, qr{p/add} => \&addform, qr{p(?:([1-9]\d*)(?:\.([1-9]\d*))?/edit|/new)} => \&edit, @@ -19,167 +17,6 @@ TUWF::register( ); -sub page { - my($self, $pid, $rev) = @_; - - my $method = $rev ? 'dbProducerGetRev' : 'dbProducerGet'; - my $p = $self->$method( - id => $pid, - what => 'extended relations', - $rev ? ( rev => $rev ) : () - )->[0]; - return $self->resNotFound if !$p->{id}; - enrich_extlinks p => $p; - - my $metadata = { - 'og:title' => $p->{name}, - 'og:description' => bb2text $p->{desc}, - }; - - $self->htmlHeader(title => $p->{name}, noindex => $rev, metadata => $metadata); - $self->htmlMainTabs(p => $p); - return if $self->htmlHiddenMessage('p', $p); - - if($rev) { - my $prev = $rev && $rev > 1 && $self->dbProducerGetRev(id => $pid, rev => $rev-1, what => 'extended relations')->[0]; - $self->htmlRevision('p', $prev, $p, - [ type => 'Type', serialize => sub { $PRODUCER_TYPE{$_[0]} } ], - [ name => 'Name (romaji)', diff => 1 ], - [ original => 'Original name', diff => 1 ], - [ alias => 'Aliases', diff => qr/[ ,\n\.]/ ], - [ lang => 'Language', serialize => sub { "$_[0] ($LANGUAGE{$_[0]})" } ], - [ website => 'Website', diff => 1 ], - [ l_wp => 'Wikipedia link',htmlize => sub { - $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : '[empty]' - }], - [ l_wikidata=> 'Wikidata ID', htmlize => sub { $_[0] ? sprintf '<a href="https://www.wikidata.org/wiki/Q%d">Q%1$d</a>', $_[0] : '[empty]' } ], - [ desc => 'Description', diff => qr/[ ,\n\.]/ ], - [ relations => 'Relations', join => '<br />', split => sub { - my @r = map sprintf('%s: <a href="/p%d" title="%s">%s</a>', - $PRODUCER_RELATION{$_->{relation}}{txt}, $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape shorten $_->{name}, 40 - ), sort { $a->{id} <=> $b->{id} } @{$_[0]}; - return @r ? @r : ('[empty]'); - }], - ); - } - - div class => 'mainbox'; - $self->htmlItemMessage('p', $p); - h1 $p->{name}; - h2 class => 'alttitle', lang => $p->{lang}, $p->{original} if $p->{original}; - p class => 'center'; - txt $PRODUCER_TYPE{$p->{type}}; - br; - txt "Primary language: $LANGUAGE{$p->{lang}}"; - if($p->{alias}) { - (my $alias = $p->{alias}) =~ s/\n/, /g; - br; - txt "a.k.a. $alias"; - } - - br if $p->{extlinks}->@*; - for($p->{extlinks}->@*) { - a href => $_->[1], $_->[0]; - txt ' - ' if $_ ne $p->{extlinks}[$#{$p->{extlinks}}]; - } - end 'p'; - - if(@{$p->{relations}}) { - my %rel; - push @{$rel{$_->{relation}}}, $_ - for (sort { $a->{name} cmp $b->{name} } @{$p->{relations}}); - p class => 'center'; - br; - for my $r (keys %PRODUCER_RELATION) { - next if !$rel{$r}; - txt $PRODUCER_RELATION{$r}{txt}.': '; - for (@{$rel{$r}}) { - a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 40; - txt ', ' if $_ ne $rel{$r}[$#{$rel{$r}}]; - } - br; - } - end 'p'; - } - - if($p->{desc}) { - p class => 'description'; - lit bb2html $p->{desc}; - end; - } - end 'div'; - - _releases($self, $p); - - $self->htmlFooter; -} - -sub _releases { - my($self, $p) = @_; - - # prodpage_(dev|pub) - my $r = $self->dbReleaseGet(pid => $p->{id}, results => 999, what => 'vn platforms links'); - enrich_extlinks r => $r; - - div class => 'mainbox'; - a href => '#', id => 'expandprodrel', 'collapse'; - h1 'Releases'; - if(!@$r) { - p 'We have currently no visual novels by this producer.'; - end; - return; - } - - my %vn; # key = vid, value = [ $r1, $r2, $r3, .. ] - my @vn; # $vn objects in order of first release - for my $rel (@$r) { - for my $v (@{$rel->{vn}}) { - push @vn, $v if !$vn{$v->{vid}}; - push @{$vn{$v->{vid}}}, $rel; - } - } - - table id => 'prodrel'; - for my $v (@vn) { - Tr class => 'vn'; - td colspan => 6; - i; lit fmtdatestr $vn{$v->{vid}}[0]{released}; end; - a href => "/v$v->{vid}", title => $v->{original}, $v->{title}; - span '('.join(', ', - (grep($_->{developer}, @{$vn{$v->{vid}}}) ? 'developer' : ()), - (grep($_->{publisher}, @{$vn{$v->{vid}}}) ? 'publisher' : ()) - ).')'; - end; - end; - for my $rel (@{$vn{$v->{vid}}}) { - Tr class => 'rel'; - td class => 'tc1'; lit fmtdatestr $rel->{released}; end; - td class => 'tc2', $rel->{minage} < 0 ? '' : minage $rel->{minage}; - td class => 'tc3'; - for (sort @{$rel->{platforms}}) { - next if $_ eq 'oth'; - cssicon $_, $PLATFORM{$_}; - } - cssicon "lang $_", $LANGUAGE{$_} for (@{$rel->{languages}}); - cssicon "rt$rel->{type}", $rel->{type}; - end; - td class => 'tc4'; - a href => "/r$rel->{id}", title => $rel->{original}||$rel->{title}, $rel->{title}; - b class => 'grayedout', ' (patch)' if $rel->{patch}; - end; - td class => 'tc5', join ', ', - ($rel->{developer} ? 'developer' : ()), ($rel->{publisher} ? 'publisher' : ()); - td class => 'tc6'; - VNWeb::Releases::Lib::release_extlinks_($rel); - end; - end 'tr'; - } - } - end 'table'; - end 'div'; -} - - sub addform { my $self = shift; return $self->htmlDenied if !$self->authCan('edit'); diff --git a/lib/VNWeb/Producers/Page.pm b/lib/VNWeb/Producers/Page.pm new file mode 100644 index 00000000..2ccf3849 --- /dev/null +++ b/lib/VNWeb/Producers/Page.pm @@ -0,0 +1,174 @@ +package VNWeb::Producers::Page; + +use VNWeb::Prelude; +use VNWeb::Releases::Lib; + + +sub enrich_item { + my($p) = @_; + enrich_extlinks p => $p; + enrich_merge pid => 'SELECT id AS pid, name, original FROM producers WHERE id IN', $p->{relations}; + $p->{relations} = [ sort { $a->{name} cmp $b->{name} || $a->{pid} <=> $b->{pid} } $p->{relations}->@* ]; +} + + +sub rev_ { + my($p) = @_; + revision_ p => $p, \&enrich_item, + [ name => 'Name' ], + [ original => 'Original name' ], + [ alias => 'Aliases' ], + [ desc => 'Description' ], + [ type => 'Type', fmt => \%PRODUCER_TYPE ], + [ lang => 'Language', fmt => \%LANGUAGE ], + [ relations => 'Relations', fmt => sub { + txt_ $PRODUCER_RELATION{$_->{relation}}{txt}.': '; + a_ href => "/p$_->{pid}", title => $_->{original}||$_->{name}, $_->{name}; + } ], + revision_extlinks 'p' +} + + +sub info_ { + my($p) = @_; + h1_ $p->{name}; + h2_ class => 'alttitle', lang => $p->{lang}, $p->{original} if length $p->{original}; + + p_ class => 'center', sub { + txt_ $PRODUCER_TYPE{$p->{type}}; + br_; + txt_ "Primary language: $LANGUAGE{$p->{lang}}"; + if(length $p->{alias}) { + br_; + txt_ 'a.k.a. '; + txt_ $p->{alias} =~ s/\n/, /gr; + } + br_ if $p->{extlinks}->@*; + join_ ' - ', sub { a_ href => $_->[1], $_->[0] }, $p->{extlinks}->@*; + }; + + p_ class => 'center', sub { + my %rel; + push $rel{$_->{relation}}->@*, $_ for $p->{relations}->@*; + br_; + join_ \&br_, sub { + txt_ $PRODUCER_RELATION{$_}{txt}.': '; + join_ ', ', sub { + a_ href => "/p$_->{pid}", title => $_->{original}||$_->{name}, $_->{name}; + }, $rel{$_}->@*; + }, grep $rel{$_}, keys %PRODUCER_RELATION; + } if $p->{relations}->@*; + + p_ class => 'description', sub { lit_ bb2html $p->{desc} } if length $p->{desc}; +} + + +sub rel_ { + my($p) = @_; + + my $r = tuwf->dbAlli(' + SELECT r.id, r.type, r.patch, r.released, r.gtin, rp.publisher, rp.developer, ', sql_extlinks(r => 'r.'), ' + FROM releases r + JOIN releases_producers rp ON rp.id = r.id + WHERE rp.pid =', \$p->{id}, ' AND NOT r.hidden + ORDER BY r.released, r.id + '); + enrich_extlinks r => $r; + enrich_release $r; + enrich vn => id => rid => sub { sql ' + SELECT rv.id as rid, v.id, v.title, v.original + FROM vn v + JOIN releases_vn rv ON rv.vid = v.id + WHERE NOT v.hidden AND rv.id IN', $_, ' + ORDER BY v.title + '}, $r; + + my(%vn, @vn); + for my $rel (@$r) { + for ($rel->{vn}->@*) { + push @vn, $_ if !$vn{$_->{id}}; + push $vn{$_->{id}}->@*, $rel; + } + } + + h1_ 'Releases'; + debug_ $r; + table_ class => 'releases', sub { + for my $v (@vn) { + tr_ class => 'vn', sub { + # TODO: VN list status & management + td_ colspan => 8, sub { + a_ href => "/v$v->{id}", title => $v->{original}||$v->{title}, $v->{title}; + }; + release_row_ $_, $v->{id}, 1 for $vn{$v->{id}}->@*; + }; + } + } if @$r; + p_ 'This producer has no releases in the database.' if !@$r; +} + + +sub vns_ { + my($p) = @_; + my $v = tuwf->dbAlli(q{ + SELECT v.id, v.title, v.original, rels.developer, rels.publisher, rels.released + FROM vn v + JOIN ( + SELECT rv.vid, bool_or(rp.developer), bool_or(rp.publisher) + , COALESCE(MIN(r.released) FILTER(WHERE r.type <> 'trial'), MIN(r.released)) + FROM releases_vn rv + JOIN releases r ON r.id = rv.id + JOIN releases_producers rp ON rp.id = rv.id + WHERE NOT r.hidden AND rp.pid =}, \$p->{id}, ' + GROUP BY rv.vid + ) rels(vid, developer, publisher, released) ON rels.vid = v.id + WHERE NOT v.hidden + ORDER BY rels.released + '); + + h1_ 'Visual Novels'; + debug_ $v; + # TODO: Perhaps something more table-like, also showing languages, platforms & VN list status + ul_ class => 'prodvns', sub { + li_ sub { + span_ sub { rdate_ $_->{released} }; + a_ href => "/v$_->{id}", title => $_->{original}||$_->{title}, $_->{title}; + span_ join ' & ', + $_->{publisher} ? 'Publisher' : (), + $_->{developer} ? 'Developer' : (); + } for @$v; + }; + p_ 'This producer has no releases in the database.' if !@$v; +} + + +TUWF::get qr{/$RE{prev}(?:/(?<tab>vn|rel))?}, sub { + my $p = db_entry p => tuwf->capture('id'), tuwf->capture('rev'); + return tuwf->resNotFound if !$p; + enrich_item $p; + + my $pref = tuwf->reqCookie('prodrelexpand') ? 'vn' : 'rel'; + my $tab = tuwf->capture('tab') || $pref; + tuwf->resCookie(prodrelexpand => $tab eq 'vn' ? 1 : undef) if $tab && $tab ne $pref; + $tab = 'rel' if !$tab; + + framework_ title => $p->{name}, index => !tuwf->capture('rev'), type => 'p', dbobj => $p, hiddenmsg => 1, + og => { + title => $p->{name}, + description => bb2text($p->{desc}), + }, + sub { + rev_ $p if tuwf->capture('rev'); + div_ class => 'mainbox', sub { info_ $p }; + div_ class => 'maintabs right', sub { + ul_ sub { + li_ mkclass(tabselected => $tab eq 'vn'), sub { a_ href => "/p$p->{id}/vn", 'Visual Novels' }; + li_ mkclass(tabselected => $tab eq 'rel'), sub { a_ href => "/p$p->{id}/rel", 'Releases' }; + }; + }; + div_ class => 'mainbox', sub { rel_ $p } if $tab eq 'rel'; + div_ class => 'mainbox', sub { vns_ $p } if $tab eq 'vn'; + } +}; + +1; diff --git a/lib/VNWeb/Releases/Lib.pm b/lib/VNWeb/Releases/Lib.pm index 29042c56..de25258a 100644 --- a/lib/VNWeb/Releases/Lib.pm +++ b/lib/VNWeb/Releases/Lib.pm @@ -3,10 +3,21 @@ package VNWeb::Releases::Lib; use VNWeb::Prelude; use Exporter 'import'; -our @EXPORT = qw/release_extlinks_/; +our @EXPORT = qw/enrich_release release_row_/; + + +# Enrich a list of releases so that it's suitable for release_row_(). +# Assumption: Each release already has id, type, patch, released, gtin and enrich_extlinks(). +sub enrich_release { + my($r) = @_; + enrich_merge id => 'SELECT id, title, original, notes, minage, freeware, doujin, resolution, voiced, ani_story, ani_ero, uncensored FROM releases WHERE id IN', $r; + enrich_merge id => sql('SELECT rid as id, status as rlist_status FROM rlists WHERE uid =', \auth->uid, 'AND rid IN'), $r if auth; + enrich_flatten lang => id => id => sub { sql 'SELECT id, lang FROM releases_lang WHERE id IN', $_, 'ORDER BY id, lang' }, $r; + enrich_flatten platforms => id => id => sub { sql 'SELECT id, platform FROM releases_platforms WHERE id IN', $_, 'ORDER BY id, platform' }, $r; + enrich media => id => id => sub { 'SELECT id, medium, qty FROM releases_media WHERE id IN', $_, 'ORDER BY id, medium' }, $r; +} -# Generate the html for an 'external links' dropdown, assumes enrich_extlinks() has already been called on this object. sub release_extlinks_ { my($r, $id) = @_; return if !$r->{extlinks}->@*; @@ -38,4 +49,57 @@ sub release_extlinks_ { } } + +sub release_row_ { + my($r, $id, $prodpage) = @_; + + my sub icon_ { + my($img, $label, $class) = @_; + $class = $class ? " release_icon_$class" : ''; + img_ src => config->{url_static}."/f/$img.svg", class => "release_icons$class", title => $label; + } + + my sub icons_ { + my($r) = @_; + icon_ 'voiced', $VOICED{$r->{voiced}}{txt}, "voiced$r->{voiced}" if $r->{voiced}; + icon_ 'story_animated', "Story: $ANIMATED{$r->{ani_story}}{txt}", "anim$r->{ani_story}" if $r->{ani_story}; + icon_ 'ero_animated', "Ero: $ANIMATED{$r->{ani_ero}}{txt}", "anim$r->{ani_ero}" if $r->{ani_ero}; + icon_ 'free', 'Freeware' if $r->{freeware}; + icon_ 'nonfree', 'Non-free' if !$r->{freeware}; + icon_ 'doujin', 'Doujin' if !$r->{patch} && $r->{doujin}; + icon_ 'commercial', 'Commercial' if !$r->{patch} && !$r->{doujin}; + if($r->{resolution} ne 'unknown') { + my $type = $r->{resolution} eq 'nonstandard' ? 'custom' : $RESOLUTION{$r->{resolution}}{cat} eq 'widescreen' ? '16-9' : '4-3'; + # Ugly workaround: PC-98 has non-square pixels, thus not widescreen + $type = '4-3' if $type eq '16-9' && grep $_ eq 'p98', $r->{platforms}->@*; + icon_ "resolution_$type", $RESOLUTION{$r->{resolution}}{txt}; + } + icon_ $MEDIUM{ $r->{media}[0]{medium} }{icon}, join ', ', map fmtmedia($_->{medium}, $_->{qty}), $r->{media}->@* if $r->{media}->@*; + icon_ 'uncensor', 'Uncensored' if $r->{uncensored}; + icon_ 'notes', bb2text $r->{notes} if $r->{notes}; + } + + tr_ sub { + td_ class => 'tc1', sub { rdate_ $r->{released} }; + td_ class => 'tc2', $r->{minage} < 0 ? '' : minage $r->{minage}; + td_ class => 'tc3', sub { + abbr_ class => "icons $_", title => $PLATFORM{$_}, '' for grep $_ ne 'oth', $r->{platforms}->@*; + if($prodpage) { + abbr_ class => "icons lang $_", title => $LANGUAGE{$_}, '' for $r->{lang}->@*; + } + abbr_ class => "icons rt$r->{type}", title => $r->{type}, ''; + }; + td_ class => 'tc4', sub { + a_ href => "/r$r->{id}", title => $r->{original}||$r->{title}, $r->{title}; + b_ class => 'grayedout', ' (patch)' if $r->{patch}; + }; + td_ class => 'tc_icons', sub { icons_ $r }; + td_ class => 'tc_prod', join ' & ', $r->{publisher} ? 'Pub' : (), $r->{developer} ? 'Dev' : () if $prodpage; + td_ class => 'tc5 elm_dd_left', sub { + elm_ 'UList.ReleaseEdit', $VNWeb::User::Lists::RLIST_STATUS, { rid => $r->{id}, uid => auth->uid, status => $r->{rlist_status}, empty => '--' } if auth; + }; + td_ class => 'tc6', sub { release_extlinks_ $r, "${id}_$r->{id}" }; + } +} + 1; diff --git a/lib/VNWeb/VN/Page.pm b/lib/VNWeb/VN/Page.pm index ba2160c1..8a116391 100644 --- a/lib/VNWeb/VN/Page.pm +++ b/lib/VNWeb/VN/Page.pm @@ -1,7 +1,7 @@ package VNWeb::VN::Page; use VNWeb::Prelude; -use VNWeb::Releases::Lib 'release_extlinks_'; +use VNWeb::Releases::Lib; use VNDB::Func 'fmtrating'; use POSIX 'strftime'; @@ -425,44 +425,11 @@ sub releases_ { # TODO: Organize a long list of releases a bit better somehow? Collapsable language sections? - enrich_merge id => ' - SELECT id, title, original, notes, minage, freeware, doujin, resolution, voiced, ani_story, ani_ero, uncensored - FROM releases WHERE id IN', $v->{releases}; - enrich_merge id => sql('SELECT rid as id, status as rlist_status FROM rlists WHERE uid =', \auth->uid, 'AND rid IN'), $v->{releases} if auth; - enrich_flatten lang => id => id => 'SELECT id, lang FROM releases_lang WHERE id IN', $v->{releases}; - enrich_flatten platforms => id => id => 'SELECT id, platform FROM releases_platforms WHERE id IN', $v->{releases}; - enrich media => id => id => 'SELECT id, medium, qty FROM releases_media WHERE id IN', $v->{releases}; - + enrich_release $v->{releases}; $v->{releases} = [ sort { $a->{released} <=> $b->{released} || $a->{id} <=> $b->{id} } $v->{releases}->@* ]; my %lang; my @lang = grep !$lang{$_}++, map $_->{lang}->@*, $v->{releases}->@*; - my sub icon_ { - my($img, $label, $class) = @_; - $class = $class ? " release_icon_$class" : ''; - img_ src => config->{url_static}."/f/$img.svg", class => "release_icons$class", title => $label; - } - - my sub icons_ { - my($r) = @_; - icon_ 'voiced', $VOICED{$r->{voiced}}{txt}, "voiced$r->{voiced}" if $r->{voiced}; - icon_ 'story_animated', "Story: $ANIMATED{$r->{ani_story}}{txt}", "anim$r->{ani_story}" if $r->{ani_story}; - icon_ 'ero_animated', "Ero: $ANIMATED{$r->{ani_ero}}{txt}", "anim$r->{ani_ero}" if $r->{ani_ero}; - icon_ 'free', 'Freeware' if $r->{freeware}; - icon_ 'nonfree', 'Non-free' if !$r->{freeware}; - icon_ 'doujin', 'Doujin' if !$r->{patch} && $r->{doujin}; - icon_ 'commercial', 'Commercial' if !$r->{patch} && !$r->{doujin}; - if($r->{resolution} ne 'unknown') { - my $type = $r->{resolution} eq 'nonstandard' ? 'custom' : $RESOLUTION{$r->{resolution}}{cat} eq 'widescreen' ? '16-9' : '4-3'; - # Ugly workaround: PC-98 has non-square pixels, thus not widescreen - $type = '4-3' if $type eq '16-9' && grep $_ eq 'p98', $r->{platforms}->@*; - icon_ "resolution_$type", $RESOLUTION{$r->{resolution}}{txt}; - } - icon_ $MEDIUM{ $r->{media}[0]{medium} }{icon}, join ', ', map fmtmedia($_->{medium}, $_->{qty}), $r->{media}->@* if $r->{media}->@*; - icon_ 'uncensor', 'Uncensored' if $r->{uncensored}; - icon_ 'notes', bb2text $r->{notes} if $r->{notes}; - } - my sub lang_ { my($lang) = @_; tr_ class => 'lang', sub { @@ -471,31 +438,15 @@ sub releases_ { txt_ $LANGUAGE{$lang}; } }; - tr_ sub { - td_ class => 'tc1', sub { rdate_ $_->{released} }; - td_ class => 'tc2', $_->{minage} < 0 ? '' : minage $_->{minage}; - td_ class => 'tc3', sub { - abbr_ class => "icons $_", title => $PLATFORM{$_}, '' for grep $_ ne 'oth', $_->{platforms}->@*; - abbr_ class => "icons rt$_->{type}", title => $_->{type}, ''; - }; - td_ class => 'tc4', sub { - a_ href => "/r$_->{id}", title => $_->{original}||$_->{title}, $_->{title}; - b_ class => 'grayedout', ' (patch)' if $_->{patch}; - }; - td_ class => 'tc_icons', sub { icons_ $_ }; - td_ class => 'tc5 elm_dd_left', sub { - elm_ 'UList.ReleaseEdit', $VNWeb::User::Lists::RLIST_STATUS, { rid => $_->{id}, uid => auth->uid, status => $_->{rlist_status}, empty => '--' } if auth; - }; - td_ class => 'tc6', sub { release_extlinks_ $_, "$lang$_->{id}" }; - } for grep grep($_ eq $lang, $_->{lang}->@*), $v->{releases}->@*; + release_row_ $_, $lang for grep grep($_ eq $lang, $_->{lang}->@*), $v->{releases}->@*; } - div_ class => 'mainbox releases', sub { + div_ class => 'mainbox', sub { h1_ 'Releases'; if(!$v->{releases}->@*) { p_ 'We don\'t have any information about releases of this visual novel yet...'; } else { - table_ sub { lang_ $_ for @lang }; + table_ class => 'releases', sub { lang_ $_ for @lang }; } } } |