AntonLV 7 лет назад
Родитель
Сommit
b5ad23df89

+ 2 - 0
modules/base/text/classes/BxBaseModTextModule.php

@@ -480,6 +480,7 @@ class BxBaseModTextModule extends BxBaseModGeneralModule implements iBxDolConten
                 continue;
 
             $aResults[] = array(
+                'id' => $a['id'],
                 'src' => $sPhotoSrc,
                 'src_medium' => $sPhotoSrc,
                 'src_orig' => $oStorage->getFileUrlById($a['id']),
@@ -562,6 +563,7 @@ class BxBaseModTextModule extends BxBaseModGeneralModule implements iBxDolConten
             $sUrl = $oStorage->getFileUrlById($a['id']);
 
             $aResults[] = array(
+                'id' => $a['id'],
                 'src' => $sPhotoSrc,
                 'src_medium' => $sPhotoSrc,
                 'src_orig' => $bImage ? $sUrl : '',

+ 11 - 3
modules/boonex/albums/classes/BxAlbumsModule.php

@@ -717,7 +717,7 @@ class BxAlbumsModule extends BxBaseModTextModule
     {
         $CNF = &$this->_oConfig->CNF;
 
-        if(empty($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']))
+        if(empty($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']) || empty($CNF['OBJECT_TRANSCODER_COVER']))
             return array();
 
         $aMediaList = $this->_oDb->getMediaListByContentId($aContentInfo[$CNF['FIELD_ID']]);
@@ -727,6 +727,7 @@ class BxAlbumsModule extends BxBaseModTextModule
         $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
         $oTcPoster = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['poster']);
         $oTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']);
+        $oTranscoderCover = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_TRANSCODER_COVER']);
         
         $aOutput = array();
         foreach ($aMediaList as $aMedia) {
@@ -737,12 +738,15 @@ class BxAlbumsModule extends BxBaseModTextModule
                 continue;
 
             $aOutput[$aMedia['id']] = array (
+                'id' => $aMedia['id'],
                 'url' => $this->_oTemplate->getViewMediaUrl($CNF, $aMedia['id']), 
                 'src' => $oTranscoder->getFileUrl($aMedia['file_id']),
+                'src_orig' => $oTranscoderCover->getFileUrl($aMedia['file_id'])
             );
         }
 
-        return count($aOutput) > 3 ? array_slice($aOutput, 0, 3) : $aOutput;
+        $iSliceLenth = 4;
+        return count($aOutput) > $iSliceLenth ? array_slice($aOutput, 0, $iSliceLenth) : $aOutput;
     }
 
     protected function _getVideosForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
@@ -783,10 +787,12 @@ class BxAlbumsModule extends BxBaseModTextModule
                 'src_poster' => $oTcPoster->getFileUrl($aMedia['file_id']),
                 'src_mp4' => $oTcMp4->getFileUrl($aMedia['file_id']),
                 'src_mp4_hd' => $sVideoUrlHd,
+                'duration' => $aFileInfo['duration'],
             );
         }
 
-        return count($aOutput) > 3 ? array_slice($aOutput, 0, 3) : $aOutput;
+        $iSliceLenth = 4;
+        return count($aOutput) > $iSliceLenth ? array_slice($aOutput, 0, $iSliceLenth) : $aOutput;
     }
 
     protected function _getContentForTimelineMedia($aEvent, $aContentInfo, $aBrowseParams = array())
@@ -817,9 +823,11 @@ class BxAlbumsModule extends BxBaseModTextModule
                     'src_poster' => $oTcPoster->getFileUrl($aMediaInfo['file_id']),
                     'src_mp4' => $oTcMp4->getFileUrl($aMediaInfo['file_id']),
                     'src_mp4_hd' => $oTcMp4Hd->getFileUrl($aMediaInfo['file_id']),
+                    'duration' => $aFileInfo['duration'],
                 );
             else
                 $aImages[$iMediaId] = array(
+                    'id' => $aMediaInfo['id'],
                     'url' => $this->_oTemplate->getViewMediaUrl($CNF, $aMediaInfo['id']), 
                     'src' => $oTranscoder->getFileUrl($aMediaInfo['file_id']),
                 );

+ 3 - 0
modules/boonex/russian/data/langs/bx_timeline/ru.xml

@@ -23,6 +23,9 @@
     <string name="_bx_timeline_option_videos_autoplay_on"><![CDATA[Включено (cо звуком)]]></string>
     <string name="_bx_timeline_option_preload_comments"><![CDATA[Количество предварительно загруженных комментариев (до 7 штук)]]></string>
     <string name="_bx_timeline_option_enable_jump_to_switcher"><![CDATA[Показывать переключатель 'Перейти к']]></string>
+    <string name="_bx_timeline_option_attachments_layout"><![CDATA[Показывать вложения как]]></string>
+    <string name="_bx_timeline_option_attachments_layout_gallery"><![CDATA[Галерея]]></string>
+    <string name="_bx_timeline_option_attachments_layout_showcase"><![CDATA[Витрина]]></string>
     <string name="_bx_timeline_option_enable_hot"><![CDATA[Включить сбор данных для листа 'горячих' сообщений]]></string>
     <string name="_bx_timeline_option_hot_interval"><![CDATA[Интервал времени (в часах) для получения 'горячих' сообщений]]></string>
     <string name="_bx_timeline_option_enable_cache_item"><![CDATA[Включить кэш элемента]]></string>

+ 12 - 0
modules/boonex/timeline/classes/BxTimelineConfig.php

@@ -38,6 +38,7 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
     protected $_iPreloadComments;
     protected $_iPreloadCommentsMax;
     protected $_bJumpTo;
+    protected $_sAttachmentsLayout;
 
     protected $_bHot;
     protected $_iHotInterval;
@@ -131,6 +132,11 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
                 'txt_sample_with_media' => '_bx_timeline_txt_sample_with_media',
                 'grid_action_err_delete' => '_bx_timeline_grid_action_err_delete', 
                 'grid_txt_account_manager' => '_bx_timeline_grid_txt_account_manager',
+                'option_vap_off' => '_bx_timeline_option_videos_autoplay_off',
+                'option_vap_on_mute' => '_bx_timeline_option_videos_autoplay_on_mute',
+                'option_vap_on' => '_bx_timeline_option_videos_autoplay_on',
+                'option_al_gallery' => '_bx_timeline_option_attachments_layout_gallery',
+                'option_al_showcase' => '_bx_timeline_option_attachments_layout_showcase'
             ),
         );
 
@@ -313,6 +319,7 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
             $this->_iPreloadComments = $this->_iPreloadCommentsMax;
 
         $this->_bJumpTo = getParam($sOptionPrefix . 'enable_jump_to_switcher') == 'on';
+        $this->_sAttachmentsLayout = getParam($sOptionPrefix . 'attachments_layout');
 
         $this->_bHot = getParam($sOptionPrefix . 'enable_hot') == 'on';
         $this->_iHotInterval = (int)getParam($sOptionPrefix . 'hot_interval');
@@ -514,6 +521,11 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
         return $this->_iPreloadComments;
     }
 
+    public function getAttachmentsLayout()
+    {
+        return $this->_sAttachmentsLayout;
+    }
+
     public function getHotInterval()
     {
         return $this->_iHotInterval;

+ 45 - 2
modules/boonex/timeline/classes/BxTimelineModule.php

@@ -48,6 +48,14 @@ define('BX_TIMELINE_VAP_OFF', 'off');
 define('BX_TIMELINE_VAP_ON_MUTE', 'on_mute');
 define('BX_TIMELINE_VAP_ON', 'on');
 
+//--- Media Layouts
+define('BX_TIMELINE_ML_SINGLE', 'single');
+define('BX_TIMELINE_ML_GALLERY', 'gallery');
+define('BX_TIMELINE_ML_SHOWCASE', 'showcase');
+
+//--- Default Attachments Media Layout
+define('BX_TIMELINE_AML_DEFAULT', BX_TIMELINE_ML_GALLERY);
+
 class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolContentInfoService
 {
     protected $_sJsPostObject;
@@ -2201,7 +2209,7 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
         return 'BxTimelineFormCheckerHelper';
     }
 
-	/**
+    /**
      * @page service Service Calls
      * @section bx_timeline Timeline
      * @subsection bx_timeline-other Other
@@ -2220,13 +2228,48 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
      */
     public function serviceGetOptionsVideosAutoplay()
     {
+        $CNF = &$this->_oConfig->CNF;
+
         $aOptions = array(BX_TIMELINE_VAP_OFF, BX_TIMELINE_VAP_ON_MUTE, BX_TIMELINE_VAP_ON);
 
         $aResult = array();
         foreach($aOptions as $sOption)
             $aResult[] = array(
                 'key' => $sOption,
-                'value' => _t('_bx_timeline_option_videos_autoplay_' . $sOption)
+                'value' => _t($CNF['T']['option_vap_' . $sOption])
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_options_attachments_layout get_options_attachments_layout
+     * 
+     * @code bx_srv('bx_timeline', 'get_options_attachments_layout', [...]); @endcode
+     * 
+     * Get an array with available options for 'Show attachments as' setting.
+     *
+     * @return an array with available options represented as key => value pairs.
+     * 
+     * @see BxTimelineModule::serviceGetOptionsAttachmentsLayout
+     */
+    /** 
+     * @ref bx_timeline-get_options_attachments_layout "get_options_attachments_layout"
+     */
+    public function serviceGetOptionsAttachmentsLayout()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOptions = array(BX_TIMELINE_ML_GALLERY, BX_TIMELINE_ML_SHOWCASE);
+
+        $aResult = array();
+        foreach($aOptions as $sOption)
+            $aResult[] = array(
+                'key' => $sOption,
+                'value' => _t($CNF['T']['option_al_' . $sOption])
             );
 
         return $aResult;

+ 123 - 26
modules/boonex/timeline/classes/BxTimelineTemplate.php

@@ -1888,12 +1888,19 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
                 );
             }
 
+        /*
+         * View Item page should use Gallery layout.
+         */
+        $sAttachmentsLayout = $this->_oConfig->getAttachmentsLayout();
+        if($bViewItem)
+            $sAttachmentsLayout = BX_TIMELINE_ML_GALLERY;
+
         $aTmplVarsImages = $aTmplVarsVideos = $aTmplVarsAttachments = array();
 
         //--- Process Photos ---//
         $bImages = !empty($aContent['images']) && is_array($aContent['images']);
         if($bImages) {
-            $aImages = $this->_getTmplVarsImages($aContent['images'], $aEvent, $aBrowseParams);
+            $aImages = $this->_getTmplVarsImages($aContent['images'], true, $aEvent, $aBrowseParams);
             if(!empty($aImages))
                 $aTmplVarsImages = array(
                     'style_prefix' => $sStylePrefix,
@@ -1904,7 +1911,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
 
         $bImagesAttach = !empty($aContent['images_attach']) && is_array($aContent['images_attach']);
         if($bImagesAttach) {
-            $aImagesAttach = $this->_getTmplVarsImages($aContent['images_attach'], $aEvent, $aBrowseParams);
+            $aImagesAttach = $this->_getTmplVarsImages($aContent['images_attach'], array('layout' => $sAttachmentsLayout, 'first' => empty($aTmplVarsAttachments)), $aEvent, $aBrowseParams);
             if(!empty($aImagesAttach))
                 $aTmplVarsAttachments = array_merge ($aTmplVarsAttachments, $aImagesAttach['items']);
         }
@@ -1936,7 +1943,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
 
         $bVideosAttach = !empty($aContent['videos_attach']) && is_array($aContent['videos_attach']);
         if($bVideosAttach) {
-            $aVideosAttach = $this->_getTmplVarsVideos($aContent['videos_attach'], false, $aEvent, $aBrowseParams);
+            $aVideosAttach = $this->_getTmplVarsVideos($aContent['videos_attach'], array('layout' => $sAttachmentsLayout, 'first' => empty($aTmplVarsAttachments)), $aEvent, $aBrowseParams);
             if(!empty($aVideosAttach))
                 $aTmplVarsAttachments = array_merge($aTmplVarsAttachments, $aVideosAttach['items']);
         }
@@ -1960,6 +1967,23 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
                 $aTmplVarsAttachments = array_merge ($aTmplVarsAttachments, $aFilesAttach['items']);
         }
 
+        /*
+         *  Process collected attachments in case of Showcase layout.
+         */
+        $iAttachmentsShow = 4;
+        $iAttachmentsCount = count($aTmplVarsAttachments);
+        if($sAttachmentsLayout == BX_TIMELINE_ML_SHOWCASE && $iAttachmentsCount > 0) {
+            $aTmplVarsAttachments[0]['class'] .= ' ' . $sStylePrefix . '-ia-first';
+
+            if($iAttachmentsCount > $iAttachmentsShow) {
+                $aTmplVarsAttachments = array_slice($aTmplVarsAttachments, 0, $iAttachmentsShow);
+                $aTmplVarsAttachments[$iAttachmentsShow - 1]['item'] .= $this->parseHtmlByName('attach_more.html', array(
+                    'style_prefix' => $sStylePrefix,
+                    'more' => $iAttachmentsCount - $iAttachmentsShow
+                ));
+            }
+        }
+
         return array(
             'style_prefix' => $sStylePrefix,
             'bx_if:show_title' => array(
@@ -2002,6 +2026,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
                 'condition' => !empty($aTmplVarsAttachments),
                 'content' => array(
                     'style_prefix' => $sStylePrefix,
+                    'display' => $sAttachmentsLayout,
                     'bx_repeat:items' => $aTmplVarsAttachments
                 )
             )
@@ -2133,7 +2158,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         );
     }
 
-    protected function _getTmplVarsImages($aImages, &$aEvent, &$aBrowseParams)
+    protected function _getTmplVarsImages($aImages, $mixedLayout, &$aEvent, &$aBrowseParams)
     {
         if(empty($aImages) || !is_array($aImages))
             return array();
@@ -2146,19 +2171,34 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         $sDisplay = '';
         $aTmplVarsImages = array();
 
-        $sImageSrcKey = '';
+        $sImageSrcKey = $sImageSrcKeyBig = '';
         $sImageSrcKeyDefault = 'src';
         if(count($aImages) == 1) {
-            $sDisplay = 'single';
+            $sDisplay = BX_TIMELINE_ML_SINGLE;
             $sImageSrcKey = $bViewItem ? 'src_orig' : 'src_medium';
         }
+        else if(is_array($mixedLayout) && !empty($mixedLayout['layout'])) {
+            $sDisplay = $mixedLayout['layout'];
+            $sImageSrcKey = 'src';
+            $sImageSrcKeyBig = 'src_orig';
+        }
         else {
-            $sDisplay = 'gallery';
+            $sDisplay = BX_TIMELINE_ML_GALLERY;
             $sImageSrcKey = 'src';
+            $sImageSrcKeyBig = 'src_orig';
         }
 
+        $bAttachFirst = false;
+        if($sDisplay == BX_TIMELINE_ML_SHOWCASE)
+            $bAttachFirst = isset($mixedLayout['first']) && $mixedLayout['first'] === true;
+
+        $iImageFirst = reset($aImages)['id'];
         foreach($aImages as $aImage) {
-            $sImageSrc = !empty($aImage[$sImageSrcKey]) ? $aImage[$sImageSrcKey] : $aImage[$sImageSrcKeyDefault];
+            $sImageSrcKeyCur = $sImageSrcKey;
+            if($bAttachFirst && $aImage['id'] == $iImageFirst)
+                $sImageSrcKeyCur = $sImageSrcKeyBig;
+
+            $sImageSrc = !empty($aImage[$sImageSrcKeyCur]) ? $aImage[$sImageSrcKeyCur] : $aImage[$sImageSrcKeyDefault];
             if(empty($sImageSrc))
                 continue;
 
@@ -2176,6 +2216,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
 
             $aTmplVarsImages[] = array(
                 'style_prefix' => $sStylePrefix,
+                'class' => '',
                 'item' => $sImage
             );
         }
@@ -2186,18 +2227,29 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         );
     }
 
-    protected function _getTmplVarsVideos($aVideos, $bMain, &$aEvent, &$aBrowseParams)
+    protected function _getTmplVarsVideos($aVideos, $mixedLayout, &$aEvent, &$aBrowseParams)
     {
         if(empty($aVideos) || !is_array($aVideos))
             return array();
 
         $sStylePrefix = $this->_oConfig->getPrefix('style');
-
-        $sDisplay = count($aVideos) == 1 ? 'single' : 'gallery';
         $aTmplVarsVideos = array();
 
+        $bMain = $mixedLayout === true;
+
         /*
-         * Autoplay feature is available for Main video only.
+         * For now Main Section may have only one video which can use 'autoplay' feature.
+         */
+        $sDisplay = BX_TIMELINE_ML_SINGLE;
+        if(count($aVideos) > 1) {
+            if($bMain)
+                $aVideos = array_slice($aVideos, 0, 1);
+            else
+                $sDisplay = is_array($mixedLayout) && !empty($mixedLayout['layout']) ? $mixedLayout['layout'] : BX_TIMELINE_AML_DEFAULT;
+        }
+
+        /*
+         * Main Section: Autoplay feature is only available here.
          */
         $sVap = $sVapId = $sVapSrc = $sVapTmpl = '';
         if($bMain) {
@@ -2205,30 +2257,73 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
             if($sVap != BX_TIMELINE_VAP_OFF) {
                 $sVapId = $this->_oConfig->getHtmlIds('view', 'video_iframe') . $aEvent['id'] . '-';
                 $sVapSrc = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'video/' . $aEvent['id'] . '/';
-                $sVapTmpl = $this->getHtml('video_iframe.html');
-
-                if(count($aVideos) > 1)
-                    $aVideos = array_slice($aVideos, 0, 1);
+                $sVapTmpl = $this->getHtml('video_iframe.html'); 
             }
         }
 
-        foreach($aVideos as $iVideo => $aVideo) {
-            if(!$bMain || $sVap == BX_TIMELINE_VAP_OFF)
-                $aTmplVarsVideos[] = array(
-                    'style_prefix' => $sStylePrefix,
-                    'item' => BxTemplFunctions::getInstance()->videoPlayer($aVideo['src_poster'], $aVideo['src_mp4'], $aVideo['src_mp4_hd'], array(
-                        'preload' => 'auto'
-                    ), '', $aBrowseParams['dynamic_mode'])
-                );
-            else 
+        /*
+         * Attachments Section.
+         */
+        $sAttachTmpl = '';
+        $bAttachFirst = false;
+        if($sDisplay == BX_TIMELINE_ML_SHOWCASE) {
+            $sAttachTmpl = $this->getHtml('attach_video_preview.html');
+            $bAttachFirst = isset($mixedLayout['first']) && $mixedLayout['first'] === true;
+        }
+
+        $iVideoFirst = reset($aVideos)['id'];
+        foreach($aVideos as $aVideo) {
+            $iVideo = (int)$aVideo['id'];
+
+            if($bMain && $sVap != BX_TIMELINE_VAP_OFF)
                 $aTmplVarsVideos[] = array(
                     'style_prefix' => $sStylePrefix,
+                    'class' => '',
                     'item' => $this->parseHtmlByContent($sVapTmpl, array(
                         'style_prefix' => $sStylePrefix,
                         'html_id' => $sVapId . $iVideo,
                         'src' => $sVapSrc . $iVideo . '/'
                     )) 
                 );
+            else {
+                if($bMain || $sDisplay == BX_TIMELINE_ML_GALLERY || ($bAttachFirst && $iVideo == $iVideoFirst))
+                    $aTmplVarsVideos[] = array(
+                        'style_prefix' => $sStylePrefix,
+                        'class' => '',
+                        'item' => BxTemplFunctions::getInstance()->videoPlayer($aVideo['src_poster'], $aVideo['src_mp4'], $aVideo['src_mp4_hd'], array(
+                            'preload' => 'auto'
+                        ), '', $aBrowseParams['dynamic_mode'])
+                    );
+                else {
+                    $bUrl = !empty($aVideo['url']);
+                    $sUrl = $bUrl ? $aVideo['url'] : '';
+
+                    $aTmplVarsVideos[] = array(
+                        'style_prefix' => $sStylePrefix,
+                        'class' => '',
+                        'item' => $this->parseHtmlByContent($sAttachTmpl, array(
+                            'style_prefix' => $sStylePrefix,
+                            'bx_if:show_link' => array(
+                                'condition' => $bUrl,
+                                'content' => array(
+                                    'style_prefix' => $sStylePrefix,
+                                    'url' => $sUrl,
+                                    'src' => $aVideo['src_poster'],
+                                )
+                            ),
+                            'bx_if:show_non_link' => array(
+                                'condition' => !$bUrl,
+                                'content' => array(
+                                    'style_prefix' => $sStylePrefix,
+                                    'src' => $aVideo['src_poster'],
+                                )
+                            ),
+                            'duration' => !empty($aVideo['duration']) ? _t_format_duration($aVideo['duration']) : 0
+                        ))
+                    );
+                }
+            }
+                
         }
 
         return array( 
@@ -2280,6 +2375,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
 
             $aTmplVarsFiles[] = array(
                 'style_prefix' => $sStylePrefix,
+                'class' => '',
                 'item' => $sImage
             );
         }
@@ -2380,8 +2476,9 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
                             $sPhotoSrcBig = $sPhotoSrcMedium;
 
                         $aResult['content']['images_attach'][] = array(
+                            'id' => $iPhotoId,
                             'src' => $sPhotoSrc,
-                        	'src_medium' => $sPhotoSrcMedium,
+                            'src_medium' => $sPhotoSrcMedium,
                             'src_orig' => $sPhotoSrcBig,
                         );
                     }

+ 3 - 0
modules/boonex/timeline/install/langs/en.xml

@@ -23,6 +23,9 @@
     <string name="_bx_timeline_option_videos_autoplay_on"><![CDATA[Enabled with sound]]></string>
     <string name="_bx_timeline_option_preload_comments"><![CDATA[Number of preloaded comments (up to 7 items)]]></string>
     <string name="_bx_timeline_option_enable_jump_to_switcher"><![CDATA[Show 'Jump to' switcher]]></string>
+    <string name="_bx_timeline_option_attachments_layout"><![CDATA[Show attachments as]]></string>
+    <string name="_bx_timeline_option_attachments_layout_gallery"><![CDATA[Gallery]]></string>
+    <string name="_bx_timeline_option_attachments_layout_showcase"><![CDATA[Showcase]]></string>
     <string name="_bx_timeline_option_enable_hot"><![CDATA[Enable Hot list aggregation]]></string>
     <string name="_bx_timeline_option_hot_interval"><![CDATA[Interval of time (in hours) to get Hot events]]></string>
     <string name="_bx_timeline_option_enable_cache_item"><![CDATA[Enable item cache]]></string>

+ 1 - 0
modules/boonex/timeline/install/sql/enable.sql

@@ -216,6 +216,7 @@ INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `c
 ('bx_timeline_videos_autoplay', 'off', @iCategId, '_bx_timeline_option_videos_autoplay', 'select', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:27:"get_options_videos_autoplay";}', 50),
 ('bx_timeline_preload_comments', '0', @iCategId, '_bx_timeline_option_preload_comments', 'digit', '', '', '', '', 51),
 ('bx_timeline_enable_jump_to_switcher', 'on', @iCategId, '_bx_timeline_option_enable_jump_to_switcher', 'checkbox', '', '', '', '', 52),
+('bx_timeline_attachments_layout', 'gallery', @iCategId, '_bx_timeline_option_attachments_layout', 'select', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:30:"get_options_attachments_layout";}', 53),
 ('bx_timeline_enable_hot', 'on', @iCategId, '_bx_timeline_option_enable_hot', 'checkbox', '', '', '', '', 60),
 ('bx_timeline_hot_interval', '48', @iCategId, '_bx_timeline_option_hot_interval', 'digit', '', '', '', '', 61),
 ('bx_timeline_enable_cache_item', 'on', @iCategId, '_bx_timeline_option_enable_cache_item', 'checkbox', '', '', '', '', 70),

+ 3 - 0
modules/boonex/timeline/template/attach_more.html

@@ -0,0 +1,3 @@
+<div class="__style_prefix__-item-more">
+    <span>+__more__</span>
+</div>

+ 9 - 0
modules/boonex/timeline/template/attach_video_preview.html

@@ -0,0 +1,9 @@
+<div class="__style_prefix__-item-video">
+    <bx_if:show_link>
+        <a href="__url__"><img class="__style_prefix__-iv-image" src="__src__" /></a>
+    </bx_if:show_link>
+    <bx_if:show_non_link>
+        <img class="__style_prefix__-iv-image" src="__src__" />
+    </bx_if:show_non_link>
+    <div class="__style_prefix__-iv-duration bx-def-padding-thd bx-def-border bx-def-round-corners">__duration__</div>
+</div>

+ 56 - 0
modules/boonex/timeline/template/css/view.css

@@ -594,6 +594,7 @@ div.bx-tl-view-search div.bx-tl-item-attachment img {
     height: 12.5rem;
 }
 
+/*+++ Video +++*/
 div.bx-tl-view-timeline div.bx-tl-item-attachment video,
 div.bx-tl-view-outline div.bx-tl-item-attachment video,
 div.bx-tl-view-item div.bx-tl-item-attachment video {
@@ -602,6 +603,61 @@ div.bx-tl-view-item div.bx-tl-item-attachment video {
     margin-left: auto;
     margin-right: auto;
 }
+div.bx-tl-item-attachment .bx-tl-item-video {
+    position: relative;
+}
+div.bx-tl-item-attachment .bx-tl-iv-duration {
+    position: absolute;
+    right: 0.25rem;
+    bottom: 0.25rem;
+    background-color: rgba(255, 255, 255, 0.8);
+}
+
+/*+++ Showcase Layout +++*/
+div.bx-tl-item-attachments.bx-tl-ia-showcase {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+    -webkit-justify-content: space-between;
+    justify-content: space-between;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase div.bx-tl-item-attachment {
+    box-sizing: border-box;
+    width: 33.2%;
+    height: 8.5rem;
+    border: 1px solid transparent;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase div.bx-tl-item-attachment.bx-tl-ia-first {
+    width: 100%;
+    height: auto;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase img {
+    position: relative;
+    display: block;
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase .bx-tl-item-more {
+    position: absolute;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.7);
+
+    font-size: 2.5rem;
+    color: #ffffff;
+}
+
 
 /*+++ Slider Styles  +++*/
 div.bx-tl-item-images .flickity-slider,

+ 2 - 2
modules/boonex/timeline/template/type_post.html

@@ -21,9 +21,9 @@
     </bx_if:show_content>
 </div>
 <bx_if:show_attachments>
-    <div class="__style_prefix__-item-attachments __style_prefix__-ia-gallery bx-def-margin-top bx-def-margin-leftright">
+    <div class="__style_prefix__-item-attachments __style_prefix__-ia-__display__ bx-def-margin-top bx-def-margin-leftright">
         <bx_repeat:items>
-            <div class="__style_prefix__-item-attachment">__item__</div>
+            <div class="__style_prefix__-item-attachment__class__">__item__</div>
         </bx_repeat:items>
     </div>
 </bx_if:show_attachments>