WWBN / AVideo

Create Your Own Broadcast Network With AVideo Platform Open-Source. OAVP OVP
https://avideo.tube/AVideo_OpenSource
Other
1.91k stars 972 forks source link

Make the Live Row on Gallery the Top feature of the home page #9332

Closed JoshWho closed 3 months ago

JoshWho commented 3 months ago

Is there a way we can get the Live Streams to be on top of the Gallery Home and then put the carrousel under it?

Screenshot - 2024-08-13T193132 871

DanielnetoDotCom commented 3 months ago

Sorry, currently no

JoshWho commented 3 months ago

What has to be done to move the livestreams above the carousel?

DanielnetoDotCom commented 3 months ago

Probady create a new Gallery plugin or modify the current one.

but I am not sure what you need to modify.

JoshWho commented 3 months ago

If I modify the original will it be overwritten every Git pull? I will take it apart tonight. I might also just try to copy the Gallery just hope it won't have symlinks or cross css issues with the original .

DanielnetoDotCom commented 3 months ago

I do not recommend you to modify the original, if you really want, copy it and rename as a new plugin

https://github.com/WWBN/AVideo/wiki/How-to-code-a-AVideo-Platform-plugin

If you do not modify the original will be easier for you to follow the updates.

JoshWho commented 3 months ago

Sounds good. I will give it a shot tonight and let you know how it goes.

JoshWho commented 3 months ago

I found the file that needs changed but now having trouble using the new theme. It is not showing up.

Every time I try to upload it it never shows up in the Plugin menu. Is there another step I am missing?

DanielnetoDotCom commented 3 months ago

Not sure, maybe the filenames or dir name or pluin class name

also make sure you have a unique getUUID

JoshWho commented 3 months ago

What file would have the GUID in it? or is it multiple files?

image

DanielnetoDotCom commented 3 months ago

From the image I can see you did not rename the plugin properly

If you really want to try create your own plugin, you MUST read this https://github.com/WWBN/AVideo/wiki/How-to-code-a-AVideo-Platform-plugin

JoshWho commented 3 months ago

After renaming those now this happens

Screenshot - 2024-08-17T195508 877

image

JoshWho commented 3 months ago
<?php

require_once $global['systemRootPath'] . 'plugin/Plugin.abstract.php';
require_once $global['systemRootPath'] . 'plugin/AVideoPlugin.php';
require_once $global['systemRootPath'] . 'objects/Channel.php';

class Gallery2 extends PluginAbstract
{
    const BigVideoLiveDisabled = 0;
    const BigVideoLiveShowLiveAndVOD = 1;
    const BigVideoLiveShowLiveOnly = 2;
    const BigVideoLiveShowVODOnly = 3;

    public function getTags()
    {
        return array(
            PluginTags::$RECOMMENDED,
            PluginTags::$FREE,
            PluginTags::$Gallery2,
            PluginTags::$LAYOUT,
        );
    }

    public function getDescription()
    {
        return "Make the first page works as a Gallery2";
    }

    public function getName()
    {
        return "Gallery2";
    }

    public function getUUID()
    {
        return "420-420-420-420-420";
    }

    public function getPluginVersion()
    {
        return "4.20";
    }

    public function getHeadCode()
    {
        global $global;
        $obj = $this->getDataObject();
        // preload image
        $js = "<script>var img1 = new Image();img1.src=\"" . ImagesPlaceHolders::getVideoPlaceholder(ImagesPlaceHolders::$RETURN_URL) . "\";</script>";
        $css = '<link href="' . getURL('plugin/Gallery2/style.css') . '" rel="stylesheet" type="text/css"/>';

        if (!empty($obj->playVideoOnFullscreenOnIframe)) {
            if (canFullScreen()) {
                $css .= '<link href="' . getURL('plugin/YouPHPFlix2/view/css/fullscreen.css') . '" rel="stylesheet" type="text/css"/>';
                $css .= '<style>.container-fluid {overflow: visible;padding: 0;}#mvideo{padding: 0 !important; position: absolute; top: 0;}</style>';
                $css .= '<style>body.fullScreen{overflow: hidden;}</style>';
            }
            $js .= '<script>var playVideoOnFullscreen = true</script>';
        } else if (!empty($obj->playVideoOnFullscreen) && canFullScreen()) {
            $css .= '<link href="' . getCDN() . 'plugin/Gallery2/fullscreen.css" rel="stylesheet" type="text/css"/>';
        }
        if (!empty($obj->playVideoOnFullscreen)) {
            $css .= '<style>body.fullScreen{overflow: hidden;}</style>';
        }

        return $js . $css;
    }

    public function getEmptyDataObject()
    {
        global $global;
        $obj = new stdClass();
        $obj->MainContainerFluid = true;
        $obj->hidePrivateVideos = false;
        $obj->BigVideo = true;

        $o = new stdClass();
        $o->type = [
            Gallery2::BigVideoLiveDisabled => 'Disable', 
            Gallery2::BigVideoLiveShowLiveAndVOD => 'Show Live and VOD', 
            Gallery2::BigVideoLiveShowLiveOnly => 'Show Live Only'
        ];
        $o->value = Gallery2::BigVideoLiveShowLiveAndVOD;
        $obj->BigVideoLive = $o;
        self::addDataObjectHelper('BigVideoLive', 'Big Video Live');
        $obj->BigVideoLiveOnFirstPageOnly = true;
        self::addDataObjectHelper('BigVideoLiveOnFirstPageOnly', 'Big Video Live on First Page Only');
        $obj->BigVideoLiveForLoggedUsersOnly = false;
        self::addDataObjectHelper('BigVideoLiveForLoggedUsersOnly', 'Big Video Live will appear only if the user is logged');

        $obj->useSuggestedVideosAsCarouselInBigVideo = true;
        $obj->GifOnBigVideo = true;
        $obj->Description = false;
        $obj->CategoryDescription = false;

        $obj->Shorts = true;
        $obj->ShortsCustomTitle = "";
        $obj->ShortsRowCount = 12;
        $obj->ShortsOrder = 1;

        $obj->Suggested = true;
        $obj->SuggestedCustomTitle = "";
        $obj->SuggestedRowCount = 12;
        $obj->SuggestedOrder = 1;

        $obj->PlayLists = true;
        $obj->PlayListsRowCount = 12;
        $obj->PlayListsOrder = 2;

        $obj->Trending = true;
        $obj->TrendingCustomTitle = "";
        $obj->TrendingRowCount = 12;
        $obj->TrendingOrder = 2;

        $obj->DateAdded = true;
        $obj->DateAddedCustomTitle = "";
        $obj->DateAddedRowCount = 12;
        $obj->DateAddedOrder = 3;

        $obj->PrivateContent = true;
        $obj->PrivateContentCustomTitle = "";
        $obj->PrivateContentRowCount = 12;
        $obj->PrivateContentOrder = 4;

        $obj->MostWatched = true;
        $obj->MostWatchedCustomTitle = "";
        $obj->MostWatchedRowCount = 12;
        $obj->MostWatchedOrder = 4;

        $obj->MostPopular = true;
        $obj->MostPopularCustomTitle = "";
        $obj->MostPopularRowCount = 12;
        $obj->MostPopularOrder = 5;

        $obj->SortByName = false;
        $obj->SortByNameCustomTitle = "";
        $obj->SortByNameRowCount = 12;
        $obj->SortByNameOrder = 6;

        $obj->SubscribedChannels = true;
        $obj->SubscribedChannelsRowCount = 12;
        $obj->SubscribedChannelsOrder = 7;

        $obj->SubscribedTags = true;
        $obj->SubscribedTagsRowCount = 12;
        $obj->SubscribedTagsOrder = 7;

        $obj->Categories = true;
        $obj->CategoriesCustomTitle = "";
        $obj->CategoriesRowCount = 12;
        $obj->CategoriesOrder = 7;
        $obj->CategoriesShowOnlySuggested = false;

        $obj->sortReverseable = false;
        $obj->SubCategorys = false;
        self::addDataObjectHelper('SubCategorys', 'Show Subcategories', 'When you are in the categories page, show the subcategories link at the top');
        $obj->showTags = true;
        $obj->showCategoryTag = true;
        $obj->showCategoryLiveRow = false;
        $obj->searchOnChannels = true;
        $obj->searchOnChannelsRowCount = 12;
        $obj->playVideoOnFullscreen = false;
        $obj->playVideoOnFullscreenOnIframe = false;
        $obj->playVideoOnBrowserFullscreen = false;
        $obj->filterUserChannel = false;
        $obj->screenColsLarge = 6;
        $obj->screenColsMedium = 3;
        $obj->screenColsSmall = 2;
        $obj->screenColsXSmall = 1;
        $obj->allowSwitchTheme = true;
        self::addDataObjectHelper('allowSwitchTheme', 'Show Switch theme button');
        $themes = getThemes();
        foreach ($themes as $value) {
            $name = ucfirst($value);
            eval('$obj->SwitchThemeShow' . $name . ' = true;');
            self::addDataObjectHelper('SwitchThemeShow' . $name, 'Show ' . $name . ' Option', 'Uncheck this button to not show the ' . $name . ' in your themes list');
            eval('$obj->SwitchThemeLabel' . $name . ' = "' . $name . '";');
            self::addDataObjectHelper('SwitchThemeLabel' . $name, $name . ' Theme Label', 'Change the label name to the theme ' . $name . ' in your themes list');
        }

        return $obj;
    }

    public function navBarProfileButtons()
    {
        global $global;
        $navBarButtons = 0;
        $obj = $this->getDataObject();
        if ($obj->allowSwitchTheme) {
            include $global['systemRootPath'] . 'plugin/Gallery2/view/themeSwitcher.php';
        }
    }

    public function navBarButtons()
    {
        global $global;
        $navBarButtons = 1;
        $obj = $this->getDataObject();
        if (!empty($obj->allowSwitchTheme)) {
            include $global['systemRootPath'] . 'plugin/Gallery2/view/themeSwitcher.php';
        }
    }

    public function getHelp()
    {
        if (User::isAdmin()) {
            return "<h2 id='Gallery2 help'>" . __('Gallery2 options (admin)') . "</h2><table class='table'><thead><th>" . __('Option-name') . "</th><th>" . __('Default') . "</th><th>" . __('Description') . "</th></thead><tbody><tr><td>BigVideo</td><td>" . __('checked') . "</td><td>" . __('Create a big preview with a direct description on top') . "</td></tr><tr><td>DateAdded,MostPopular,MostWatched,SortByName</td><td>" . __('checked') . "," . __('checked') . "," . __('checked') . "," . __('unchecked') . "</td><td>" . __('Metacategories') . "</td></tr><tr><td>SubCategorys</td><td>" . __('unchecked') . "</td> <td>" . __('Enable a view for subcategories on top') . "</td></tr><tr><td>Description</td><td>" . __('unchecked') . "</td><td>" . __('Enable a small button for show the description') . "</td></tr></tbody></table>";
        }
        return "";
    }

    public function getFirstPage()
    {
        global $global;
        if (!AVideoPlugin::isEnabledByName("YouPHPFlix2")) {
            return $global['systemRootPath'] . 'plugin/Gallery2/view/modeGallery2.php';
        }
    }

    public function getFooterCode()
    {
        $obj = $this->getDataObject();
        global $global;

        $js = '';
        if (!empty($obj->playVideoOnFullscreenOnIframe)) {
            $js = '<script src="' . getURL('plugin/YouPHPFlix2/view/js/fullscreen.js') . '"></script>';
            $js .= '<script>$(function () { if(typeof linksToFullscreen === \'function\'){ linksToFullscreen(\'a.Gallery2Link\'); } });</script>';
        } else
        if (!empty($obj->playVideoOnFullscreen)) {
            $js = '<script src="' . getURL('plugin/YouPHPFlix2/view/js/fullscreen.js') . '"></script>';
            $js .= '<script>$(function () { if(typeof linksToEmbed === \'function\'){ linksToEmbed(\'a.Gallery2Link\'); } });</script>';
        } else
        if (!empty($obj->playVideoOnBrowserFullscreen)) {
            $js = '<script src="' . getURL('plugin/YouPHPFlix2/view/js/fullscreen.js') . '"></script>';
            $js .= '<script>$(function () { if(typeof linksToEmbed === \'function\'){ linksToEmbed(\'a.Gallery2Link\'); } });</script>';
            $js .= '<script src="' . getURL('plugin/Gallery2/fullscreen.js') . '"></script>';
            $js .= '<script>var playVideoOnBrowserFullscreen = 1;</script>';
        }
        $js .= '<script src="' . getURL('plugin/Gallery2/script.js') . '" type="text/javascript"></script>';
        return $js;
    }

    static function getThemes()
    {
        $obj = AVideoPlugin::getDataObject("Gallery2");
        if (empty($obj->allowSwitchTheme)) {
            return false;
        }
        $themes = getThemes();
        $selectedThemes = array();
        foreach ($themes as $value) {
            $name = ucfirst($value);
            eval('$t = $obj->SwitchThemeShow' . $name . ';');
            if (!empty($t)) {
                $l = '';
                eval('$l = $obj->SwitchThemeLabel' . $name . ';');
                $selectedThemes[] = array('name' => $value, 'label' => $l);
            }
        }
        return $selectedThemes;
    }

    static function getSectionsOrder()
    {
        $obj = AVideoPlugin::getObjectData('Gallery2');
        $sections = array();
        foreach ($obj as $key => $value) {
            if (preg_match('/(.*)Order$/', $key, $matches)) {
                $index = $value;
                while (isset($sections[$index])) {
                    $index++;
                }
                $sections[$index] = array('name' => $matches[1], 'active' => $obj->{$matches[1]});
            }
        }
        ksort($sections);
        return $sections;
    }

    public function getPluginMenu()
    {
        global $global;
        return '<button onclick="avideoModalIframeSmall(webSiteRootURL+\'plugin/Gallery2/view/sections.php\')" class="btn btn-primary btn-sm btn-xs btn-block"><i class="fas fa-sort-numeric-down"></i> ' . __('Sort Sections') . '</button>';
    }

    public static function getAddChannelToGallery2Button($users_id)
    {
        global $global, $config;
        $filePath = $global['systemRootPath'] . 'plugin/Gallery2/buttonChannelToGallery2.php';
        $varsArray = array('users_id' => $users_id);
        $button = getIncludeFileContent($filePath, $varsArray);
        return $button;
    }

    public static function setAddChannelToGallery2($users_id, $add)
    {
        global $global, $config;
        $users_id = intval($users_id);
        $add = intval($add);

        $obj = AVideoPlugin::getObjectData('Gallery2');

        $parameterName = "Channel_{$users_id}_";

        if (!empty($add)) {
            $obj->{$parameterName} = true;
            $obj->{"{$parameterName}CustomTitle"} = User::getNameIdentificationById($users_id);
            $obj->{"{$parameterName}RowCount"} = 12;
            $obj->{"{$parameterName}Order"} = 1;
        } else {
            unset($obj->{$parameterName});
            unset($obj->{"{$parameterName}CustomTitle"});
            unset($obj->{"{$parameterName}RowCount"});
            unset($obj->{"{$parameterName}Order"});
        }
        return AVideoPlugin::setObjectData('Gallery2', $obj);
    }

    public static function isChannelToGallery2($users_id)
    {
        $obj = AVideoPlugin::getObjectData('Gallery2');

        $parameterName = "Channel_{$users_id}_";

        return !empty($obj->{$parameterName});
    }

    static function getVideoDropdownMenu($videos_id)
    {
        global $global;
        $varsArray = array('videos_id' => $videos_id);
        $filePath = $global['systemRootPath'] . 'plugin/Gallery2/view/videoDropDownMenu.php';
        return getIncludeFileContent($filePath, $varsArray);
    }

    static function getContaierClass($addClass = '')
    {
        global $global, $objGallery2;
        if (!isset($objGallery2)) {
            $objGallery2 = AVideoPlugin::getObjectData('Gallery2');
        }

        $class = 'container Gallery2';
        if ($objGallery2->MainContainerFluid) {
            $class = 'container-fluid Gallery2';
        }

        return $class . " {$addClass}";
    }

    /**
     * @param string $parameters
     * This will return the configuration of the first page, also the URL to retreive the videos list from each section
     * @example {webSiteRootURL}plugin/API/{getOrSet}.json.php?APIPlugin={APIPlugin}&APIName={APIName}
     * @return \ApiObject
     */
    static function API_get_firstPage($parameters){
        global $global;
        $start = microtime(true);
        $cacheName = 'Gallery2_API_get_firstPage_'.md5(json_encode($parameters)).'_'.User::getId();
        $object = ObjectYPT::getCache($cacheName, 3600); // 1 hour
        if(empty($object)){
            $obj = AVideoPlugin::getObjectData("Gallery2");
            $sections = Gallery2::getSectionsOrder();
            $response = new stdClass();
            $response->sections = array();
            $countSections = 0;
            $countVideos = 0;
            foreach ($sections as $value) {
                if (empty($value['active'])) {
                    continue;
                }
                $countSections++;
                if (preg_match('/Channel_([0-9]+)_/', $value['name'], $matches)) {
                    $users_id = intval($matches[1]);
                    $title = User::_getUserChannelName($users_id);
                    $rowCount = getRowCount();
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&channelName={$title}";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'Suggested') {

                    $title = !empty($obj->SuggestedCustomTitle) ? $obj->SuggestedCustomTitle : __("Suggested");
                    $rowCount = intval($obj->SuggestedRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[suggested]=1";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'Trending') {
                    $title = !empty($obj->TrendingCustomTitle) ? $obj->TrendingCustomTitle : __("Trending");
                    $rowCount = intval($obj->TrendingRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[trending]=1";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'SortByName') {
                    $title = !empty($obj->SortByNameCustomTitle) ? $obj->SortByNameCustomTitle : __("Sort by name");
                    $rowCount = intval($obj->SortByNameRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[name]=asc";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'Shorts' && empty($_REQUEST['catName'])) {
                    $title = !empty($obj->ShortsCustomTitle) ? $obj->ShortsCustomTitle : __("Shorts");
                    $rowCount = intval($obj->ShortsRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[shorts]=1";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'DateAdded' && empty($_REQUEST['catName'])) {
                    $title = !empty($obj->DateAddedCustomTitle) ? $obj->DateAddedCustomTitle : __("Date added");
                    $rowCount = intval($obj->DateAddedRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[created]=desc";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'PrivateContent') {
                    /*
                    $title = !empty($obj->PrivateContentCustomTitle) ? $obj->PrivateContentCustomTitle : __("Private Content");
                    $rowCount = intval($obj->PrivateContentRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[created]=asc";
                    $response->sections[] = new Section($title,$endpoint,$rowCount);
                    createGallery2(!empty($obj->PrivateContentCustomTitle) ? $obj->PrivateContentCustomTitle : __("Private Content"), 'created', $obj->PrivateContentRowCount, 'privateContentOrder', __("Most"), __("Fewest"), $orderString, "DESC", true, "fas fa-lock");
                    */
                } else
                if ($value['name'] == 'MostWatched') {
                    $title = !empty($obj->MostWatchedCustomTitle) ? $obj->MostWatchedCustomTitle : __("Most watched");
                    $rowCount = intval($obj->MostWatchedRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[views_count]=desc";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'MostPopular') {
                    $title = !empty($obj->MostPopularCustomTitle) ? $obj->MostPopularCustomTitle : __("Most popular");
                    $rowCount = intval($obj->MostPopularRowCount);
                    $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&sort[likes]=desc";
                    $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                    $countVideos += $section->totalRows;
                    $response->sections[] = $section;
                } else
                if ($value['name'] == 'SubscribedChannels' && User::isLogged() && AVideoPlugin::isEnabledByName('VideoTags')) {
                    require_once $global['systemRootPath'] . 'objects/subscribe.php';
                    $users_id = User::getId();
                    $channels = Subscribe::getSubscribedChannels($users_id, $obj->SubscribedChannelsRowCount, 1);
                    foreach ($channels as $value2) {
                        $title = $value2['channelName'];
                        $rowCount = $obj->SubscribedChannelsRowCount;
                        $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&channelName={$title}&sort[created]=desc";
                        $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                        $countVideos += $section->totalRows;
                        $response->sections[] = $section;
                    }
                } else
                if ($value['name'] == 'SubscribedTags' && User::isLogged()) {
                    $users_id = User::getId();
                    $tags = Tags_subscriptions::getAllFromUsers_id($users_id);
                    if (!empty($tags)) {
                        foreach ($tags as $value2) {
                            $title = $value2['name'];
                            $rowCount = $obj->SubscribedTagsRowCount;
                            $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&tags_id={$value2['id']}&sort[created]=desc";
                            $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                            $countVideos += $section->totalRows;
                            $response->sections[] = $section;
                        }
                    }
                } else
                if ($value['name'] == 'Categories') {
                    $onlySuggested = $obj->CategoriesShowOnlySuggested;
                    cleanSearchVar();
                    $categories = Category::getAllCategories(false, true, $onlySuggested);
                    reloadSearchVar();
                    foreach ($categories as $value2) {
                        $title = $value2['name'];
                        $rowCount = $obj->CategoriesRowCount;
                        $endpoint = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=video&catName={$value2['clean_name']}&sort[created]=desc";
                        $section = new SectionFirstPage($value['name'], $title, $endpoint, $rowCount);
                        $countVideos += $section->totalRows;
                        $response->sections[] = $section;
                    }
                }
            }
            $response->countVideos = $countVideos;
            $response->countSections = $countSections;

            $finish = microtime(true)-$start;
            $response->responseTime = $finish;

            $object = new ApiObject("", false, $response);

            ObjectYPT::setCache($cacheName, $object);
        }else{
            $finish = microtime(true)-$start;
            $object->response->responseCacheTime = $finish;
        }

        return $object;
    }
}
JoshWho commented 3 months ago

I have a way to edit all files at once copy replace text. Tell me what I need to replace I thought I just had to change everything that says Gallery to Gallery2 like how wordpress does it.

JoshWho commented 3 months ago

This is the only file I am trying to modify image

which is mainArea.php

Edit from

<?php
saveRequestVars();
?>
<link href="<?php echo getURL('plugin/Gallery/style.css'); ?>" rel="stylesheet" type="text/css"/>
<div class="row mainArea">
    <?php
    if (!empty($currentCat)) {
        include $global['systemRootPath'] . 'plugin/Gallery/view/Category.php';
    }
    $obj = AVideoPlugin::getObjectData("Gallery");
    if ($obj->searchOnChannels) {
        echo '<!-- searchOnChannels -->';
        if (!empty($_REQUEST['search'])) {
            $users_id_array = VideoStatistic::getUsersIDFromChannelsWithMoreViews();
            $channels = Channel::getChannels(true, "u.id, '" . implode(",", $users_id_array) . "'");
            if (!empty($channels)) {
    ?>
                <div id="channelsResults" class="clear clearfix">
                    <h3 class="galleryTitle"> <i class="fas fa-user"></i> <?php echo __('Channels'); ?></h3>
                    <div class="row">
                        <?php
                        $search = $_REQUEST['search'];
                        clearSearch();
                        foreach ($channels as $value) {
                            echo '<div class="col-sm-12">';
                            User::getChannelPanel($value['id']);
                            echo '</div>';
                        }
                        reloadSearch();
                        ?>
                    </div>
                </div>
            <?php
                global $contentSearchFound;
                $contentSearchFound = true;
            }
        }
    }
    if (empty($_GET['search']) && !isInfiniteScroll()) {
        include $global['systemRootPath'] . 'plugin/Gallery/view/BigVideoLive.php';
    }
    //var_dump(!empty($video), debug_backtrace());exit;
    if (!empty($video)) {
        global $contentSearchFound;
        $contentSearchFound = true;
        $img_portrait = ($video['rotation'] === "90" || $video['rotation'] === "270") ? "img-portrait" : "";
        if (empty($_GET['search']) && !isInfiniteScroll()) {
            include $global['systemRootPath'] . 'plugin/Gallery/view/BigVideo.php';
        }
        echo '<center style="margin:5px;">' . getAdsLeaderBoardTop2() . '</center>';
        if (empty($_REQUEST['catName'])) {
            $objLive = AVideoPlugin::getDataObject('Live');
            if (empty($objLive->doNotShowLiveOnVideosList)) {
            ?>
                <!-- For Live Videos mainArea -->
                <div id="liveVideos" class="clear clearfix" style="display: none;">
                    <h3 class="galleryTitle text-danger"> <i class="fas fa-play-circle"></i> <?php echo __("Live"); ?></h3>
                    <div class="extraVideos"></div>
                </div>
                <!-- For Live Schedule Videos -->
                <div id="liveScheduleVideos" class="clear clearfix" style="display: none;">
                    <h3 class="galleryTitle"> <i class="far fa-calendar-alt"></i> <?php echo __($objLive->live_schedule_label); ?></h3>
                    <div class="extraVideos"></div>
                </div>
                <!-- For Live Videos End -->
                <?php
            }
        }
        echo AVideoPlugin::getGallerySection();

        $sections = Gallery::getSectionsOrder();
        $countSections = 0;
        if (!empty($_REQUEST['catName'])) {
            $currentCat = Category::getCategoryByName($_REQUEST['catName']);
            //createGallery($category['name'], 'created', $obj->CategoriesRowCount, 'dateAddedOrder', __("newest"), __("oldest"), $orderString, "DESC", !$obj->hidePrivateVideos, $category['iconClass'], true);

            include $global['systemRootPath'] . 'plugin/Gallery/view/mainAreaCategory.php';
        } else {
            //var_dump($sections);exit;
            //var_dump(getSearchVar());exit;
            foreach ($sections as $value) {
                if (empty($value['active'])) {
                    continue;
                }
                $countSections++;
                if (preg_match('/Channel_([0-9]+)_/', $value['name'], $matches) && empty($_GET['showOnly'])) {
                    $users_id = intval($matches[1]);
                    User::getChannelPanel($users_id);
                } else
                if ($value['name'] == 'Shorts' && empty($_GET['showOnly']) && AVideoPlugin::isEnabledByName('Shorts')) {
                    include $global['systemRootPath'] . 'plugin/Shorts/row.php';
                } else
                if ($value['name'] == 'Suggested') {
                    createGallery(!empty($obj->SuggestedCustomTitle) ? $obj->SuggestedCustomTitle : __("Suggested"), 'suggested', $obj->SuggestedRowCount, 'SuggestedOrder', "", "", $orderString, "ASC", !$obj->hidePrivateVideos, "fas fa-star", true);
                } else 
                if(empty(getSearchVar()) && empty($_GET['showOnly']) && $value['name'] == 'PlayLists'){
                    $objPl = AVideoPlugin::getDataObject('PlayLists');
                    $plRows = PlayList::getAllToShowOnFirstPage();
                    //var_dump(count($plRows));exit;
                    if (!empty($plRows)) {
                        $rowCount = getRowCount();
                        setRowCount($obj->PlayListsRowCount);
                        foreach ($plRows as $pl) {
                        ?>
                            <!-- For Playlist -->
                            <div class="clear clearfix">
                                <h3 class="galleryTitle">
                                    <a href="<?php echo "{$global['webSiteRootURL']}viewProgram/{$pl['id']}/" . urlencode($pl['name']); ?>">
                                        <i class="fas fa-list"></i> <?php echo __($pl['name']); ?>
                                    </a>
                                </h3>
                                <?php
                                $videos = PlayList::getAllFromPlaylistsID($pl['id']);
                                // need to add dechex because some times it return an negative value and make it fails on javascript playlists
                                ?>
                                <div class="gallerySectionContent">
                                    <?php
                                    $countCols = createGallerySection($videos);
                                    ?>
                                </div>
                            </div>
                        <?php
                        }
                        setRowCount($rowCount);
                    }
                }else 
                if ($value['name'] == 'Trending') {
                    createGallery(!empty($obj->TrendingCustomTitle) ? $obj->TrendingCustomTitle : __("Trending"), 'trending', $obj->TrendingRowCount, 'TrendingOrder', "zyx", "abc", $orderString, "ASC", !$obj->hidePrivateVideos, "fas fa-chart-line", true);
                } else
                if ($value['name'] == 'SortByName') {
                    createGallery(!empty($obj->SortByNameCustomTitle) ? $obj->SortByNameCustomTitle : __("Sort by name"), 'title', $obj->SortByNameRowCount, 'sortByNameOrder', "zyx", "abc", $orderString, "ASC", !$obj->hidePrivateVideos, "fas fa-font", true);
                } else
                if ($value['name'] == 'DateAdded' && empty($_REQUEST['catName'])) {
                    createGallery(!empty($obj->DateAddedCustomTitle) ? $obj->DateAddedCustomTitle : __("Date added"), 'created', $obj->DateAddedRowCount, 'dateAddedOrder', __("newest"), __("oldest"), $orderString, "DESC", !$obj->hidePrivateVideos, "far fa-calendar-alt", true);
                } else
                if ($value['name'] == 'PrivateContent') {
                    createGallery(!empty($obj->PrivateContentCustomTitle) ? $obj->PrivateContentCustomTitle : __("Private Content"), 'created', $obj->PrivateContentRowCount, 'privateContentOrder', __("Most"), __("Fewest"), $orderString, "DESC", true, "fas fa-lock", true);
                } else
                if ($value['name'] == 'MostWatched') {
                    createGallery(!empty($obj->MostWatchedCustomTitle) ? $obj->MostWatchedCustomTitle : __("Most watched"), 'views_count', $obj->MostWatchedRowCount, 'mostWatchedOrder', __("Most"), __("Fewest"), $orderString, "DESC", !$obj->hidePrivateVideos, "far fa-eye", true);
                } else
                if ($value['name'] == 'MostPopular') {
                    createGallery(!empty($obj->MostPopularCustomTitle) ? $obj->MostPopularCustomTitle : __("Most popular"), 'likes', $obj->MostPopularRowCount, 'mostPopularOrder', __("Most"), __("Fewest"), $orderString, "DESC", !$obj->hidePrivateVideos, "fas fa-fire", true);
                } else
                if ($value['name'] == 'SubscribedChannels' && User::isLogged() && empty($_GET['showOnly'])) {
                    include $global['systemRootPath'] . 'plugin/Gallery/view/mainAreaChannels.php';
                } else
                if ($value['name'] == 'SubscribedTags' && User::isLogged() && empty($_GET['showOnly'])) {
                    include $global['systemRootPath'] . 'plugin/Gallery/view/mainAreaTags.php';
                } else
                if ($value['name'] == 'Categories' && empty($_GET['showOnly'])) {
                    if (empty($currentCat) && !empty(getSearchVar())) {
                        $onlySuggested = $obj->CategoriesShowOnlySuggested;
                        cleanSearchVar();
                        $categories = Category::getAllCategories(false, true, $onlySuggested);
                        reloadSearchVar();
                        foreach ($categories as $value) {
                            $currentCat = $value['clean_name'];
                            include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategory.php';
                        }
                    } else {
                        include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategory.php';
                    }
                }
            }
            if (empty($countSections) && !empty($_REQUEST['catName'])) {
                $category = Category::getCategoryByName($_REQUEST['catName']);
                createGallery($category['name'], 'created', $obj->CategoriesRowCount, 'dateAddedOrder', __("newest"), __("oldest"), $orderString, "DESC", !$obj->hidePrivateVideos, $category['iconClass'], true);
            }
        }
    } else {
        echo '<!-- ' . basename(__FILE__) . ' modeGalleryCategoryLive -->';
        include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategoryLive.php';
        $ob = _ob_get_clean();
        _ob_start();
        echo AVideoPlugin::getGallerySection();
        $ob2 = _ob_get_clean();
        echo $ob;
        global $contentSearchFound;
        if (empty($contentSearchFound) && empty($ob2)) {
            //$contentSearchFound = false;
        } else {
            $contentSearchFound = true;
        }
    }

    global $contentSearchFound;
    if (empty($contentSearchFound)) {
        //var_dump(debug_backtrace(), $debugLastGetVideoSQL);exit;
        _session_start();
        unset($_SESSION['type']);
        ?>
        <div class="alert alert-warning">
            <h1>
                <i class="fa-solid fa-video"></i>
                <?php echo __("Warning"); ?>!
            </h1>
            <!-- <?php echo basename(__FILE__); ?> -->
            <?php echo __("It seems that your search did not return any results"); ?>.
            <br>
            <?php echo __("This could be due to the enabled filters"); ?>:
        </div>
    <?php
        _error_log('contentSearchFound NOT FOUND ' . json_encode(debug_backtrace()));
        _error_log('contentSearchFound NOT FOUND LAST SQL ' . $debugLastGetVideoSQL);
        _error_log('contentSearchFound NOT FOUND LAST TOTAL SQL ' . $lastGetTotalVideos);
        include $global['systemRootPath'] . 'view/include/notfound.php';
    }
    ?>
</div>
<?php
restoreRequestVars();
?>

Line 171

    } else {
        echo '<!-- ' . basename(__FILE__) . ' modeGalleryCategoryLive -->';
        include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategoryLive.php';
        $ob = _ob_get_clean();
        _ob_start();
        echo AVideoPlugin::getGallerySection();
        $ob2 = _ob_get_clean();
        echo $ob;
        global $contentSearchFound;
        if (empty($contentSearchFound) && empty($ob2)) {
            //$contentSearchFound = false;
        } else {
            $contentSearchFound = true;
        }
    }

move to the top to line 38

To this

<?php
saveRequestVars();
?>
<link href="<?php echo getURL('plugin/Gallery/style.css'); ?>" rel="stylesheet" type="text/css"/>
<div class="row mainArea">
    <?php
    if (!empty($currentCat)) {
        include $global['systemRootPath'] . 'plugin/Gallery/view/Category.php';
    }
    $obj = AVideoPlugin::getObjectData("Gallery");
    if ($obj->searchOnChannels) {
        echo '<!-- searchOnChannels -->';
        if (!empty($_REQUEST['search'])) {
            $users_id_array = VideoStatistic::getUsersIDFromChannelsWithMoreViews();
            $channels = Channel::getChannels(true, "u.id, '" . implode(",", $users_id_array) . "'");
            if (!empty($channels)) {
    ?>
                <div id="channelsResults" class="clear clearfix">
                    <h3 class="galleryTitle"> <i class="fas fa-user"></i> <?php echo __('Channels'); ?></h3>
                    <div class="row">
                        <?php
                        $search = $_REQUEST['search'];
                        clearSearch();
                        foreach ($channels as $value) {
                            echo '<div class="col-sm-12">';
                            User::getChannelPanel($value['id']);
                            echo '</div>';
                        }
                        reloadSearch();
                        ?>
                    </div>
                </div>
            <?php
                global $contentSearchFound;
                $contentSearchFound = true;
            }
        }
    } else {
        echo '<!-- ' . basename(__FILE__) . ' modeGalleryCategoryLive -->';
        include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategoryLive.php';
        $ob = _ob_get_clean();
        _ob_start();
        echo AVideoPlugin::getGallerySection();
        $ob2 = _ob_get_clean();
        echo $ob;
        global $contentSearchFound;
        if (empty($contentSearchFound) && empty($ob2)) {
            //$contentSearchFound = false;
        } else {
            $contentSearchFound = true;
        }
    }

    }
    if (empty($_GET['search']) && !isInfiniteScroll()) {
        include $global['systemRootPath'] . 'plugin/Gallery/view/BigVideoLive.php';
    }
    //var_dump(!empty($video), debug_backtrace());exit;
    if (!empty($video)) {
        global $contentSearchFound;
        $contentSearchFound = true;
        $img_portrait = ($video['rotation'] === "90" || $video['rotation'] === "270") ? "img-portrait" : "";
        if (empty($_GET['search']) && !isInfiniteScroll()) {
            include $global['systemRootPath'] . 'plugin/Gallery/view/BigVideo.php';
        }
        echo '<center style="margin:5px;">' . getAdsLeaderBoardTop2() . '</center>';
        if (empty($_REQUEST['catName'])) {
            $objLive = AVideoPlugin::getDataObject('Live');
            if (empty($objLive->doNotShowLiveOnVideosList)) {
            ?>
                <!-- For Live Videos mainArea -->
                <div id="liveVideos" class="clear clearfix" style="display: none;">
                    <h3 class="galleryTitle text-danger"> <i class="fas fa-play-circle"></i> <?php echo __("Live"); ?></h3>
                    <div class="extraVideos"></div>
                </div>
                <!-- For Live Schedule Videos -->
                <div id="liveScheduleVideos" class="clear clearfix" style="display: none;">
                    <h3 class="galleryTitle"> <i class="far fa-calendar-alt"></i> <?php echo __($objLive->live_schedule_label); ?></h3>
                    <div class="extraVideos"></div>
                </div>
                <!-- For Live Videos End -->
                <?php
            }
        }
        echo AVideoPlugin::getGallerySection();

        $sections = Gallery::getSectionsOrder();
        $countSections = 0;
        if (!empty($_REQUEST['catName'])) {
            $currentCat = Category::getCategoryByName($_REQUEST['catName']);
            //createGallery($category['name'], 'created', $obj->CategoriesRowCount, 'dateAddedOrder', __("newest"), __("oldest"), $orderString, "DESC", !$obj->hidePrivateVideos, $category['iconClass'], true);

            include $global['systemRootPath'] . 'plugin/Gallery/view/mainAreaCategory.php';
        } else {
            //var_dump($sections);exit;
            //var_dump(getSearchVar());exit;
            foreach ($sections as $value) {
                if (empty($value['active'])) {
                    continue;
                }
                $countSections++;
                if (preg_match('/Channel_([0-9]+)_/', $value['name'], $matches) && empty($_GET['showOnly'])) {
                    $users_id = intval($matches[1]);
                    User::getChannelPanel($users_id);
                } else
                if ($value['name'] == 'Shorts' && empty($_GET['showOnly']) && AVideoPlugin::isEnabledByName('Shorts')) {
                    include $global['systemRootPath'] . 'plugin/Shorts/row.php';
                } else
                if ($value['name'] == 'Suggested') {
                    createGallery(!empty($obj->SuggestedCustomTitle) ? $obj->SuggestedCustomTitle : __("Suggested"), 'suggested', $obj->SuggestedRowCount, 'SuggestedOrder', "", "", $orderString, "ASC", !$obj->hidePrivateVideos, "fas fa-star", true);
                } else 
                if(empty(getSearchVar()) && empty($_GET['showOnly']) && $value['name'] == 'PlayLists'){
                    $objPl = AVideoPlugin::getDataObject('PlayLists');
                    $plRows = PlayList::getAllToShowOnFirstPage();
                    //var_dump(count($plRows));exit;
                    if (!empty($plRows)) {
                        $rowCount = getRowCount();
                        setRowCount($obj->PlayListsRowCount);
                        foreach ($plRows as $pl) {
                        ?>
                            <!-- For Playlist -->
                            <div class="clear clearfix">
                                <h3 class="galleryTitle">
                                    <a href="<?php echo "{$global['webSiteRootURL']}viewProgram/{$pl['id']}/" . urlencode($pl['name']); ?>">
                                        <i class="fas fa-list"></i> <?php echo __($pl['name']); ?>
                                    </a>
                                </h3>
                                <?php
                                $videos = PlayList::getAllFromPlaylistsID($pl['id']);
                                // need to add dechex because some times it return an negative value and make it fails on javascript playlists
                                ?>
                                <div class="gallerySectionContent">
                                    <?php
                                    $countCols = createGallerySection($videos);
                                    ?>
                                </div>
                            </div>
                        <?php
                        }
                        setRowCount($rowCount);
                    }
                }else 
                if ($value['name'] == 'Trending') {
                    createGallery(!empty($obj->TrendingCustomTitle) ? $obj->TrendingCustomTitle : __("Trending"), 'trending', $obj->TrendingRowCount, 'TrendingOrder', "zyx", "abc", $orderString, "ASC", !$obj->hidePrivateVideos, "fas fa-chart-line", true);
                } else
                if ($value['name'] == 'SortByName') {
                    createGallery(!empty($obj->SortByNameCustomTitle) ? $obj->SortByNameCustomTitle : __("Sort by name"), 'title', $obj->SortByNameRowCount, 'sortByNameOrder', "zyx", "abc", $orderString, "ASC", !$obj->hidePrivateVideos, "fas fa-font", true);
                } else
                if ($value['name'] == 'DateAdded' && empty($_REQUEST['catName'])) {
                    createGallery(!empty($obj->DateAddedCustomTitle) ? $obj->DateAddedCustomTitle : __("Date added"), 'created', $obj->DateAddedRowCount, 'dateAddedOrder', __("newest"), __("oldest"), $orderString, "DESC", !$obj->hidePrivateVideos, "far fa-calendar-alt", true);
                } else
                if ($value['name'] == 'PrivateContent') {
                    createGallery(!empty($obj->PrivateContentCustomTitle) ? $obj->PrivateContentCustomTitle : __("Private Content"), 'created', $obj->PrivateContentRowCount, 'privateContentOrder', __("Most"), __("Fewest"), $orderString, "DESC", true, "fas fa-lock", true);
                } else
                if ($value['name'] == 'MostWatched') {
                    createGallery(!empty($obj->MostWatchedCustomTitle) ? $obj->MostWatchedCustomTitle : __("Most watched"), 'views_count', $obj->MostWatchedRowCount, 'mostWatchedOrder', __("Most"), __("Fewest"), $orderString, "DESC", !$obj->hidePrivateVideos, "far fa-eye", true);
                } else
                if ($value['name'] == 'MostPopular') {
                    createGallery(!empty($obj->MostPopularCustomTitle) ? $obj->MostPopularCustomTitle : __("Most popular"), 'likes', $obj->MostPopularRowCount, 'mostPopularOrder', __("Most"), __("Fewest"), $orderString, "DESC", !$obj->hidePrivateVideos, "fas fa-fire", true);
                } else
                if ($value['name'] == 'SubscribedChannels' && User::isLogged() && empty($_GET['showOnly'])) {
                    include $global['systemRootPath'] . 'plugin/Gallery/view/mainAreaChannels.php';
                } else
                if ($value['name'] == 'SubscribedTags' && User::isLogged() && empty($_GET['showOnly'])) {
                    include $global['systemRootPath'] . 'plugin/Gallery/view/mainAreaTags.php';
                } else
                if ($value['name'] == 'Categories' && empty($_GET['showOnly'])) {
                    if (empty($currentCat) && !empty(getSearchVar())) {
                        $onlySuggested = $obj->CategoriesShowOnlySuggested;
                        cleanSearchVar();
                        $categories = Category::getAllCategories(false, true, $onlySuggested);
                        reloadSearchVar();
                        foreach ($categories as $value) {
                            $currentCat = $value['clean_name'];
                            include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategory.php';
                        }
                    } else {
                        include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategory.php';
                    }
                }
            }
            if (empty($countSections) && !empty($_REQUEST['catName'])) {
                $category = Category::getCategoryByName($_REQUEST['catName']);
                createGallery($category['name'], 'created', $obj->CategoriesRowCount, 'dateAddedOrder', __("newest"), __("oldest"), $orderString, "DESC", !$obj->hidePrivateVideos, $category['iconClass'], true);
            }
        }
    global $contentSearchFound;
    if (empty($contentSearchFound)) {
        //var_dump(debug_backtrace(), $debugLastGetVideoSQL);exit;
        _session_start();
        unset($_SESSION['type']);
        ?>
        <div class="alert alert-warning">
            <h1>
                <i class="fa-solid fa-video"></i>
                <?php echo __("Warning"); ?>!
            </h1>
            <!-- <?php echo basename(__FILE__); ?> -->
            <?php echo __("It seems that your search did not return any results"); ?>.
            <br>
            <?php echo __("This could be due to the enabled filters"); ?>:
        </div>
    <?php
        _error_log('contentSearchFound NOT FOUND ' . json_encode(debug_backtrace()));
        _error_log('contentSearchFound NOT FOUND LAST SQL ' . $debugLastGetVideoSQL);
        _error_log('contentSearchFound NOT FOUND LAST TOTAL SQL ' . $lastGetTotalVideos);
        include $global['systemRootPath'] . 'view/include/notfound.php';
    }
    ?>
</div>
<?php
restoreRequestVars();
?>
DanielnetoDotCom commented 3 months ago

Sorry I cannnot help you to code or understand the code.

But Gallery.php should also be called Gallery2.php

JoshWho commented 3 months ago

I can modify this on the main gallery and it works. but every git pull will erase it.

I just need the live code block on line

Line 171

    } else {
        echo '<!-- ' . basename(__FILE__) . ' modeGalleryCategoryLive -->';
        include $global['systemRootPath'] . 'plugin/Gallery/view/modeGalleryCategoryLive.php';
        $ob = _ob_get_clean();
        _ob_start();
        echo AVideoPlugin::getGallerySection();
        $ob2 = _ob_get_clean();
        echo $ob;
        global $contentSearchFound;
        if (empty($contentSearchFound) && empty($ob2)) {
            //$contentSearchFound = false;
        } else {
            $contentSearchFound = true;
        }
    }

move to the top to line 38 in mainArea.php

JoshWho commented 3 months ago

I wish you had a Child Theme option built in this

JoshWho commented 3 months ago

That really sucks I have to make a whole theme just for this 1 modification. Little things like this is why it is so hard to get others to use this Avideo script. I am trying everything to keep using this for everything. I am trying my hardest for this to work.

I am trying to please the owner of this site with this and it will make you a continuous flow of money for the next few years and little things like this is making it very challenging.

DanielnetoDotCom commented 3 months ago

Sorry but is not easy make design modifications , specially move things around

JoshWho commented 3 months ago

I did it already just need it to be global so updates do not erase it https://github.com/WWBN/AVideo/issues/9332#issuecomment-2295051690

JoshWho commented 3 months ago

Anyway PLEASE you can just generate me a clone template of the theme that will work? I will do the modifying it, I just need it to work.

I was going to gut the deprecated theme Youtube and add all this to it but I think I will be in the same situation do to all the linking back to specific names instead of it just being dynamic

DanielnetoDotCom commented 3 months ago

you must use your own custom Gallery plugin, and also be aware if something change in the Gallery you will not be able to follow the updates.

another option you can hire me to add the option to move the live to the top

JoshWho commented 3 months ago

you must use your own custom Gallery plugin, and also be aware if something change in the Gallery you will not be able to follow the updates.

another option you can hire me to add the option to move the live to the top

That sounds like a more easier option. I will send a email for quote. Just have to talk with the team first.