mirror of
https://github.com/openvk/openvk
synced 2024-11-15 03:31:18 +03:00
nsfw cover change & add masonry video support
This commit is contained in:
parent
ad61a89812
commit
873f00788d
12 changed files with 184 additions and 53 deletions
|
@ -1,6 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Entities\Traits;
|
namespace openvk\Web\Models\Entities\Traits;
|
||||||
use openvk\Web\Models\Entities\{Attachable, Photo};
|
use openvk\Web\Models\Entities\{Attachable, Photo, Video};
|
||||||
use openvk\Web\Util\Makima\Makima;
|
use openvk\Web\Util\Makima\Makima;
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ trait TAttachmentHost
|
||||||
if($h < 0)
|
if($h < 0)
|
||||||
$h = $w;
|
$h = $w;
|
||||||
|
|
||||||
$children = $this->getChildren();
|
$children = iterator_to_array($this->getChildren());
|
||||||
$skipped = $photos = $result = [];
|
$skipped = $photos = $result = [];
|
||||||
foreach($children as $child) {
|
foreach($children as $child) {
|
||||||
if($child instanceof Photo) {
|
if($child instanceof Photo || $child instanceof Video && $child->getDimensions()) {
|
||||||
$photos[] = $child;
|
$photos[] = $child;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,23 @@ class Video extends Media
|
||||||
if(sizeof($durations[1]) === 0)
|
if(sizeof($durations[1]) === 0)
|
||||||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
throw new \DomainException("$filename does not contain any meaningful video streams");
|
||||||
|
|
||||||
foreach($durations[1] as $duration)
|
$length = 0;
|
||||||
if(floatval($duration) < 1.0)
|
foreach($durations[1] as $duration) {
|
||||||
|
$duration = floatval($duration);
|
||||||
|
if($duration < 1.0)
|
||||||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
throw new \DomainException("$filename does not contain any meaningful video streams");
|
||||||
|
else
|
||||||
|
$length = max($length, $duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stateChanges("length", (int) round($length, 0, PHP_ROUND_HALF_EVEN));
|
||||||
|
|
||||||
|
preg_match('%width=([0-9\.]++)%', $streams, $width);
|
||||||
|
preg_match('%height=([0-9\.]++)%', $streams, $height);
|
||||||
|
if(!empty($width) && !empty($height)) {
|
||||||
|
$this->stateChanges("width", $width[1]);
|
||||||
|
$this->stateChanges("height", $height[1]);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
|
if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
|
||||||
|
@ -118,6 +132,7 @@ class Video extends Media
|
||||||
function getApiStructure(?User $user = NULL): object
|
function getApiStructure(?User $user = NULL): object
|
||||||
{
|
{
|
||||||
$fromYoutube = $this->getType() == Video::TYPE_EMBED;
|
$fromYoutube = $this->getType() == Video::TYPE_EMBED;
|
||||||
|
$dimensions = $this->getDimensions();
|
||||||
$res = (object)[
|
$res = (object)[
|
||||||
"type" => "video",
|
"type" => "video",
|
||||||
"video" => [
|
"video" => [
|
||||||
|
@ -130,7 +145,7 @@ class Video extends Media
|
||||||
"comments" => $this->getCommentsCount(),
|
"comments" => $this->getCommentsCount(),
|
||||||
"date" => $this->getPublicationTime()->timestamp(),
|
"date" => $this->getPublicationTime()->timestamp(),
|
||||||
"description" => $this->getDescription(),
|
"description" => $this->getDescription(),
|
||||||
"duration" => 0, // я хуй знает как получить длину видео
|
"duration" => $this->getLength(),
|
||||||
"image" => [
|
"image" => [
|
||||||
[
|
[
|
||||||
"url" => $this->getThumbnailURL(),
|
"url" => $this->getThumbnailURL(),
|
||||||
|
@ -139,8 +154,8 @@ class Video extends Media
|
||||||
"with_padding" => 1
|
"with_padding" => 1
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"width" => 640,
|
"width" => $dimensions ? $dimensions[0] : 640,
|
||||||
"height" => 480,
|
"height" => $dimensions ? $dimensions[1] : 480,
|
||||||
"id" => $this->getVirtualId(),
|
"id" => $this->getVirtualId(),
|
||||||
"owner_id" => $this->getOwner()->getId(),
|
"owner_id" => $this->getOwner()->getId(),
|
||||||
"user_id" => $this->getOwner()->getId(),
|
"user_id" => $this->getOwner()->getId(),
|
||||||
|
@ -224,6 +239,74 @@ class Video extends Media
|
||||||
|
|
||||||
return $video;
|
return $video;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fillDimensions()
|
||||||
|
{
|
||||||
|
$hash = $this->getRecord()->hash;
|
||||||
|
$path = $this->pathFromHash($hash);
|
||||||
|
if(!file_exists($path)) {
|
||||||
|
$this->stateChanges("width", 0);
|
||||||
|
$this->stateChanges("height", 0);
|
||||||
|
$this->stateChanges("length", 0);
|
||||||
|
$this->save();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$streams = Shell::ffprobe("-i", $path, "-show_streams", "-select_streams v", "-loglevel error")->execute($error);
|
||||||
|
$durations = [];
|
||||||
|
preg_match_all('%duration=([0-9\.]++)%', $streams, $durations);
|
||||||
|
|
||||||
|
$length = 0;
|
||||||
|
foreach($durations[1] as $duration) {
|
||||||
|
$duration = floatval($duration);
|
||||||
|
if($duration < 1.0)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
$length = max($length, $duration);
|
||||||
|
}
|
||||||
|
$this->stateChanges("length", (int) round($length, 0, PHP_ROUND_HALF_EVEN));
|
||||||
|
|
||||||
|
preg_match('%width=([0-9\.]++)%', $streams, $width);
|
||||||
|
preg_match('%height=([0-9\.]++)%', $streams, $height);
|
||||||
|
|
||||||
|
if(!empty($width) && !empty($height)) {
|
||||||
|
$this->stateChanges("width", $width[1]);
|
||||||
|
$this->stateChanges("height", $height[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->save();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDimensions()
|
||||||
|
{
|
||||||
|
if($this->getType() == Video::TYPE_EMBED) return [320, 180];
|
||||||
|
|
||||||
|
$width = $this->getRecord()->width;
|
||||||
|
$height = $this->getRecord()->height;
|
||||||
|
|
||||||
|
if(!$width) return NULL;
|
||||||
|
return $width != 0 ? [$width, $height] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLength()
|
||||||
|
{
|
||||||
|
return $this->getRecord()->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFormattedLength(): string
|
||||||
|
{
|
||||||
|
$len = $this->getLength();
|
||||||
|
if(!$len) return "00:00";
|
||||||
|
$mins = floor($len / 60);
|
||||||
|
$secs = $len - ($mins * 60);
|
||||||
|
return (
|
||||||
|
str_pad((string) $mins, 2, "0", STR_PAD_LEFT)
|
||||||
|
. ":" .
|
||||||
|
str_pad((string) $secs, 2, "0", STR_PAD_LEFT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function canBeViewedBy(?User $user = NULL): bool
|
function canBeViewedBy(?User $user = NULL): bool
|
||||||
{
|
{
|
||||||
|
@ -248,7 +331,7 @@ class Video extends Media
|
||||||
$res->owner_id = $this->getOwner()->getId();
|
$res->owner_id = $this->getOwner()->getId();
|
||||||
$res->title = $this->getName();
|
$res->title = $this->getName();
|
||||||
$res->description = $this->getDescription();
|
$res->description = $this->getDescription();
|
||||||
$res->duration = "22";
|
$res->duration = $this->getLength();
|
||||||
$res->link = "/video".$this->getOwner()->getId()."_".$this->getVirtualId();
|
$res->link = "/video".$this->getOwner()->getId()."_".$this->getVirtualId();
|
||||||
$res->image = $this->getThumbnailURL();
|
$res->image = $this->getThumbnailURL();
|
||||||
$res->date = $this->getPublicationTime()->timestamp();
|
$res->date = $this->getPublicationTime()->timestamp();
|
||||||
|
|
|
@ -10,23 +10,37 @@
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
||||||
{if $attachment->getType() === 0}
|
{if $tilesCount <= 1}
|
||||||
<div class="bsdn media" data-name="{$attachment->getName()}" data-author="{$attachment->getOwner()->getCanonicalName()}">
|
{if $attachment->getType() === 0}
|
||||||
<video class="media" src="{$attachment->getURL()}"></video>
|
<div class="bsdn media" data-name="{$attachment->getName()}" data-author="{$attachment->getOwner()->getCanonicalName()}">
|
||||||
|
<video class="media" src="{$attachment->getURL()}"></video>
|
||||||
|
</div>
|
||||||
|
{else}
|
||||||
|
{var $driver = $attachment->getVideoDriver()}
|
||||||
|
{if !$driver}
|
||||||
|
<span style="color:red;">{_version_incompatibility}</span>
|
||||||
|
{else}
|
||||||
|
{$driver->getEmbed("100%")|noescape}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="video-wowzer">
|
||||||
|
<div class="small-video-ico"></div>
|
||||||
|
<a href="/video{$attachment->getPrettyId()}" id="videoOpen" data-id="{$attachment->getId()}">{$attachment->getName()}</a>
|
||||||
|
<span class="video-wowzer-length" n:if="$attachment->getLength() != NULL">({$attachment->getFormattedLength()})</span>
|
||||||
</div>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
{var $driver = $attachment->getVideoDriver()}
|
<a class='compact_video' id='videoOpen' data-id='{$attachment->getId()}' href="/video{$attachment->getPrettyId()}">
|
||||||
{if !$driver}
|
<div class='play-button'>
|
||||||
<span style="color:red;">{_version_incompatibility}</span>
|
<div class='play-button-ico'></div>
|
||||||
{else}
|
</div>
|
||||||
{$driver->getEmbed("100%")|noescape}
|
<div class='video-length' n:if="$attachment->getLength() != NULL">
|
||||||
{/if}
|
{$attachment->getFormattedLength()}
|
||||||
{/if}
|
</div>
|
||||||
|
|
||||||
<div class="video-wowzer">
|
<img class="media media_makima" src="{$attachment->getThumbnailURL()}" loading=lazy />
|
||||||
<img src="/assets/packages/static/openvk/img/videoico.png" />
|
</a>
|
||||||
<a href="/video{$attachment->getPrettyId()}" id="videoOpen" data-id="{$attachment->getId()}">{$attachment->getName()}</a>
|
{/if}
|
||||||
</div>
|
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
|
||||||
{presenter "openvk!Poll->view", $attachment->getId()}
|
{presenter "openvk!Poll->view", $attachment->getId()}
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Note}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Note}
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
{if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}></a>
|
{if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}></a>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$post->getPrettyId()}">
|
<div class="post-content" id="{$post->getPrettyId()}" data-localized-nsfw-text="{_nsfw_warning}">
|
||||||
<div class="text" id="text{$post->getPrettyId()}">
|
<div class="text" id="text{$post->getPrettyId()}">
|
||||||
<span data-text="{$post->getText(false)}" class="really_text">{$post->getText()|noescape}</span>
|
<span data-text="{$post->getText(false)}" class="really_text">{$post->getText()|noescape}</span>
|
||||||
|
|
||||||
|
@ -84,8 +84,8 @@
|
||||||
{/if}
|
{/if}
|
||||||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};">
|
||||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post"}
|
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
</a>
|
</a>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$post->getPrettyId()}">
|
<div class="post-content" id="{$post->getPrettyId()}" data-localized-nsfw-text="{_nsfw_warning}">
|
||||||
<div class="text" id="text{$post->getPrettyId()}">
|
<div class="text" id="text{$post->getPrettyId()}">
|
||||||
{var $owner = $author->getId()}
|
{var $owner = $author->getId()}
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@
|
||||||
{/if}
|
{/if}
|
||||||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};">
|
||||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post"}
|
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Makima
|
||||||
$this->photos = $photos;
|
$this->photos = $photos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getOrientation(Photo $photo, &$ratio): int
|
private function getOrientation($photo, &$ratio): int
|
||||||
{
|
{
|
||||||
[$width, $height] = $photo->getDimensions();
|
[$width, $height] = $photo->getDimensions();
|
||||||
$ratio = $width / $height;
|
$ratio = $width / $height;
|
||||||
|
|
|
@ -2441,7 +2441,7 @@ a.poll-retract-vote {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-horizontal .upload-item .play-button {
|
.post-horizontal .upload-item .play-button, .compact_video .play-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
@ -2452,7 +2452,7 @@ a.poll-retract-vote {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-horizontal .upload-item .play-button .play-button-ico {
|
.post-horizontal .upload-item .play-button .play-button-ico, .compact_video .play-button .play-button-ico {
|
||||||
background: url(/assets/packages/static/openvk/img/wall.png) no-repeat 1px 0;
|
background: url(/assets/packages/static/openvk/img/wall.png) no-repeat 1px 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
|
@ -2648,12 +2648,13 @@ a.poll-retract-vote {
|
||||||
padding: 3px 0;
|
padding: 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-wowzer a::before {
|
.video-wowzer .small-video-ico {
|
||||||
content: "b";
|
vertical-align: bottom;
|
||||||
color: transparent;
|
display: inline-block;
|
||||||
width: 12px;
|
width: 11px;
|
||||||
background-image: url(/assets/packages/static/openvk/img/videoico.png);
|
height: 14px;
|
||||||
display: none;
|
background: url(/assets/packages/static/openvk/img/wall.png?v=2);
|
||||||
|
background-position: -87px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Da search */
|
/* Da search */
|
||||||
|
@ -3511,3 +3512,26 @@ hr {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compact_video {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compact_video .video-length {
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
width: 34px;
|
||||||
|
height: 14px;
|
||||||
|
bottom: 5px;
|
||||||
|
right: 5px;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
.post-nsfw .post-content .media {
|
.post-nsfw .post-content {
|
||||||
filter: saturate(0.8) blur(15px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment {
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment:active .media {
|
.post-nsfw .post-content .text {
|
||||||
filter: none;
|
filter: saturate(0.8) blur(28px);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment::after {
|
.post-nsfw .post-content::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(50% - 16px);
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 0;
|
height: 100%;
|
||||||
background-color: hsla(0, 0%, 0%, .5);
|
z-index: 1;
|
||||||
|
background-color: hsla(0, 0%, 0%, .7);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
content: attr(data-localized-nsfw-text);
|
content: attr(data-localized-nsfw-text);
|
||||||
}
|
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment:active::after {
|
display: flex;
|
||||||
display: none;
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 130 B |
Binary file not shown.
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2.1 KiB |
|
@ -486,6 +486,7 @@ async function __uploadToTextarea(file, textareaNode) {
|
||||||
})
|
})
|
||||||
const json_response = await res.json()
|
const json_response = await res.json()
|
||||||
if(!json_response.success) {
|
if(!json_response.success) {
|
||||||
|
u(`#temp_filler${rand}`).remove()
|
||||||
fastError((tr("error_uploading_photo") + json_response.flash.message))
|
fastError((tr("error_uploading_photo") + json_response.flash.message))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1025,6 +1026,13 @@ u(document).on('click', '.post-buttons .upload-item', (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
u(document).on('click', '.post.post-nsfw .post-content', (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
u(e.target).closest('.post-nsfw').removeClass('post-nsfw')
|
||||||
|
})
|
||||||
|
|
||||||
async function repost(id, repost_type = 'post') {
|
async function repost(id, repost_type = 'post') {
|
||||||
const repostsCount = u(`#repostsCount${id}`)
|
const repostsCount = u(`#repostsCount${id}`)
|
||||||
const previousVal = repostsCount.length > 0 ? Number(repostsCount.html()) : 0;
|
const previousVal = repostsCount.length > 0 ? Number(repostsCount.html()) : 0;
|
||||||
|
|
2
install/sqls/000XX-new-video-fields.sql
Normal file
2
install/sqls/000XX-new-video-fields.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE `videos` ADD `length` SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER `name`, ADD INDEX `length` (`length`);
|
||||||
|
ALTER TABLE `videos` ADD `height` SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER `length`, ADD `width` SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER `height`;
|
Loading…
Reference in a new issue