summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/style.css42
-rw-r--r--lib/VNDB/Handler/Producers.pm165
-rw-r--r--lib/VNWeb/Producers/Page.pm174
-rw-r--r--lib/VNWeb/Releases/Lib.pm68
-rw-r--r--lib/VNWeb/VN/Page.pm59
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 };
}
}
}