Plugin Directory

Changeset 2963306


Ignore:
Timestamp:
09/05/2023 10:54:27 PM (2 years ago)
Author:
deambulando
Message:

tagging version 2.1

Location:
better-video-playlist
Files:
8 added
3 edited
4 copied

Legend:

Unmodified
Added
Removed
  • better-video-playlist/tags/2.1/README.TXT

    r2959725 r2963306  
    55Requires at least: 6.0
    66Tested up to: 6.3
    7 Stable tag: 2.0.4
     7Stable tag: 2.1
    88Requires PHP: 7.4
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1111
    12 Improves video capabilities for wordpress, stores progress and adds video playlist features.
    13 
     12Improves WordPress Video Experience by adding playlist, resume video and a lot more!
    1413
    1514== Description ==
    1615
    17 Super fast video player and playlist player using native HTML5 video player and jQuery. Uses browser local storage for most features.
     16**Elevate Your WordPress Video Experience!**
    1817
    19 If user is logged in we store video position in the database. So even if changes browser will save the progress.
     18The Better Video & Playlist Plugin is designed to enhance the video capabilities of your WordPress website while adding a sophisticated video playlist feature. This plugin ensures that your site's visitors enjoy a seamless and engaging video-watching experience.
    2019
    21 Works in pages, posts, widgets or any place at your site.
     20**Key Features:**
    2221
    23 = Features =
     22- **Resume Video Playback**: Never lose progress – our plugin remembers where you left off.
     23- **Video Progress Storage**: Store video progress in the WordPress database and local browser storage.
     24- **Customized Start Time**: Start your videos at specific times using the `?t=SECONDS` parameter (e.g., `?t=120` starts at 2 minutes).
     25- **Video Playlists**: Create and manage video playlists effortlessly using block editor.
     26- **Autoplay Next Video**: Keep viewers engaged with automatic playback of the next video.
     27- **Emoji Customization**: Add a personal touch with custom video emojis.
     28- **Background Color**: Tailor the video player's background color to match your site's aesthetics.
    2429
    25 - Resume video from last position. Saves progress in DB and browser storage.
    26 - On pause or window close, stores progress
    27 -  Start playing video at custom time using ?t=SECONDS ex ?t=120 will start at 2 minutes
     30**Why Choose Better Video & Playlist?**
    2831
    29 **Playlist Features**
    30 - Create playlist video from a HTML5 list or JS array
    31 - Resume on last played video
    32 - Autoplay next video on video end
    33 - Mark video as played
    34 - Start playing from video via url parameter using ?start_video=ID_VIDEO
    35 - Stored in user browser storage and at WordPress Database
    36 
     32- **User-Friendly**: Seamlessly integrate advanced video features into your WordPress site.
     33- **Progress Tracking**: Never make viewers start from scratch; they can pick up right where they left off.
     34- **Playlist Management**: Create and organize video playlists with ease.
     35- **Community Support**: Join a community of users benefiting from this plugin's capabilities.
    3736
    3837== Installation ==
    3938
    40 Through WordPress admin:
     39**Via WordPress Admin:**
    4140
    42 1. Go to Plugins -> Add New
    43 2. Search for "Better Video"
    44 3. Install the plugin
    45 4. Activate it
     411. Go to **Plugins** -> **Add New**.
     422. Search for "Better Video & Playlist."
     433. Click **Install Now**.
     444. Activate the plugin.
    4645
    47 Through FTP:
     46**Via FTP:**
    4847
    49 1. Download the plugin
    50 2. Unzip .zip and upload the folder to the `/wp-content/plugins/` directory
    51 3. Activate the plugin through the 'Plugins' menu in WordPress
    52 
     481. Download the plugin.
     492. Unzip the .zip file and upload the folder to `/wp-content/plugins/`.
     503. Activate the plugin in the **Plugins** menu of WordPress.
    5351
    5452== Frequently Asked Questions ==
    5553
    56 = How to use? =
     54**How to Use?**
    5755
    58 To enable the video features just add a video from the post editor or add HTML video tag. You can have as many video tags as you want.
     56To enable the video features, add a video from the post editor or use the HTML video tag. You can include as many video tags as needed.
    5957
    60 = Video Play list =
     58**Creating Video Playlists**
    6159
    62 You can create a list on your editor and then in the side panel in advanced, anchor set it to "bvideo_playlist".
     60You can create a video playlist within your editor by using the block.
    6361
    64 Also you can edit the HTML and create List with id = bvideo_playlist:
     62Or by using the advanced settings panel and setting it to "bvideo_playlist." Alternatively, you can create a list in your HTML with the id "bvideo_playlist."
    6563
    66     <ol id="bvideo_playlist">
    67         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/earth_night_rotate_1080.mov">Animation: Rotating Earth at Night</a></li>
    68         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/rbsp_launch_1080p.mp4">Radiation Belt Storm Probes Launch</a></li>
    69         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/curiosity_lands.mov">Dropping in on Mars in High-Res</a></li>
    70         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/GRAIL_launch_1080.mov">GRAIL Launches on Mission to Moon</a></li>
    71         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/HLV_Launch_anim.mov">Space Launch System Animation</a></li>
    72     </ol>
     64Here's an example HTML playlist:
    7365
     66```html
     67<ol id="bvideo_playlist">
     68    <li><a href="video1.mp4">Video 1</a></li>
     69    <li><a href="video2.mp4">Video 2</a></li>
     70    <li><a href="video3.mp4">Video 3</a></li>
     71</ol>
     72```
    7473
    75 You can also add in your HTML/JS file a playlist array and will create your list magically, the size field it’s optional:
     74You can also create a playlist using a JavaScript array:
    7675
    77     <script>
    78     var video_playlist = [
    79         {
    80             "name": "Animation: Rotating Earth at Night",
    81             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/earth_night_rotate_1080.mov",
    82             "size": 55000000,
    83         },
    84         {
    85             "name": "Radiation Belt Storm Probes Launch",
    86             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/rbsp_launch_1080p.mp4",
    87             "size": 475000000,
    88         },
    89         {
    90             "name": "Dropping in on Mars in High-Res",
    91             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/curiosity_lands.mov",
    92             "size": 105000000,
    93         },
    94         {
    95             "name": "GRAIL Launches on Mission to Moon",
    96             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/GRAIL_launch_1080.mov",
    97             "size": 1113000000,
    98         },
    99         {
    100             "name": "Space Launch System Animation",
    101             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/HLV_Launch_anim.mov",
    102             "size": 642570000,
    103         },
    104    
    105     ];
    106     </script>
     76```javascript
     77<script>
     78var video_playlist = [
     79    {
     80        "name": "Video 1",
     81        "link": "video1.mp4",
     82        "size": 55000000
     83    },
     84    {
     85        "name": "Video 2",
     86        "link": "video2.mp4",
     87        "size": 475000000
     88    },
     89    {
     90        "name": "Video 3",
     91        "link": "video3.mp4",
     92        "size": 105000000
     93    }
     94];
     95</script>
     96```
    10797
    108 To add the JS to your post/page you can use a plugin like [this one](https://wordpress.org/plugins/header-and-footer-scripts/).
    109 
     98To add the JavaScript to your post/page, consider using a plugin like [this one](https://wordpress.org/plugins/header-and-footer-scripts/).
    11099
    111100== Screenshots ==
    112 1. Video player
    113 2. Play list player
    114101
    115 == Upgrade Notice ==
    116 None.
     1021. Video Player
     1032. Playlist Player
    117104
    118 == Changelog ==
     105== Upgrade History ==
    119106
     107= Version 2.1 =
     108- Major jQuery and PHP code refactor
     109- Improved method for tracking played videos
     110- New admin panel with customizable settings
    120111
    121 = 2.0.4 =
    122 * Improved description and FAQ's
     112= Version 2.0.4 =
     113- Enhanced descriptions and FAQs
    123114
    124 = 2.0.3 =
    125 * WP 6.3 tested
     115= Version 2.0.3 =
     116- Tested for WordPress 6.3 compatibility
    126117
    127 = 2.0.2 =
    128 * smooth scroll to video
     118= Version 2.0.2 =
     119- Added smooth scroll to video
    129120
    130 = 2.0.1 =
    131 * ajax stores video time for logged user
     121= Version 2.0.1 =
     122- Implemented AJAX for storing video time for logged-in users
    132123
    133 = 1.0 =
    134 * Initial version
     124= Version 1.0 =
     125- Initial release
  • better-video-playlist/tags/2.1/better-video.php

    r2959725 r2963306  
    11<?php
    22/**
    3     * Plugin Name: Better Video & Playlist
    4     * Plugin URI: https://garridodiaz.com/better-video-plugin-for-wordpress/
    5     * Description: Improves video capabilities for wordpress and adds video playlist features.
    6     * Version: 2.0.4
    7     * Author: Chema
    8     * Author URI: https://garridodiaz.com
    9     * License: GPL2
    10 */
    11 
    12 add_action( 'wp_enqueue_scripts', 'bbpl_assets');
    13 add_action( 'wp_ajax_bbpl_store_video_time', 'bbpl_store_video_time' );
    14 add_action( 'wp_ajax_bbpl_get_video_time', 'bbpl_get_video_time' );
    15 
    16 /* enqueue scripts and style from parent theme */       
    17 function bbpl_assets() {
    18     wp_enqueue_script( 'better-video', plugin_dir_url( __FILE__ ) . 'js/better-video.js', array('jquery'), '2.0.4', true );
    19 
    20     wp_localize_script(
    21         'better-video',
    22         'my_ajax_obj',
    23         array(
    24             'ajax_url' => admin_url( 'admin-ajax.php' ),
    25             'nonce'    => wp_create_nonce( 'better-video' ),
    26         )
    27     );
     3 * Plugin Name: Better Video & Playlist
     4 * Plugin URI: https://garridodiaz.com/better-video-plugin-for-wordpress/
     5 * Description: Improves video capabilities for WordPress and adds video playlist features.
     6 * Version: 2.1
     7 * Author: Chema
     8 * Author URI: https://garridodiaz.com
     9 * License: GPL2
     10 */
     11
     12if (!defined('ABSPATH')) exit; // Exit if accessed directly
     13
     14class BetterVideoPlaylistPlugin
     15{
     16    const MAIN_FILE = __FILE__;
     17
     18    public function __construct()
     19    {
     20        // Initialize the plugin by adding hooks and actions
     21        add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']);
     22        add_action('wp_ajax_bbpl_store_video_time', [$this, 'storeVideoTime']);
     23        add_action('wp_ajax_bbpl_get_video_time', [$this, 'getVideoTime']);
     24        add_action('admin_menu', [$this, 'addAdminMenu']);
     25        add_action('admin_init', [$this, 'registerSettings']);
     26        add_action('admin_enqueue_scripts', [$this, 'enqueueAdminScripts']);
     27        add_action('admin_notices', [$this, 'displayDonationMessage']);
     28        add_action('admin_head', [$this, 'addDonationMessageJS']);
     29        add_filter('plugin_row_meta', [$this, 'addPluginRowMeta'], 10, 2);
     30        add_action('admin_init', [$this, 'setupSettingsFields']);
     31    }
     32
     33    /**
     34     * Enqueue assets (scripts and styles) for the plugin.
     35     */
     36    public function enqueueAssets()
     37    {
     38        // Enqueue scripts and localize for better-video.js
     39        wp_enqueue_script('better-video', plugin_dir_url(__FILE__) . 'js/better-video.js', array('jquery'), '2.1', true);
     40
     41        wp_localize_script(
     42            'better-video',
     43            'betterVideo_ajax',
     44            array(
     45                'ajax_url' => admin_url('admin-ajax.php'),
     46                'nonce' => wp_create_nonce('better-video'),
     47            )
     48        );
     49
     50        $bbpl_settings = array(
     51            'playedVideoEmoji' => get_option('bbpl_played_video_emoji', __('✔', 'bbpl-textdomain')),
     52            'playingEmoji' => get_option('bbpl_playing_emoji', __('▶️', 'bbpl-textdomain')),
     53            'downloadEmoji' => get_option('bbpl_download_emoji', __('💾', 'bbpl-textdomain')),
     54            'playingBackgroundColor' => get_option('bbpl_playing_background_color', '#FFFF00'),
     55            'autoplay' => get_option('bbpl_autoplay', true),
     56        );
     57        wp_localize_script('better-video', 'bbplSettings', $bbpl_settings);
     58    }
     59
     60    /**
     61     * Handle AJAX request for storing video time.
     62     *
     63     * @return bool JSON response indicating success or failure.
     64     */
     65    public function storeVideoTime()
     66    {
     67        // Handle the AJAX request for storing video time
     68        check_ajax_referer('better-video');
     69        $return = false;
     70
     71        if (is_user_logged_in()) {
     72            global $current_user;
     73            $time = sanitize_text_field($_POST['time']);
     74            $video = sanitize_url($_POST['video']);
     75
     76            if (is_numeric($time) && wp_http_validate_url($video)) {
     77                $return = update_user_meta($current_user->ID, 'bvideo-' . md5($video), $time);
     78            }
     79        }
     80
     81        wp_send_json($return);
     82    }
     83
     84    /**
     85     * Handle AJAX request for getting video time.
     86     *
     87     * @return mixed JSON response containing the video time or 0.
     88     */
     89    public function getVideoTime()
     90    {
     91        // Handle the AJAX request for getting video time
     92        check_ajax_referer('better-video');
     93        $return = 0;
     94
     95        if (is_user_logged_in()) {
     96            global $current_user;
     97            $video = sanitize_url($_POST['video']);
     98            if (wp_http_validate_url($video)) {
     99                $return = get_user_meta($current_user->ID, 'bvideo-' . md5($video));
     100            }
     101        }
     102
     103        wp_send_json($return);
     104    }
     105
     106    /**
     107     * Add the admin menu for plugin settings.
     108     */
     109    public function addAdminMenu()
     110    {
     111        // Add the admin menu for settings
     112        add_submenu_page(
     113            'options-general.php',
     114            __('Better Video & Playlist Settings', 'bbpl-textdomain'),
     115            __('Video Settings', 'bbpl-textdomain'),
     116            'manage_options',
     117            'bbpl-settings',
     118            [$this, 'renderSettingsPage']
     119        );
     120    }
     121
     122    /**
     123     * Register plugin settings.
     124     */
     125    public function registerSettings()
     126    {
     127        // Register plugin settings
     128        register_setting('bbpl_settings_group', 'bbpl_played_video_emoji');
     129        register_setting('bbpl_settings_group', 'bbpl_playing_emoji');
     130        register_setting('bbpl_settings_group', 'bbpl_download_emoji');
     131        register_setting('bbpl_settings_group', 'bbpl_playing_background_color');
     132        register_setting('bbpl_settings_group', 'bbpl_autoplay');
     133    }
     134
     135    /**
     136     * Enqueue scripts for the admin page.
     137     *
     138     * @param string $hook The current admin page hook.
     139     */
     140    public function enqueueAdminScripts($hook)
     141    {
     142        // Enqueue scripts for the admin page
     143        if ($hook === 'settings_page_bbpl-settings') {
     144            wp_enqueue_script('bbpl-admin', plugin_dir_url(__FILE__) . 'js/admin-better-video.js', array('jquery', 'wp-color-picker'), '1.0', true);
     145        }
     146    }
     147
     148    /**
     149     * Display a donation message in the WordPress admin.
     150     */
     151    public function displayDonationMessage()
     152    {
     153        // Display the donation message
     154        if ((isset($_GET['page']) && $_GET['page'] === 'bbpl-settings') && !isset($_COOKIE['donation_message_closed'])) {
     155            echo '<div id="donation-message" class="notice notice-info is-dismissible" style="background-color: #f5f5f5; border-left: 4px solid #0073aa; padding: 10px;">
     156                <p style="font-size: 16px;">Enjoy using our plugin? Consider <a href="https://paypal.me/chema/10EUR" target="_blank" id="donate-link">making a donation</a> to support our work! THANKS!</p>
     157                </div>';
     158        }
     159    }
     160
     161    /**
     162     * Add JavaScript for handling the donation message.
     163     */
     164    public function addDonationMessageJS()
     165    {
     166        // Add JavaScript for handling the donation message
     167        if (!isset($_COOKIE['donation_message_closed'])) {
     168            ?>
     169            <script type="text/javascript">
     170                jQuery(document).ready(function ($) {
     171
     172                    $('#donate-link').click(function () {
     173                        $('#donation-message').remove();
     174                        var expirationDate = new Date();
     175                        expirationDate.setDate(expirationDate.getDate() + 30); // Expires in 30 days
     176                        document.cookie = 'donation_message_closed=true; expires=' + expirationDate.toUTCString() + '; path=/';
     177
     178                    });
     179                });
     180            </script>
     181            <?php
     182        }
     183    }
     184
     185    /**
     186     * Setup settings fields and sections for the plugin.
     187     */
     188    public function setupSettingsFields()
     189    {
     190        // Setup settings fields and sections
     191        add_settings_section('bbpl_general_section', __('General Settings', 'bbpl-textdomain'), [$this, 'renderGeneralSection'], 'bbpl-settings');
     192
     193        // Define custom sanitize callbacks for each field
     194        $sanitize_callbacks = [
     195            'bbpl_played_video_emoji' => 'sanitize_text_field',
     196            'bbpl_playing_emoji' => 'sanitize_text_field',
     197            'bbpl_download_emoji' => 'sanitize_text_field',
     198            'bbpl_playing_background_color' => 'sanitize_hex_color',
     199            'bbpl_autoplay' => 'sanitize_checkbox',
     200        ];
     201
     202        // Sanitize user input for each field
     203        add_settings_field('bbpl_played_video_emoji', __('Played Video Emoji', 'bbpl-textdomain'), [$this, 'renderPlayedVideoEmojiField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_played_video_emoji']]);
     204        add_settings_field('bbpl_playing_emoji', __('Playing Emoji', 'bbpl-textdomain'), [$this, 'renderPlayingEmojiField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_playing_emoji']]);
     205        add_settings_field('bbpl_download_emoji', __('Download Emoji', 'bbpl-textdomain'), [$this, 'renderDownloadEmojiField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_download_emoji']]);
     206        add_settings_field('bbpl_playing_background_color', __('Playing Background Color', 'bbpl-textdomain'), [$this, 'renderBackgroundColorField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_playing_background_color']]);
     207        add_settings_field('bbpl_autoplay', __('Autoplay', 'bbpl-textdomain'), [$this, 'renderAutoplayField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_autoplay']]);
     208    }
     209
     210    // Custom sanitize function for checkbox input
     211    public function sanitize_checkbox($value)
     212    {
     213        return empty($value) ? false : true;
     214    }
     215
     216
     217    /**
     218     * Render the plugin's settings page.
     219     */
     220    public function renderSettingsPage()
     221    {
     222        ?>
     223        <div class="wrap">
     224            <h2><?php _e('Better Video & Playlist Settings', 'bbpl-textdomain'); ?></h2>
     225            <form method="post" action="options.php">
     226                <?php settings_fields('bbpl_settings_group'); ?>
     227                <?php do_settings_sections('bbpl-settings'); ?>
     228                <input type="submit" class="button-primary" value="<?php _e('Save Settings', 'bbpl-textdomain'); ?>">
     229            </form>
     230        </div>
     231        <?php
     232    }
     233
     234    /**
     235     * Render the general section description.
     236     */
     237    public function renderGeneralSection()
     238    {
     239        echo __('Configure general settings for Better Video & Playlist.', 'bbpl-textdomain');
     240    }
     241
     242    // Sanitize user input for each field before saving
     243    public function renderPlayedVideoEmojiField()
     244    {
     245        $value = get_option('bbpl_played_video_emoji', __('✔', 'bbpl-textdomain'));
     246        $value = sanitize_text_field($value); // Sanitize the input
     247        echo "<input type='text' name='bbpl_played_video_emoji' value='$value'>";
     248    }
     249
     250    public function renderPlayingEmojiField()
     251    {
     252        $value = get_option('bbpl_playing_emoji', __('▶️', 'bbpl-textdomain'));
     253        $value = sanitize_text_field($value); // Sanitize the input
     254        echo "<input type='text' name='bbpl_playing_emoji' value='$value'>";
     255    }
     256
     257    public function renderDownloadEmojiField()
     258    {
     259        $value = get_option('bbpl_download_emoji', __('💾', 'bbpl-textdomain'));
     260        $value = sanitize_text_field($value); // Sanitize the input
     261        echo "<input type='text' name='bbpl_download_emoji' value='$value'>";
     262    }
     263
     264    public function renderBackgroundColorField()
     265    {
     266        $value = get_option('bbpl_playing_background_color', '#FFFF00');
     267        $value = sanitize_hex_color($value); // Sanitize the color input
     268        echo "<input type='text' name='bbpl_playing_background_color' value='$value' class='color-picker'>";
     269    }
     270
     271    public function renderAutoplayField()
     272    {
     273        $value = get_option('bbpl_autoplay', true);
     274        $value = $value ? '1' : '0'; // Ensure it's either '0' or '1'
     275        echo "<input type='hidden' name='bbpl_autoplay' value='0'>
     276        <label for='bbpl_autoplay'>
     277            <input type='checkbox' id='bbpl_autoplay' name='bbpl_autoplay' value='1' " . checked($value, '1', false) . ">
     278            " . __('Enable Autoplay', 'bbpl-textdomain') . "
     279        </label>";
     280    }
     281
     282
     283    /**
     284     * Add links to settings and sponsorship in plugin row meta.
     285     *
     286     * @param array $plugin_meta The existing plugin meta.
     287     * @param string $plugin_file The plugin file path.
     288     * @return array Modified plugin meta with added links.
     289     */
     290    public function addPluginRowMeta($plugin_meta, $plugin_file)
     291    {
     292        if (plugin_basename(self::MAIN_FILE) !== $plugin_file) {
     293            return $plugin_meta;
     294        }
     295
     296        $settings_page_url = admin_url('options-general.php?page=bbpl-settings');
     297
     298        $plugin_meta[] = sprintf(
     299            '<a href="%1$s"><span class="dashicons dashicons-admin-settings" aria-hidden="true" style="font-size:14px;line-height:1.3"></span>%2$s</a>',
     300            $settings_page_url,
     301            esc_html_x('Settings', 'verb', 'bbpl-textdomain')
     302        );
     303
     304        $plugin_meta[] = sprintf(
     305            '<a href="%1$s"><span class="dashicons dashicons-star-filled" aria-hidden="true" style="font-size:14px;line-height:1.3"></span>%2$s</a>',
     306            'https://paypal.me/chema/10EUR',
     307            esc_html_x('Sponsor', 'verb', 'better-video')
     308        );
     309
     310        return $plugin_meta;
     311    }
    28312}
    29313
    30 
    31 /**
    32  * Handles AJAX requests.
    33  */
    34 function bbpl_store_video_time() {
    35 
    36     // Handle the ajax request here
    37     check_ajax_referer( 'better-video' );
    38     $return = FALSE;
    39 
    40     //only store for loged in users
    41     if (is_user_logged_in() ){
    42         global $current_user;
    43         $time = sanitize_text_field($_POST['time']);
    44         $video = sanitize_url($_POST['video']);
    45 
    46         if (is_numeric($time) AND wp_http_validate_url($video))
    47             $return = update_user_meta($current_user->ID,'bvideo-'.md5($video),$time);
    48     }
    49 
    50     wp_send_json($return);
     314// Initialize the plugin
     315new BetterVideoPlaylistPlugin();
     316
     317
     318
     319 function enqueueBlockAssets() {
     320    wp_enqueue_script(
     321        'bbpl-block',
     322        plugins_url('blocks/block.js', __FILE__),
     323        array('wp-blocks', 'wp-components', 'wp-i18n'),
     324    );
     325
    51326}
    52327
    53 
    54 function bbpl_get_video_time() {
    55     // Handle the ajax request here
    56     check_ajax_referer( 'better-video' );
    57     $return = 0;
    58 
    59     //only store for loged in users
    60     if (is_user_logged_in() ){
    61         global $current_user;
    62         $video = sanitize_url($_POST['video']);
    63         if (wp_http_validate_url($video))
    64             $return = get_user_meta($current_user->ID,'bvideo-'.md5($video));
    65     }
    66 
    67     wp_send_json($return);
    68 }
    69 
    70 
    71 
    72 ?>
     328add_action('enqueue_block_editor_assets', 'enqueueBlockAssets');
     329
  • better-video-playlist/tags/2.1/js/better-video.js

    r2959725 r2963306  
    11/**
    2  * Better Video and playlist jQuery plugin
    3  * Version: 2.0.4
     2 * Better Video and Playlist jQuery Plugin
     3 * Version: 2.1
    44 */
    5 jQuery(document).ready(function( $ ) {
     5
     6const config = {
     7    playedVideoEmoji: bbplSettings.playedVideoEmoji,
     8    playingEmoji: bbplSettings.playingEmoji,
     9    downloadEmoji: bbplSettings.downloadEmoji,
     10    playingBackgroundColor: bbplSettings.playingBackgroundColor,
     11    autoplay: bbplSettings.autoplay,
     12};
     13
     14jQuery(document).ready(function($) {
    615   
    7     //when we pause we store the current time
    8     $("video").on("pause", function(event) {
    9         // Save into local storage,if you change the browser will not work
    10         localStorage.setItem('bvideo-'+btoa(this.src), this.currentTime);
    11 
    12         //ajax call
    13         $.post(my_ajax_obj.ajax_url, {         //POST request
    14             _ajax_nonce: my_ajax_obj.nonce,     //nonce
    15             action: "bbpl_store_video_time",            //action
    16             time: this.currentTime,                  //time
    17             video: this.src,                    //video url
    18             }
    19         );
    20 
    21     });
    22 
    23     //if you close the window and video playing store the current time
     16
     17    //cache for DOM optimization
     18    let bvideo = $("video");
     19
     20    // If you close the window and a video is playing, store the current time by invoking the pause method
    2421    $(window).on("unload", function(e) {
    25         $("video").each(function(index, value) {
    26             if ( ! this.paused ) {
     22        bvideo.each(function(index, value) {
     23            if (!this.paused)
    2724                this.pause();
    28             }
    2925        });
    3026    });
    3127
    32     // first time the force time happens
    33     var first_time = true;
    34 
    35     //play video restores the video from the last point or from the query string using ?t=444
    36     $("video").on("play", function(event) {
    37 
    38         //only load the stored time the first time.
    39         if (first_time==true)
    40         {
    41             first_time = false;
    42             //using time provided via url only once!!
    43             var start_time = new URLSearchParams(window.location.search).get('t');
    44             var start_video = new URLSearchParams(window.location.search).get('start_video');
    45 
    46             if ( (start_time!==null && $.isNumeric(start_time)) &&  (start_video!==null && $.isNumeric(start_video)) ){
    47                 if (start_time < this.duration)
    48                     this.currentTime = start_time;
     28    // When we pause, we store the current time
     29    bvideo.on("pause", function(event) {
     30        storeVideoTime(this);
     31    });
     32
     33    // First time we force the player from the time we have stored. This is used so playlist works.
     34    let firstTime = true;
     35
     36    // Play video restores the video from the last point or from the query string using ?t=444
     37    bvideo.on("play", function(event) {
     38
     39        // Only load the stored time the first time they click play.
     40        if (firstTime == true) {
     41            firstTime = false;
     42            // Using time provided via URL only once!!
     43            let startTime = new URLSearchParams(window.location.search).get('t');
     44
     45            if (startTime !== null && $.isNumeric(startTime))  {
     46                if (startTime < this.duration)
     47                    this.currentTime = startTime;
     48            } else { // Init video at last stored time
     49
     50                storedTime = getVideoTime(this);
     51                // if not at the end or already played
     52                if (storedTime >= this.duration || storedTime == -1) {
     53                    storedTime = 0;
     54                }
     55
     56                this.currentTime = storedTime;
    4957            }
    50             else{//init video at last stored time
    51                
    52                 //first retrieve from localstorage
    53                 var storedtime = localStorage.getItem('bvideo-'+btoa(this.src));
    54      
    55                 //only ajax if storedtime is empty, saves queries
    56                 if (storedtime == null){
    57                     var video_obj = this;
    58                     //ajax call
    59                     $.post(my_ajax_obj.ajax_url, {         //POST request
    60                         _ajax_nonce: my_ajax_obj.nonce,     //nonce
    61                         action: "bbpl_get_video_time",            //action
    62                         video: this.src,                    //video url
    63                         },function(data) {                    //callback
    64                             if (data[0] < video_obj.duration)
    65                                 video_obj.currentTime = data[0];
    66                         }
    67                     );
    68                 }
    69                 // Get the time from localStorage and play if not at the end.
    70                 else if (storedtime < this.duration){
    71                     this.currentTime = storedtime;
     58        } // End if first time
     59
     60        this.play();
     61    });
     62
     63    // On finished video mark as played
     64    bvideo.on('ended', function(e) {
     65        markPlayedVideo(this);
     66    });
     67
     68    /**
     69     * Playlist player for 1 video HTML tag
     70     */
     71    let bvideo_playlist = $('#bvideo_playlist');
     72
     73    if (bvideo_playlist.length) {
     74        let currentUrl = btoa(window.location.href.split('?')[0].split('#')[0]);
     75        let videoList  = getVideoList();
     76
     77        // Playlist video player
     78        if (typeof videoList !== 'undefined') {
     79            // Start video from parameter ID
     80            let startVideo = new URLSearchParams(window.location.search).get('start_video');
     81            if (startVideo !== null && $.isNumeric(startVideo))
     82                idCurrent = startVideo - 1; // We start counting from 1 so we do not use 0.
     83            else // Init video at last play
     84                idCurrent = localStorage.getItem('bvideo-playlist-' + currentUrl);
     85            idCurrent = ($.isNumeric(idCurrent)) ? idCurrent : 0;
     86            idCurrent = (idCurrent > videoList.length - 1) ? 0 : idCurrent;
     87
     88            // gets the data from an A tag using the data attribute
     89            currentLinkVideo = $('a[data-bvideo_id~="' + idCurrent + '"]');
     90
     91            // Current video playing
     92            localStorage.setItem('bvideo-playlist-' + currentUrl, idCurrent);
     93
     94            // Setup player to play current video
     95            bvideo.attr({
     96                "id": "bvideo",
     97                "src": currentLinkVideo.attr("href"),
     98                "data-bvideo_id": idCurrent // Which video are we playing
     99            });
     100
     101            // Change title for video playing
     102            $('#bvideo_title').text(currentLinkVideo.text());
     103
     104            listVideoHighlight(currentLinkVideo);
     105
     106            // On finished video, play next
     107            bvideo.on('ended', function(e) {
     108
     109                // Current ID, using attribute since data gets cached and we are updating it
     110                id = parseInt($(this).attr("data-bvideo_id"));
     111
     112                // Icon marked played
     113                if (config.playedVideoEmoji != '')
     114                    currentLinkVideo.parent().prepend(config.playedVideoEmoji);
     115
     116                // Remove background color
     117                if (config.playingBackgroundColor != '')
     118                    currentLinkVideo.parent().css("background-color", "");
     119
     120                // What to play next
     121                idNext = (id == videoList.length - 1) ? 0 : id + 1;
     122
     123                // Getting the source of the a
     124                videoNext = $('a[data-bvideo_id~="' + idNext + '"]');
     125
     126                $(this).attr({
     127                    "src": videoNext.attr("href"),
     128                    "data-bvideo_id": idNext // Which video are we playing
     129                });
     130
     131                if (config.autoplay == 1)
     132                    $(this).attr("autoplay", "autoplay");
     133
     134                // Remember next video
     135                localStorage.setItem('bvideo-playlist-' + currentUrl, idNext);
     136
     137                // Change title for video playing
     138                $('#bvideo_title').text(videoNext.text());
     139
     140                listVideoHighlight(videoNext);
     141            });
     142
     143            // Sets the source of the video from an ahref
     144            $("#bvideo_playlist a[target!='_blank']").on("click", function(e) {
     145
     146                // We prevent any default action, so we do not go to the URL
     147                e.preventDefault();
     148
     149                bvideo.attr({
     150                    "src": $(this).attr("href"),
     151                    "data-bvideo_id": $(this).data("bvideo_id") // Which video are we playing
     152                });
     153
     154                if (config.autoplay == true)
     155                    bvideo.attr("autoplay", "autoplay");
     156
     157                // Scroll to video
     158                if ($('#bvideo_title').length) // Location.href = "#bvideo_title";
     159                    document.querySelector('#bvideo_title').scrollIntoView({
     160                        behavior: 'smooth'
     161                    });
     162                else // Location.href = "#bvideo";
     163                    document.querySelector('#bvideo').scrollIntoView({
     164                        behavior: 'smooth'
     165                    });
     166
     167                // Remember last video
     168                localStorage.setItem('bvideo-playlist-' + currentUrl, $(this).data("bvideo_id"));
     169
     170                // Change title for video playing
     171                $('#bvideo_title').text($(this).text());
     172
     173                listVideoHighlight($(this));
     174
     175            });
     176
     177        }
     178    }
     179
     180
     181    /**
     182     * generates the videoList used for the play list
     183     * if uses ARRAY JS generates the inner LI HTML
     184     * @return Array videoList
     185     */
     186    function getVideoList(){
     187        let videoList = [];
     188
     189        // 1st way to load the playlist comes from a playlist JS array
     190        if (typeof directLinkData !== 'undefined' || typeof video_playlist !== 'undefined') {
     191            // In case there's a default playlist array
     192            if (typeof video_playlist !== 'undefined') {
     193                videoList = video_playlist;
     194            }
     195
     196            // Loading playlist from a pCloud array, in a public folder view page use the directLinkData array embedded in the HTML
     197            if (typeof directLinkData !== 'undefined') {
     198                // Create the list of links
     199                let pCloud = directLinkData.content;
     200                let path = 'https://filedn.eu/' + directLinkData.code + directLinkData.dirpath;
     201
     202                for (i = 0; i < pCloud.length; i++) {
     203                    let temp = [];
     204                    temp["name"] = pCloud[i].name.slice(0, -4);
     205                    temp["link"] = path + pCloud[i].urlencodedname;
     206                    temp["size"] = pCloud[i].size;
     207                    videoList.push(temp);
    72208                }
    73209            }
    74         }//end if first time
    75 
    76         this.play();
    77     });   
    78 
    79     /**
    80      * Playlist player for 1 video HTML tag
    81      */
    82    
    83     if ($('#bvideo_playlist').length )
    84     {
    85         var video_list = [];
    86         var current_url = btoa(window.location.href.split('?')[0].split('#')[0]);
    87 
    88         // 1st way to load the playlist comes from a plylist JS array
    89         if (typeof directLinkData !== 'undefined' || typeof video_playlist !== 'undefined')
    90         {
    91             //in case there's a default playlist array
    92             if (typeof video_playlist !== 'undefined'){
    93                 video_list = video_playlist;           
     210
     211            // From array videoList to a table
     212            let htmlList = "";
     213            for (i = 0; i < videoList.length; i++) {
     214
     215                htmlList += '<li>';
     216
     217                if (isPlayedVideo(videoList[i].link))
     218                    htmlList += config.playedVideoEmoji;
     219
     220                htmlList += '<a data-bvideo_id="' + i + '" href="' + videoList[i].link + '" title="' + videoList[i].name + '">' + videoList[i].name + '</a>';
     221
     222                if (videoList[i].size != undefined) {
     223                    videoSize = (videoList[i].size != undefined ? fileSize(videoList[i].size) : '-')
     224                    htmlList += '<span style="float:right;"><a target="_blank" title="' + videoSize + ' Download" download href="' + videoList[i].link + '">' + config.downloadEmoji + '</a></span>';
     225                }
     226
     227                htmlList += '</li>';
    94228            }
    95229
    96             // loading playlist from a pcloud array, in a public folder view page use the directLinkData array embeded in the HTML
    97             if (typeof directLinkData !== 'undefined')
    98             {
    99                 //created the list of links
    100                 var pcloud = directLinkData.content;
    101                 var path   = 'https://filedn.eu/'+directLinkData.code+directLinkData.dirpath;
    102 
    103                 for (i=0; i<pcloud.length; i++)
    104                 {
    105                     var temp = [];
    106                     temp["name"] = pcloud[i].name.slice(0, -4);
    107                     temp["link"] = path+pcloud[i].urlencodedname;
    108                     temp["size"] = pcloud[i].size;
    109                     video_list.push(temp);
    110                 }
    111 
    112             }
    113 
    114             // from array video_list to a table
    115             var html_list = "";
    116             for (i=0; i<video_list.length; i++) {
    117 
    118                 html_list+='<li>';
    119 
    120                 if (is_played_video(video_list[i].link))
    121                     html_list+='&#10004;&nbsp;';
    122 
    123                 html_list+='<a data-bvideo_id="'+i+'" href="'+video_list[i].link+'" title="'+video_list[i].name+'">'+video_list[i].name+'</a>';
    124                
    125                 if (video_list[i].size!=undefined)
    126                 {
    127                     video_size = (video_list[i].size!=undefined?fileSize(video_list[i].size):'-')
    128                     html_list+='<span style="float:right;"><a target="_blank" title="'+video_size+' Download" download href="'+video_list[i].link+'">💾</a></span>';
    129                 }
    130 
    131                 html_list+='</li>';
    132             }
    133 
    134             //print html
    135             $("#bvideo_playlist").html(html_list);
    136             $("#bvideo_playlist").parent().css(  {
    137                                           "height":$("video").height()+120,
    138                                           "overflow-y": "auto"
    139                                         });
    140 
    141         }
    142 
    143         // 2nd way to get a playlist load video_list array from a list instead than JS array   
    144         else if($('#bvideo_playlist').is('ol, ul'))
    145         {
    146             var video_list = [];
    147             $("#bvideo_playlist li a").each(function(e) {
     230            // Print HTML
     231            bvideo_playlist.html(htmlList);
     232            bvideo_playlist.parent().css({
     233                "height": bvideo.height() + 120,
     234                "overflow-y": "auto"
     235            });
     236
     237        }
     238
     239        // 2nd way to get a playlist: load videoList array from a list instead than JS array   
     240        else if (bvideo_playlist.is('ol, ul')) {
     241            videoList = [];
     242            $("#bvideo_playlist li a").each(function(e) {
    148243                a = $(this);
    149                 a.attr('data-bvideo_id',e);
    150                 var temp = [];
    151                     temp["name"] = this.text;
    152                     temp["link"] = this.href;
    153                     temp["size"] = a.data('size')!==undefined?a.data('size'):0;
    154                 video_list.push(temp);
    155             });
    156         }
    157 
    158         // playlist video player
    159         if (typeof video_list !== 'undefined')
    160         {
    161             //start video from parameeter ID....
    162             var start_video = new URLSearchParams(window.location.search).get('start_video');
    163             if (start_video!==null && $.isNumeric(start_video))
    164                 id_current = start_video-1;//we start counting from 1 so we do not use the 0.
    165             else//init video at last play
    166                 id_current = localStorage.getItem('bvideo-'+current_url);
     244                a.attr('data-bvideo_id', e);
     245
     246                // Icon marked played
     247                if (config.playedVideoEmoji != '' && isPlayedVideo(this.href) )
     248                    a.parent().prepend(config.playedVideoEmoji);
     249
     250                let temp = {};
     251                temp["name"] = this.text;
     252                temp["link"] = this.href;
     253                temp["size"] = a.data('size') !== undefined ? a.data('size') : 0;
     254                videoList.push(temp);
     255            });
    167256           
    168             id_current = ($.isNumeric(id_current))?id_current:0;
    169             id_current = (id_current > video_list.length-1)?0:id_current;
    170 
    171             current_video = $('a[data-bvideo_id~="'+id_current+'"]');
    172 
    173             //current video playing
    174             localStorage.setItem('bvideo-'+current_url, id_current);
    175 
    176             //setup player to play current video
    177             $("video").attr({
    178                 "id":"bvideo",
    179                 "src": current_video.attr("href"),
    180                 "data-bvideo_id":id_current//which video are we playing
    181             });
    182            
    183             //change title for video playing
    184             $('#bvideo_title').text(current_video.text());
    185 
    186             //highlight
    187             current_video.parent().css("background-color","#eeeeee");
    188 
    189 
    190             //on finished video play next
    191             $("video").on('ended', function(e){
    192 
    193                 //current id,using attribute since data gets cached and we are updating it
    194                 id = parseInt($(this).attr("data-bvideo_id"));
    195 
    196                 //we mark this video as played
    197                 mark_played_video(id);
    198                
    199                 //what to play next
    200                 id_next = (id == video_list.length-1)?0:id+1;
    201 
    202                 //getting the source of the a
    203                 src = $('a[data-bvideo_id~="'+id_next+'"]');
    204 
    205                 $(this).attr({
    206                     "src": src.attr("href"),
    207                     "autoplay": "autoplay",
    208                     "data-bvideo_id":id_next //which video are we playing
    209                 });
    210 
    211                 //remember next video
    212                 localStorage.setItem('bvideo-'+current_url, id_next);
    213 
    214                 //change title for video playing
    215                 $('#bvideo_title').text(src.text());
    216 
    217                 //highlight whats currently playing
    218                 //$(this).parent().prepend('▶️&nbsp;');
    219                 $('#bvideo_playlist li').css("background-color","");
    220                 src.parent().css("background-color","#eeeeee");
    221             });
    222 
    223             //sets the source of the video from an ahref
    224             $("#bvideo_playlist a[target!='_blank']").on("click", function(e) {
    225 
    226                 //we prevent any default action, so we do not go to the url
    227                 e.preventDefault();
    228 
    229                 $("video").attr({
    230                     "src": $(this).attr("href"),
    231                     "autoplay": "autoplay",
    232                     "data-bvideo_id":$(this).data("bvideo_id") //which video are we playing
    233                 });
    234 
    235                 //scroll to video
    236                 if ($('#bvideo_title').length )//location.href = "#bvideo_title";
    237                     document.querySelector('#bvideo_title').scrollIntoView({behavior: 'smooth'});
    238                    
    239                 else//location.href = "#bvideo";
    240                     document.querySelector('#bvideo').scrollIntoView({behavior: 'smooth'});
    241 
    242                 //remember last video
    243                 localStorage.setItem('bvideo-'+current_url, $(this).data("bvideo_id"));
    244 
    245                 //change title for video playing
    246                 $('#bvideo_title').text($(this).text());
    247 
    248                 //highlight whats currently playing
    249                 //$(this).parent().prepend('▶️&nbsp;');
    250                 $('#bvideo_playlist li').css("background-color","");
    251                 $(this).parent().css("background-color","#eeeeee");
    252             });
     257        }
     258
     259        return videoList;
     260    }
     261
     262
     263    /**
     264     * store video time in local and WP
     265     * @param   video
     266     * @param   time we can specify the time we store. For instance -1 means video played.
     267     */
     268    function storeVideoTime(video, time = false){
     269        //time not set then using video current
     270        if (time==false)
     271            time = video.currentTime;
     272
     273        // Save into local storage; if you change the browser, it will not work
     274        localStorage.setItem('bvideo-' + btoa(video.src), time);
     275
     276        // Ajax call
     277        $.post(betterVideo_ajax.ajax_url, {
     278            _ajax_nonce: betterVideo_ajax.nonce, // Nonce
     279            action: "bbpl_store_video_time", // Action
     280            time: time, // Time
     281            video: video.src, // Video URL
     282        }).fail(handleAjaxError);
     283    }
     284
     285    /**
     286     * get the video time from a SRC
     287     * @param  video
     288     * @return integer
     289     */
     290    function getVideoTime(video){
     291        storedTime = getVideoTimeSrc(video.src);
     292        if (storedTime > video.duration)
     293            storedTime = 0;
     294
     295        return storedTime;
     296    }
     297
     298
     299    function getVideoTimeSrc(videoSrc){
     300        // First, retrieve from local storage
     301        let storedTime = localStorage.getItem('bvideo-' + btoa(videoSrc));
     302
     303        // TODO needed improvement here!!
     304        // Only Ajax if stored time is empty, saves queries
     305        // but we may have different values if used in different browsers
     306        if (storedTime == null) {
     307            // Ajax call
     308            $.post(betterVideo_ajax.ajax_url, {
     309                _ajax_nonce: betterVideo_ajax.nonce, // Nonce
     310                action: "bbpl_get_video_time", // Action
     311                video: videoSrc, // Video URL
     312            }, function(data) { // Callback
     313                storedTime = data[0];
     314            }).fail(handleAjaxError);
     315        }
    253316       
    254         }
    255 
    256         /**
    257          * we mark a video as played, we use the btoa of the current url and we store the btoa of the video src
    258          * @param  id_video we get the src from the a
    259          */
    260         function mark_played_video(id_video)
    261         {
    262             //getting the source of the a
    263             a = $('a[data-bvideo_id~="'+id_video+'"]');
    264             src = a.attr("href");
    265 
    266             // if it was not in the array before, then store
    267             if(is_played_video(src) == false)
    268             { 
    269                 var watched_videos;
    270 
    271                 watched_videos = localStorage.getItem('bvideo-played-'+ current_url);
    272 
    273                 if (watched_videos == null)
    274                     watched_videos = [];
    275                 else
    276                     watched_videos = JSON.parse(watched_videos);
    277 
    278                 watched_videos.push(btoa(src));
    279                 localStorage.setItem('bvideo-played-'+ current_url, JSON.stringify(watched_videos));
    280 
    281                 //icon marked played
    282                 a.parent().prepend('&#10004;&nbsp;');
    283                 //remove backgorund color
    284                 a.parent().css("background-color","");
    285             }
    286         }
    287 
    288         /**
    289          * tells us if we have seen that video in this url
    290          * @param  string btoa src of the video
    291          * @return boolean   
    292          */
    293         function is_played_video(src)
    294         {
    295             watched_videos = localStorage.getItem('bvideo-played-'+ current_url);
    296 
    297             if (watched_videos == null)
    298                 return false;
    299 
    300             watched_videos = JSON.parse(watched_videos);
    301 
    302             if( watched_videos.indexOf(btoa(src)) != -1 )
    303                 return true;
    304             else
    305                 return false;
    306         }
    307    
    308     }
     317        return storedTime;
     318    }
     319
     320    /**
     321     * video is marked as played using -1
     322     * @param   video
     323     */
     324    function markPlayedVideo(video){
     325
     326        if (isPlayedVideo(video.src) == false)
     327            storeVideoTime(video,-1);
     328    }
     329
     330    /**
     331     * Tells us if we have seen that video in this URL
     332     * @param  string btoa src of the video
     333     * @return boolean   
     334     */
     335    function isPlayedVideo(videoSrc) {
     336        return getVideoTimeSrc(videoSrc) == -1;
     337    }
     338
     339    /**
     340     * Highlights the item on the playlist to know what is been playing
     341     * @return none
     342     */
     343    function listVideoHighlight(linkList) {
     344        // Highlight what's currently playing
     345        if (config.playingEmoji != '') {
     346            $("#bvideoCurrentVideoEmoji").remove();
     347            linkList.parent().prepend('<span id="bvideoCurrentVideoEmoji">' + config.playingEmoji + '&nbsp;</span>');
     348        }
     349        if (config.playingBackgroundColor != '') {
     350            $(".bvideoCurrentVideoColor").css("background-color", "");
     351            linkList.parent().addClass('bvideoCurrentVideoColor');
     352            linkList.parent().css("background-color", config.playingBackgroundColor);
     353        }
     354    }
     355
     356    // AJAX error handling function
     357    function handleAjaxError(xhr, textStatus, errorThrown) {
     358        console.error("AJAX Error: " + textStatus);
     359        console.error("Error Details: " + errorThrown);
     360    }
     361
    309362
    310363})
    311364
    312 //from https://stackoverflow.com/a/20463021
    313 function fileSize(a,b,c,d,e)
    314 {
    315     return (b=Math,c=b.log,d=1e3,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(e?2:0)+' '+(e?'kMGTPEZY'[--e]+'B':'Bytes')
     365// From https://stackoverflow.com/a/20463021
     366function fileSize(a, b, c, d, e) {
     367    return (b = Math, c = b.log, d = 1e3, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(e ? 2 : 0) + ' ' + (e ? 'kMGTPEZY'[--e] + 'B' : 'Bytes')
    316368}
  • better-video-playlist/trunk/README.TXT

    r2959725 r2963306  
    55Requires at least: 6.0
    66Tested up to: 6.3
    7 Stable tag: 2.0.4
     7Stable tag: 2.1
    88Requires PHP: 7.4
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1111
    12 Improves video capabilities for wordpress, stores progress and adds video playlist features.
    13 
     12Improves WordPress Video Experience by adding playlist, resume video and a lot more!
    1413
    1514== Description ==
    1615
    17 Super fast video player and playlist player using native HTML5 video player and jQuery. Uses browser local storage for most features.
     16**Elevate Your WordPress Video Experience!**
    1817
    19 If user is logged in we store video position in the database. So even if changes browser will save the progress.
     18The Better Video & Playlist Plugin is designed to enhance the video capabilities of your WordPress website while adding a sophisticated video playlist feature. This plugin ensures that your site's visitors enjoy a seamless and engaging video-watching experience.
    2019
    21 Works in pages, posts, widgets or any place at your site.
     20**Key Features:**
    2221
    23 = Features =
     22- **Resume Video Playback**: Never lose progress – our plugin remembers where you left off.
     23- **Video Progress Storage**: Store video progress in the WordPress database and local browser storage.
     24- **Customized Start Time**: Start your videos at specific times using the `?t=SECONDS` parameter (e.g., `?t=120` starts at 2 minutes).
     25- **Video Playlists**: Create and manage video playlists effortlessly using block editor.
     26- **Autoplay Next Video**: Keep viewers engaged with automatic playback of the next video.
     27- **Emoji Customization**: Add a personal touch with custom video emojis.
     28- **Background Color**: Tailor the video player's background color to match your site's aesthetics.
    2429
    25 - Resume video from last position. Saves progress in DB and browser storage.
    26 - On pause or window close, stores progress
    27 -  Start playing video at custom time using ?t=SECONDS ex ?t=120 will start at 2 minutes
     30**Why Choose Better Video & Playlist?**
    2831
    29 **Playlist Features**
    30 - Create playlist video from a HTML5 list or JS array
    31 - Resume on last played video
    32 - Autoplay next video on video end
    33 - Mark video as played
    34 - Start playing from video via url parameter using ?start_video=ID_VIDEO
    35 - Stored in user browser storage and at WordPress Database
    36 
     32- **User-Friendly**: Seamlessly integrate advanced video features into your WordPress site.
     33- **Progress Tracking**: Never make viewers start from scratch; they can pick up right where they left off.
     34- **Playlist Management**: Create and organize video playlists with ease.
     35- **Community Support**: Join a community of users benefiting from this plugin's capabilities.
    3736
    3837== Installation ==
    3938
    40 Through WordPress admin:
     39**Via WordPress Admin:**
    4140
    42 1. Go to Plugins -> Add New
    43 2. Search for "Better Video"
    44 3. Install the plugin
    45 4. Activate it
     411. Go to **Plugins** -> **Add New**.
     422. Search for "Better Video & Playlist."
     433. Click **Install Now**.
     444. Activate the plugin.
    4645
    47 Through FTP:
     46**Via FTP:**
    4847
    49 1. Download the plugin
    50 2. Unzip .zip and upload the folder to the `/wp-content/plugins/` directory
    51 3. Activate the plugin through the 'Plugins' menu in WordPress
    52 
     481. Download the plugin.
     492. Unzip the .zip file and upload the folder to `/wp-content/plugins/`.
     503. Activate the plugin in the **Plugins** menu of WordPress.
    5351
    5452== Frequently Asked Questions ==
    5553
    56 = How to use? =
     54**How to Use?**
    5755
    58 To enable the video features just add a video from the post editor or add HTML video tag. You can have as many video tags as you want.
     56To enable the video features, add a video from the post editor or use the HTML video tag. You can include as many video tags as needed.
    5957
    60 = Video Play list =
     58**Creating Video Playlists**
    6159
    62 You can create a list on your editor and then in the side panel in advanced, anchor set it to "bvideo_playlist".
     60You can create a video playlist within your editor by using the block.
    6361
    64 Also you can edit the HTML and create List with id = bvideo_playlist:
     62Or by using the advanced settings panel and setting it to "bvideo_playlist." Alternatively, you can create a list in your HTML with the id "bvideo_playlist."
    6563
    66     <ol id="bvideo_playlist">
    67         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/earth_night_rotate_1080.mov">Animation: Rotating Earth at Night</a></li>
    68         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/rbsp_launch_1080p.mp4">Radiation Belt Storm Probes Launch</a></li>
    69         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/curiosity_lands.mov">Dropping in on Mars in High-Res</a></li>
    70         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/GRAIL_launch_1080.mov">GRAIL Launches on Mission to Moon</a></li>
    71         <li><a href="http://s3.amazonaws.com/akamai.netstorage/HD_downloads/HLV_Launch_anim.mov">Space Launch System Animation</a></li>
    72     </ol>
     64Here's an example HTML playlist:
    7365
     66```html
     67<ol id="bvideo_playlist">
     68    <li><a href="video1.mp4">Video 1</a></li>
     69    <li><a href="video2.mp4">Video 2</a></li>
     70    <li><a href="video3.mp4">Video 3</a></li>
     71</ol>
     72```
    7473
    75 You can also add in your HTML/JS file a playlist array and will create your list magically, the size field it’s optional:
     74You can also create a playlist using a JavaScript array:
    7675
    77     <script>
    78     var video_playlist = [
    79         {
    80             "name": "Animation: Rotating Earth at Night",
    81             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/earth_night_rotate_1080.mov",
    82             "size": 55000000,
    83         },
    84         {
    85             "name": "Radiation Belt Storm Probes Launch",
    86             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/rbsp_launch_1080p.mp4",
    87             "size": 475000000,
    88         },
    89         {
    90             "name": "Dropping in on Mars in High-Res",
    91             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/curiosity_lands.mov",
    92             "size": 105000000,
    93         },
    94         {
    95             "name": "GRAIL Launches on Mission to Moon",
    96             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/GRAIL_launch_1080.mov",
    97             "size": 1113000000,
    98         },
    99         {
    100             "name": "Space Launch System Animation",
    101             "link": "http://s3.amazonaws.com/akamai.netstorage/HD_downloads/HLV_Launch_anim.mov",
    102             "size": 642570000,
    103         },
    104    
    105     ];
    106     </script>
     76```javascript
     77<script>
     78var video_playlist = [
     79    {
     80        "name": "Video 1",
     81        "link": "video1.mp4",
     82        "size": 55000000
     83    },
     84    {
     85        "name": "Video 2",
     86        "link": "video2.mp4",
     87        "size": 475000000
     88    },
     89    {
     90        "name": "Video 3",
     91        "link": "video3.mp4",
     92        "size": 105000000
     93    }
     94];
     95</script>
     96```
    10797
    108 To add the JS to your post/page you can use a plugin like [this one](https://wordpress.org/plugins/header-and-footer-scripts/).
    109 
     98To add the JavaScript to your post/page, consider using a plugin like [this one](https://wordpress.org/plugins/header-and-footer-scripts/).
    11099
    111100== Screenshots ==
    112 1. Video player
    113 2. Play list player
    114101
    115 == Upgrade Notice ==
    116 None.
     1021. Video Player
     1032. Playlist Player
    117104
    118 == Changelog ==
     105== Upgrade History ==
    119106
     107= Version 2.1 =
     108- Major jQuery and PHP code refactor
     109- Improved method for tracking played videos
     110- New admin panel with customizable settings
    120111
    121 = 2.0.4 =
    122 * Improved description and FAQ's
     112= Version 2.0.4 =
     113- Enhanced descriptions and FAQs
    123114
    124 = 2.0.3 =
    125 * WP 6.3 tested
     115= Version 2.0.3 =
     116- Tested for WordPress 6.3 compatibility
    126117
    127 = 2.0.2 =
    128 * smooth scroll to video
     118= Version 2.0.2 =
     119- Added smooth scroll to video
    129120
    130 = 2.0.1 =
    131 * ajax stores video time for logged user
     121= Version 2.0.1 =
     122- Implemented AJAX for storing video time for logged-in users
    132123
    133 = 1.0 =
    134 * Initial version
     124= Version 1.0 =
     125- Initial release
  • better-video-playlist/trunk/better-video.php

    r2959725 r2963306  
    11<?php
    22/**
    3     * Plugin Name: Better Video & Playlist
    4     * Plugin URI: https://garridodiaz.com/better-video-plugin-for-wordpress/
    5     * Description: Improves video capabilities for wordpress and adds video playlist features.
    6     * Version: 2.0.4
    7     * Author: Chema
    8     * Author URI: https://garridodiaz.com
    9     * License: GPL2
    10 */
    11 
    12 add_action( 'wp_enqueue_scripts', 'bbpl_assets');
    13 add_action( 'wp_ajax_bbpl_store_video_time', 'bbpl_store_video_time' );
    14 add_action( 'wp_ajax_bbpl_get_video_time', 'bbpl_get_video_time' );
    15 
    16 /* enqueue scripts and style from parent theme */       
    17 function bbpl_assets() {
    18     wp_enqueue_script( 'better-video', plugin_dir_url( __FILE__ ) . 'js/better-video.js', array('jquery'), '2.0.4', true );
    19 
    20     wp_localize_script(
    21         'better-video',
    22         'my_ajax_obj',
    23         array(
    24             'ajax_url' => admin_url( 'admin-ajax.php' ),
    25             'nonce'    => wp_create_nonce( 'better-video' ),
    26         )
    27     );
     3 * Plugin Name: Better Video & Playlist
     4 * Plugin URI: https://garridodiaz.com/better-video-plugin-for-wordpress/
     5 * Description: Improves video capabilities for WordPress and adds video playlist features.
     6 * Version: 2.1
     7 * Author: Chema
     8 * Author URI: https://garridodiaz.com
     9 * License: GPL2
     10 */
     11
     12if (!defined('ABSPATH')) exit; // Exit if accessed directly
     13
     14class BetterVideoPlaylistPlugin
     15{
     16    const MAIN_FILE = __FILE__;
     17
     18    public function __construct()
     19    {
     20        // Initialize the plugin by adding hooks and actions
     21        add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']);
     22        add_action('wp_ajax_bbpl_store_video_time', [$this, 'storeVideoTime']);
     23        add_action('wp_ajax_bbpl_get_video_time', [$this, 'getVideoTime']);
     24        add_action('admin_menu', [$this, 'addAdminMenu']);
     25        add_action('admin_init', [$this, 'registerSettings']);
     26        add_action('admin_enqueue_scripts', [$this, 'enqueueAdminScripts']);
     27        add_action('admin_notices', [$this, 'displayDonationMessage']);
     28        add_action('admin_head', [$this, 'addDonationMessageJS']);
     29        add_filter('plugin_row_meta', [$this, 'addPluginRowMeta'], 10, 2);
     30        add_action('admin_init', [$this, 'setupSettingsFields']);
     31    }
     32
     33    /**
     34     * Enqueue assets (scripts and styles) for the plugin.
     35     */
     36    public function enqueueAssets()
     37    {
     38        // Enqueue scripts and localize for better-video.js
     39        wp_enqueue_script('better-video', plugin_dir_url(__FILE__) . 'js/better-video.js', array('jquery'), '2.1', true);
     40
     41        wp_localize_script(
     42            'better-video',
     43            'betterVideo_ajax',
     44            array(
     45                'ajax_url' => admin_url('admin-ajax.php'),
     46                'nonce' => wp_create_nonce('better-video'),
     47            )
     48        );
     49
     50        $bbpl_settings = array(
     51            'playedVideoEmoji' => get_option('bbpl_played_video_emoji', __('✔', 'bbpl-textdomain')),
     52            'playingEmoji' => get_option('bbpl_playing_emoji', __('▶️', 'bbpl-textdomain')),
     53            'downloadEmoji' => get_option('bbpl_download_emoji', __('💾', 'bbpl-textdomain')),
     54            'playingBackgroundColor' => get_option('bbpl_playing_background_color', '#FFFF00'),
     55            'autoplay' => get_option('bbpl_autoplay', true),
     56        );
     57        wp_localize_script('better-video', 'bbplSettings', $bbpl_settings);
     58    }
     59
     60    /**
     61     * Handle AJAX request for storing video time.
     62     *
     63     * @return bool JSON response indicating success or failure.
     64     */
     65    public function storeVideoTime()
     66    {
     67        // Handle the AJAX request for storing video time
     68        check_ajax_referer('better-video');
     69        $return = false;
     70
     71        if (is_user_logged_in()) {
     72            global $current_user;
     73            $time = sanitize_text_field($_POST['time']);
     74            $video = sanitize_url($_POST['video']);
     75
     76            if (is_numeric($time) && wp_http_validate_url($video)) {
     77                $return = update_user_meta($current_user->ID, 'bvideo-' . md5($video), $time);
     78            }
     79        }
     80
     81        wp_send_json($return);
     82    }
     83
     84    /**
     85     * Handle AJAX request for getting video time.
     86     *
     87     * @return mixed JSON response containing the video time or 0.
     88     */
     89    public function getVideoTime()
     90    {
     91        // Handle the AJAX request for getting video time
     92        check_ajax_referer('better-video');
     93        $return = 0;
     94
     95        if (is_user_logged_in()) {
     96            global $current_user;
     97            $video = sanitize_url($_POST['video']);
     98            if (wp_http_validate_url($video)) {
     99                $return = get_user_meta($current_user->ID, 'bvideo-' . md5($video));
     100            }
     101        }
     102
     103        wp_send_json($return);
     104    }
     105
     106    /**
     107     * Add the admin menu for plugin settings.
     108     */
     109    public function addAdminMenu()
     110    {
     111        // Add the admin menu for settings
     112        add_submenu_page(
     113            'options-general.php',
     114            __('Better Video & Playlist Settings', 'bbpl-textdomain'),
     115            __('Video Settings', 'bbpl-textdomain'),
     116            'manage_options',
     117            'bbpl-settings',
     118            [$this, 'renderSettingsPage']
     119        );
     120    }
     121
     122    /**
     123     * Register plugin settings.
     124     */
     125    public function registerSettings()
     126    {
     127        // Register plugin settings
     128        register_setting('bbpl_settings_group', 'bbpl_played_video_emoji');
     129        register_setting('bbpl_settings_group', 'bbpl_playing_emoji');
     130        register_setting('bbpl_settings_group', 'bbpl_download_emoji');
     131        register_setting('bbpl_settings_group', 'bbpl_playing_background_color');
     132        register_setting('bbpl_settings_group', 'bbpl_autoplay');
     133    }
     134
     135    /**
     136     * Enqueue scripts for the admin page.
     137     *
     138     * @param string $hook The current admin page hook.
     139     */
     140    public function enqueueAdminScripts($hook)
     141    {
     142        // Enqueue scripts for the admin page
     143        if ($hook === 'settings_page_bbpl-settings') {
     144            wp_enqueue_script('bbpl-admin', plugin_dir_url(__FILE__) . 'js/admin-better-video.js', array('jquery', 'wp-color-picker'), '1.0', true);
     145        }
     146    }
     147
     148    /**
     149     * Display a donation message in the WordPress admin.
     150     */
     151    public function displayDonationMessage()
     152    {
     153        // Display the donation message
     154        if ((isset($_GET['page']) && $_GET['page'] === 'bbpl-settings') && !isset($_COOKIE['donation_message_closed'])) {
     155            echo '<div id="donation-message" class="notice notice-info is-dismissible" style="background-color: #f5f5f5; border-left: 4px solid #0073aa; padding: 10px;">
     156                <p style="font-size: 16px;">Enjoy using our plugin? Consider <a href="https://paypal.me/chema/10EUR" target="_blank" id="donate-link">making a donation</a> to support our work! THANKS!</p>
     157                </div>';
     158        }
     159    }
     160
     161    /**
     162     * Add JavaScript for handling the donation message.
     163     */
     164    public function addDonationMessageJS()
     165    {
     166        // Add JavaScript for handling the donation message
     167        if (!isset($_COOKIE['donation_message_closed'])) {
     168            ?>
     169            <script type="text/javascript">
     170                jQuery(document).ready(function ($) {
     171
     172                    $('#donate-link').click(function () {
     173                        $('#donation-message').remove();
     174                        var expirationDate = new Date();
     175                        expirationDate.setDate(expirationDate.getDate() + 30); // Expires in 30 days
     176                        document.cookie = 'donation_message_closed=true; expires=' + expirationDate.toUTCString() + '; path=/';
     177
     178                    });
     179                });
     180            </script>
     181            <?php
     182        }
     183    }
     184
     185    /**
     186     * Setup settings fields and sections for the plugin.
     187     */
     188    public function setupSettingsFields()
     189    {
     190        // Setup settings fields and sections
     191        add_settings_section('bbpl_general_section', __('General Settings', 'bbpl-textdomain'), [$this, 'renderGeneralSection'], 'bbpl-settings');
     192
     193        // Define custom sanitize callbacks for each field
     194        $sanitize_callbacks = [
     195            'bbpl_played_video_emoji' => 'sanitize_text_field',
     196            'bbpl_playing_emoji' => 'sanitize_text_field',
     197            'bbpl_download_emoji' => 'sanitize_text_field',
     198            'bbpl_playing_background_color' => 'sanitize_hex_color',
     199            'bbpl_autoplay' => 'sanitize_checkbox',
     200        ];
     201
     202        // Sanitize user input for each field
     203        add_settings_field('bbpl_played_video_emoji', __('Played Video Emoji', 'bbpl-textdomain'), [$this, 'renderPlayedVideoEmojiField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_played_video_emoji']]);
     204        add_settings_field('bbpl_playing_emoji', __('Playing Emoji', 'bbpl-textdomain'), [$this, 'renderPlayingEmojiField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_playing_emoji']]);
     205        add_settings_field('bbpl_download_emoji', __('Download Emoji', 'bbpl-textdomain'), [$this, 'renderDownloadEmojiField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_download_emoji']]);
     206        add_settings_field('bbpl_playing_background_color', __('Playing Background Color', 'bbpl-textdomain'), [$this, 'renderBackgroundColorField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_playing_background_color']]);
     207        add_settings_field('bbpl_autoplay', __('Autoplay', 'bbpl-textdomain'), [$this, 'renderAutoplayField'], 'bbpl-settings', 'bbpl_general_section', ['sanitize_callback' => $sanitize_callbacks['bbpl_autoplay']]);
     208    }
     209
     210    // Custom sanitize function for checkbox input
     211    public function sanitize_checkbox($value)
     212    {
     213        return empty($value) ? false : true;
     214    }
     215
     216
     217    /**
     218     * Render the plugin's settings page.
     219     */
     220    public function renderSettingsPage()
     221    {
     222        ?>
     223        <div class="wrap">
     224            <h2><?php _e('Better Video & Playlist Settings', 'bbpl-textdomain'); ?></h2>
     225            <form method="post" action="options.php">
     226                <?php settings_fields('bbpl_settings_group'); ?>
     227                <?php do_settings_sections('bbpl-settings'); ?>
     228                <input type="submit" class="button-primary" value="<?php _e('Save Settings', 'bbpl-textdomain'); ?>">
     229            </form>
     230        </div>
     231        <?php
     232    }
     233
     234    /**
     235     * Render the general section description.
     236     */
     237    public function renderGeneralSection()
     238    {
     239        echo __('Configure general settings for Better Video & Playlist.', 'bbpl-textdomain');
     240    }
     241
     242    // Sanitize user input for each field before saving
     243    public function renderPlayedVideoEmojiField()
     244    {
     245        $value = get_option('bbpl_played_video_emoji', __('✔', 'bbpl-textdomain'));
     246        $value = sanitize_text_field($value); // Sanitize the input
     247        echo "<input type='text' name='bbpl_played_video_emoji' value='$value'>";
     248    }
     249
     250    public function renderPlayingEmojiField()
     251    {
     252        $value = get_option('bbpl_playing_emoji', __('▶️', 'bbpl-textdomain'));
     253        $value = sanitize_text_field($value); // Sanitize the input
     254        echo "<input type='text' name='bbpl_playing_emoji' value='$value'>";
     255    }
     256
     257    public function renderDownloadEmojiField()
     258    {
     259        $value = get_option('bbpl_download_emoji', __('💾', 'bbpl-textdomain'));
     260        $value = sanitize_text_field($value); // Sanitize the input
     261        echo "<input type='text' name='bbpl_download_emoji' value='$value'>";
     262    }
     263
     264    public function renderBackgroundColorField()
     265    {
     266        $value = get_option('bbpl_playing_background_color', '#FFFF00');
     267        $value = sanitize_hex_color($value); // Sanitize the color input
     268        echo "<input type='text' name='bbpl_playing_background_color' value='$value' class='color-picker'>";
     269    }
     270
     271    public function renderAutoplayField()
     272    {
     273        $value = get_option('bbpl_autoplay', true);
     274        $value = $value ? '1' : '0'; // Ensure it's either '0' or '1'
     275        echo "<input type='hidden' name='bbpl_autoplay' value='0'>
     276        <label for='bbpl_autoplay'>
     277            <input type='checkbox' id='bbpl_autoplay' name='bbpl_autoplay' value='1' " . checked($value, '1', false) . ">
     278            " . __('Enable Autoplay', 'bbpl-textdomain') . "
     279        </label>";
     280    }
     281
     282
     283    /**
     284     * Add links to settings and sponsorship in plugin row meta.
     285     *
     286     * @param array $plugin_meta The existing plugin meta.
     287     * @param string $plugin_file The plugin file path.
     288     * @return array Modified plugin meta with added links.
     289     */
     290    public function addPluginRowMeta($plugin_meta, $plugin_file)
     291    {
     292        if (plugin_basename(self::MAIN_FILE) !== $plugin_file) {
     293            return $plugin_meta;
     294        }
     295
     296        $settings_page_url = admin_url('options-general.php?page=bbpl-settings');
     297
     298        $plugin_meta[] = sprintf(
     299            '<a href="%1$s"><span class="dashicons dashicons-admin-settings" aria-hidden="true" style="font-size:14px;line-height:1.3"></span>%2$s</a>',
     300            $settings_page_url,
     301            esc_html_x('Settings', 'verb', 'bbpl-textdomain')
     302        );
     303
     304        $plugin_meta[] = sprintf(
     305            '<a href="%1$s"><span class="dashicons dashicons-star-filled" aria-hidden="true" style="font-size:14px;line-height:1.3"></span>%2$s</a>',
     306            'https://paypal.me/chema/10EUR',
     307            esc_html_x('Sponsor', 'verb', 'better-video')
     308        );
     309
     310        return $plugin_meta;
     311    }
    28312}
    29313
    30 
    31 /**
    32  * Handles AJAX requests.
    33  */
    34 function bbpl_store_video_time() {
    35 
    36     // Handle the ajax request here
    37     check_ajax_referer( 'better-video' );
    38     $return = FALSE;
    39 
    40     //only store for loged in users
    41     if (is_user_logged_in() ){
    42         global $current_user;
    43         $time = sanitize_text_field($_POST['time']);
    44         $video = sanitize_url($_POST['video']);
    45 
    46         if (is_numeric($time) AND wp_http_validate_url($video))
    47             $return = update_user_meta($current_user->ID,'bvideo-'.md5($video),$time);
    48     }
    49 
    50     wp_send_json($return);
     314// Initialize the plugin
     315new BetterVideoPlaylistPlugin();
     316
     317
     318
     319 function enqueueBlockAssets() {
     320    wp_enqueue_script(
     321        'bbpl-block',
     322        plugins_url('blocks/block.js', __FILE__),
     323        array('wp-blocks', 'wp-components', 'wp-i18n'),
     324    );
     325
    51326}
    52327
    53 
    54 function bbpl_get_video_time() {
    55     // Handle the ajax request here
    56     check_ajax_referer( 'better-video' );
    57     $return = 0;
    58 
    59     //only store for loged in users
    60     if (is_user_logged_in() ){
    61         global $current_user;
    62         $video = sanitize_url($_POST['video']);
    63         if (wp_http_validate_url($video))
    64             $return = get_user_meta($current_user->ID,'bvideo-'.md5($video));
    65     }
    66 
    67     wp_send_json($return);
    68 }
    69 
    70 
    71 
    72 ?>
     328add_action('enqueue_block_editor_assets', 'enqueueBlockAssets');
     329
  • better-video-playlist/trunk/js/better-video.js

    r2959725 r2963306  
    11/**
    2  * Better Video and playlist jQuery plugin
    3  * Version: 2.0.4
     2 * Better Video and Playlist jQuery Plugin
     3 * Version: 2.1
    44 */
    5 jQuery(document).ready(function( $ ) {
     5
     6const config = {
     7    playedVideoEmoji: bbplSettings.playedVideoEmoji,
     8    playingEmoji: bbplSettings.playingEmoji,
     9    downloadEmoji: bbplSettings.downloadEmoji,
     10    playingBackgroundColor: bbplSettings.playingBackgroundColor,
     11    autoplay: bbplSettings.autoplay,
     12};
     13
     14jQuery(document).ready(function($) {
    615   
    7     //when we pause we store the current time
    8     $("video").on("pause", function(event) {
    9         // Save into local storage,if you change the browser will not work
    10         localStorage.setItem('bvideo-'+btoa(this.src), this.currentTime);
    11 
    12         //ajax call
    13         $.post(my_ajax_obj.ajax_url, {         //POST request
    14             _ajax_nonce: my_ajax_obj.nonce,     //nonce
    15             action: "bbpl_store_video_time",            //action
    16             time: this.currentTime,                  //time
    17             video: this.src,                    //video url
    18             }
    19         );
    20 
    21     });
    22 
    23     //if you close the window and video playing store the current time
     16
     17    //cache for DOM optimization
     18    let bvideo = $("video");
     19
     20    // If you close the window and a video is playing, store the current time by invoking the pause method
    2421    $(window).on("unload", function(e) {
    25         $("video").each(function(index, value) {
    26             if ( ! this.paused ) {
     22        bvideo.each(function(index, value) {
     23            if (!this.paused)
    2724                this.pause();
    28             }
    2925        });
    3026    });
    3127
    32     // first time the force time happens
    33     var first_time = true;
    34 
    35     //play video restores the video from the last point or from the query string using ?t=444
    36     $("video").on("play", function(event) {
    37 
    38         //only load the stored time the first time.
    39         if (first_time==true)
    40         {
    41             first_time = false;
    42             //using time provided via url only once!!
    43             var start_time = new URLSearchParams(window.location.search).get('t');
    44             var start_video = new URLSearchParams(window.location.search).get('start_video');
    45 
    46             if ( (start_time!==null && $.isNumeric(start_time)) &&  (start_video!==null && $.isNumeric(start_video)) ){
    47                 if (start_time < this.duration)
    48                     this.currentTime = start_time;
     28    // When we pause, we store the current time
     29    bvideo.on("pause", function(event) {
     30        storeVideoTime(this);
     31    });
     32
     33    // First time we force the player from the time we have stored. This is used so playlist works.
     34    let firstTime = true;
     35
     36    // Play video restores the video from the last point or from the query string using ?t=444
     37    bvideo.on("play", function(event) {
     38
     39        // Only load the stored time the first time they click play.
     40        if (firstTime == true) {
     41            firstTime = false;
     42            // Using time provided via URL only once!!
     43            let startTime = new URLSearchParams(window.location.search).get('t');
     44
     45            if (startTime !== null && $.isNumeric(startTime))  {
     46                if (startTime < this.duration)
     47                    this.currentTime = startTime;
     48            } else { // Init video at last stored time
     49
     50                storedTime = getVideoTime(this);
     51                // if not at the end or already played
     52                if (storedTime >= this.duration || storedTime == -1) {
     53                    storedTime = 0;
     54                }
     55
     56                this.currentTime = storedTime;
    4957            }
    50             else{//init video at last stored time
    51                
    52                 //first retrieve from localstorage
    53                 var storedtime = localStorage.getItem('bvideo-'+btoa(this.src));
    54      
    55                 //only ajax if storedtime is empty, saves queries
    56                 if (storedtime == null){
    57                     var video_obj = this;
    58                     //ajax call
    59                     $.post(my_ajax_obj.ajax_url, {         //POST request
    60                         _ajax_nonce: my_ajax_obj.nonce,     //nonce
    61                         action: "bbpl_get_video_time",            //action
    62                         video: this.src,                    //video url
    63                         },function(data) {                    //callback
    64                             if (data[0] < video_obj.duration)
    65                                 video_obj.currentTime = data[0];
    66                         }
    67                     );
    68                 }
    69                 // Get the time from localStorage and play if not at the end.
    70                 else if (storedtime < this.duration){
    71                     this.currentTime = storedtime;
     58        } // End if first time
     59
     60        this.play();
     61    });
     62
     63    // On finished video mark as played
     64    bvideo.on('ended', function(e) {
     65        markPlayedVideo(this);
     66    });
     67
     68    /**
     69     * Playlist player for 1 video HTML tag
     70     */
     71    let bvideo_playlist = $('#bvideo_playlist');
     72
     73    if (bvideo_playlist.length) {
     74        let currentUrl = btoa(window.location.href.split('?')[0].split('#')[0]);
     75        let videoList  = getVideoList();
     76
     77        // Playlist video player
     78        if (typeof videoList !== 'undefined') {
     79            // Start video from parameter ID
     80            let startVideo = new URLSearchParams(window.location.search).get('start_video');
     81            if (startVideo !== null && $.isNumeric(startVideo))
     82                idCurrent = startVideo - 1; // We start counting from 1 so we do not use 0.
     83            else // Init video at last play
     84                idCurrent = localStorage.getItem('bvideo-playlist-' + currentUrl);
     85            idCurrent = ($.isNumeric(idCurrent)) ? idCurrent : 0;
     86            idCurrent = (idCurrent > videoList.length - 1) ? 0 : idCurrent;
     87
     88            // gets the data from an A tag using the data attribute
     89            currentLinkVideo = $('a[data-bvideo_id~="' + idCurrent + '"]');
     90
     91            // Current video playing
     92            localStorage.setItem('bvideo-playlist-' + currentUrl, idCurrent);
     93
     94            // Setup player to play current video
     95            bvideo.attr({
     96                "id": "bvideo",
     97                "src": currentLinkVideo.attr("href"),
     98                "data-bvideo_id": idCurrent // Which video are we playing
     99            });
     100
     101            // Change title for video playing
     102            $('#bvideo_title').text(currentLinkVideo.text());
     103
     104            listVideoHighlight(currentLinkVideo);
     105
     106            // On finished video, play next
     107            bvideo.on('ended', function(e) {
     108
     109                // Current ID, using attribute since data gets cached and we are updating it
     110                id = parseInt($(this).attr("data-bvideo_id"));
     111
     112                // Icon marked played
     113                if (config.playedVideoEmoji != '')
     114                    currentLinkVideo.parent().prepend(config.playedVideoEmoji);
     115
     116                // Remove background color
     117                if (config.playingBackgroundColor != '')
     118                    currentLinkVideo.parent().css("background-color", "");
     119
     120                // What to play next
     121                idNext = (id == videoList.length - 1) ? 0 : id + 1;
     122
     123                // Getting the source of the a
     124                videoNext = $('a[data-bvideo_id~="' + idNext + '"]');
     125
     126                $(this).attr({
     127                    "src": videoNext.attr("href"),
     128                    "data-bvideo_id": idNext // Which video are we playing
     129                });
     130
     131                if (config.autoplay == 1)
     132                    $(this).attr("autoplay", "autoplay");
     133
     134                // Remember next video
     135                localStorage.setItem('bvideo-playlist-' + currentUrl, idNext);
     136
     137                // Change title for video playing
     138                $('#bvideo_title').text(videoNext.text());
     139
     140                listVideoHighlight(videoNext);
     141            });
     142
     143            // Sets the source of the video from an ahref
     144            $("#bvideo_playlist a[target!='_blank']").on("click", function(e) {
     145
     146                // We prevent any default action, so we do not go to the URL
     147                e.preventDefault();
     148
     149                bvideo.attr({
     150                    "src": $(this).attr("href"),
     151                    "data-bvideo_id": $(this).data("bvideo_id") // Which video are we playing
     152                });
     153
     154                if (config.autoplay == true)
     155                    bvideo.attr("autoplay", "autoplay");
     156
     157                // Scroll to video
     158                if ($('#bvideo_title').length) // Location.href = "#bvideo_title";
     159                    document.querySelector('#bvideo_title').scrollIntoView({
     160                        behavior: 'smooth'
     161                    });
     162                else // Location.href = "#bvideo";
     163                    document.querySelector('#bvideo').scrollIntoView({
     164                        behavior: 'smooth'
     165                    });
     166
     167                // Remember last video
     168                localStorage.setItem('bvideo-playlist-' + currentUrl, $(this).data("bvideo_id"));
     169
     170                // Change title for video playing
     171                $('#bvideo_title').text($(this).text());
     172
     173                listVideoHighlight($(this));
     174
     175            });
     176
     177        }
     178    }
     179
     180
     181    /**
     182     * generates the videoList used for the play list
     183     * if uses ARRAY JS generates the inner LI HTML
     184     * @return Array videoList
     185     */
     186    function getVideoList(){
     187        let videoList = [];
     188
     189        // 1st way to load the playlist comes from a playlist JS array
     190        if (typeof directLinkData !== 'undefined' || typeof video_playlist !== 'undefined') {
     191            // In case there's a default playlist array
     192            if (typeof video_playlist !== 'undefined') {
     193                videoList = video_playlist;
     194            }
     195
     196            // Loading playlist from a pCloud array, in a public folder view page use the directLinkData array embedded in the HTML
     197            if (typeof directLinkData !== 'undefined') {
     198                // Create the list of links
     199                let pCloud = directLinkData.content;
     200                let path = 'https://filedn.eu/' + directLinkData.code + directLinkData.dirpath;
     201
     202                for (i = 0; i < pCloud.length; i++) {
     203                    let temp = [];
     204                    temp["name"] = pCloud[i].name.slice(0, -4);
     205                    temp["link"] = path + pCloud[i].urlencodedname;
     206                    temp["size"] = pCloud[i].size;
     207                    videoList.push(temp);
    72208                }
    73209            }
    74         }//end if first time
    75 
    76         this.play();
    77     });   
    78 
    79     /**
    80      * Playlist player for 1 video HTML tag
    81      */
    82    
    83     if ($('#bvideo_playlist').length )
    84     {
    85         var video_list = [];
    86         var current_url = btoa(window.location.href.split('?')[0].split('#')[0]);
    87 
    88         // 1st way to load the playlist comes from a plylist JS array
    89         if (typeof directLinkData !== 'undefined' || typeof video_playlist !== 'undefined')
    90         {
    91             //in case there's a default playlist array
    92             if (typeof video_playlist !== 'undefined'){
    93                 video_list = video_playlist;           
     210
     211            // From array videoList to a table
     212            let htmlList = "";
     213            for (i = 0; i < videoList.length; i++) {
     214
     215                htmlList += '<li>';
     216
     217                if (isPlayedVideo(videoList[i].link))
     218                    htmlList += config.playedVideoEmoji;
     219
     220                htmlList += '<a data-bvideo_id="' + i + '" href="' + videoList[i].link + '" title="' + videoList[i].name + '">' + videoList[i].name + '</a>';
     221
     222                if (videoList[i].size != undefined) {
     223                    videoSize = (videoList[i].size != undefined ? fileSize(videoList[i].size) : '-')
     224                    htmlList += '<span style="float:right;"><a target="_blank" title="' + videoSize + ' Download" download href="' + videoList[i].link + '">' + config.downloadEmoji + '</a></span>';
     225                }
     226
     227                htmlList += '</li>';
    94228            }
    95229
    96             // loading playlist from a pcloud array, in a public folder view page use the directLinkData array embeded in the HTML
    97             if (typeof directLinkData !== 'undefined')
    98             {
    99                 //created the list of links
    100                 var pcloud = directLinkData.content;
    101                 var path   = 'https://filedn.eu/'+directLinkData.code+directLinkData.dirpath;
    102 
    103                 for (i=0; i<pcloud.length; i++)
    104                 {
    105                     var temp = [];
    106                     temp["name"] = pcloud[i].name.slice(0, -4);
    107                     temp["link"] = path+pcloud[i].urlencodedname;
    108                     temp["size"] = pcloud[i].size;
    109                     video_list.push(temp);
    110                 }
    111 
    112             }
    113 
    114             // from array video_list to a table
    115             var html_list = "";
    116             for (i=0; i<video_list.length; i++) {
    117 
    118                 html_list+='<li>';
    119 
    120                 if (is_played_video(video_list[i].link))
    121                     html_list+='&#10004;&nbsp;';
    122 
    123                 html_list+='<a data-bvideo_id="'+i+'" href="'+video_list[i].link+'" title="'+video_list[i].name+'">'+video_list[i].name+'</a>';
    124                
    125                 if (video_list[i].size!=undefined)
    126                 {
    127                     video_size = (video_list[i].size!=undefined?fileSize(video_list[i].size):'-')
    128                     html_list+='<span style="float:right;"><a target="_blank" title="'+video_size+' Download" download href="'+video_list[i].link+'">💾</a></span>';
    129                 }
    130 
    131                 html_list+='</li>';
    132             }
    133 
    134             //print html
    135             $("#bvideo_playlist").html(html_list);
    136             $("#bvideo_playlist").parent().css(  {
    137                                           "height":$("video").height()+120,
    138                                           "overflow-y": "auto"
    139                                         });
    140 
    141         }
    142 
    143         // 2nd way to get a playlist load video_list array from a list instead than JS array   
    144         else if($('#bvideo_playlist').is('ol, ul'))
    145         {
    146             var video_list = [];
    147             $("#bvideo_playlist li a").each(function(e) {
     230            // Print HTML
     231            bvideo_playlist.html(htmlList);
     232            bvideo_playlist.parent().css({
     233                "height": bvideo.height() + 120,
     234                "overflow-y": "auto"
     235            });
     236
     237        }
     238
     239        // 2nd way to get a playlist: load videoList array from a list instead than JS array   
     240        else if (bvideo_playlist.is('ol, ul')) {
     241            videoList = [];
     242            $("#bvideo_playlist li a").each(function(e) {
    148243                a = $(this);
    149                 a.attr('data-bvideo_id',e);
    150                 var temp = [];
    151                     temp["name"] = this.text;
    152                     temp["link"] = this.href;
    153                     temp["size"] = a.data('size')!==undefined?a.data('size'):0;
    154                 video_list.push(temp);
    155             });
    156         }
    157 
    158         // playlist video player
    159         if (typeof video_list !== 'undefined')
    160         {
    161             //start video from parameeter ID....
    162             var start_video = new URLSearchParams(window.location.search).get('start_video');
    163             if (start_video!==null && $.isNumeric(start_video))
    164                 id_current = start_video-1;//we start counting from 1 so we do not use the 0.
    165             else//init video at last play
    166                 id_current = localStorage.getItem('bvideo-'+current_url);
     244                a.attr('data-bvideo_id', e);
     245
     246                // Icon marked played
     247                if (config.playedVideoEmoji != '' && isPlayedVideo(this.href) )
     248                    a.parent().prepend(config.playedVideoEmoji);
     249
     250                let temp = {};
     251                temp["name"] = this.text;
     252                temp["link"] = this.href;
     253                temp["size"] = a.data('size') !== undefined ? a.data('size') : 0;
     254                videoList.push(temp);
     255            });
    167256           
    168             id_current = ($.isNumeric(id_current))?id_current:0;
    169             id_current = (id_current > video_list.length-1)?0:id_current;
    170 
    171             current_video = $('a[data-bvideo_id~="'+id_current+'"]');
    172 
    173             //current video playing
    174             localStorage.setItem('bvideo-'+current_url, id_current);
    175 
    176             //setup player to play current video
    177             $("video").attr({
    178                 "id":"bvideo",
    179                 "src": current_video.attr("href"),
    180                 "data-bvideo_id":id_current//which video are we playing
    181             });
    182            
    183             //change title for video playing
    184             $('#bvideo_title').text(current_video.text());
    185 
    186             //highlight
    187             current_video.parent().css("background-color","#eeeeee");
    188 
    189 
    190             //on finished video play next
    191             $("video").on('ended', function(e){
    192 
    193                 //current id,using attribute since data gets cached and we are updating it
    194                 id = parseInt($(this).attr("data-bvideo_id"));
    195 
    196                 //we mark this video as played
    197                 mark_played_video(id);
    198                
    199                 //what to play next
    200                 id_next = (id == video_list.length-1)?0:id+1;
    201 
    202                 //getting the source of the a
    203                 src = $('a[data-bvideo_id~="'+id_next+'"]');
    204 
    205                 $(this).attr({
    206                     "src": src.attr("href"),
    207                     "autoplay": "autoplay",
    208                     "data-bvideo_id":id_next //which video are we playing
    209                 });
    210 
    211                 //remember next video
    212                 localStorage.setItem('bvideo-'+current_url, id_next);
    213 
    214                 //change title for video playing
    215                 $('#bvideo_title').text(src.text());
    216 
    217                 //highlight whats currently playing
    218                 //$(this).parent().prepend('▶️&nbsp;');
    219                 $('#bvideo_playlist li').css("background-color","");
    220                 src.parent().css("background-color","#eeeeee");
    221             });
    222 
    223             //sets the source of the video from an ahref
    224             $("#bvideo_playlist a[target!='_blank']").on("click", function(e) {
    225 
    226                 //we prevent any default action, so we do not go to the url
    227                 e.preventDefault();
    228 
    229                 $("video").attr({
    230                     "src": $(this).attr("href"),
    231                     "autoplay": "autoplay",
    232                     "data-bvideo_id":$(this).data("bvideo_id") //which video are we playing
    233                 });
    234 
    235                 //scroll to video
    236                 if ($('#bvideo_title').length )//location.href = "#bvideo_title";
    237                     document.querySelector('#bvideo_title').scrollIntoView({behavior: 'smooth'});
    238                    
    239                 else//location.href = "#bvideo";
    240                     document.querySelector('#bvideo').scrollIntoView({behavior: 'smooth'});
    241 
    242                 //remember last video
    243                 localStorage.setItem('bvideo-'+current_url, $(this).data("bvideo_id"));
    244 
    245                 //change title for video playing
    246                 $('#bvideo_title').text($(this).text());
    247 
    248                 //highlight whats currently playing
    249                 //$(this).parent().prepend('▶️&nbsp;');
    250                 $('#bvideo_playlist li').css("background-color","");
    251                 $(this).parent().css("background-color","#eeeeee");
    252             });
     257        }
     258
     259        return videoList;
     260    }
     261
     262
     263    /**
     264     * store video time in local and WP
     265     * @param   video
     266     * @param   time we can specify the time we store. For instance -1 means video played.
     267     */
     268    function storeVideoTime(video, time = false){
     269        //time not set then using video current
     270        if (time==false)
     271            time = video.currentTime;
     272
     273        // Save into local storage; if you change the browser, it will not work
     274        localStorage.setItem('bvideo-' + btoa(video.src), time);
     275
     276        // Ajax call
     277        $.post(betterVideo_ajax.ajax_url, {
     278            _ajax_nonce: betterVideo_ajax.nonce, // Nonce
     279            action: "bbpl_store_video_time", // Action
     280            time: time, // Time
     281            video: video.src, // Video URL
     282        }).fail(handleAjaxError);
     283    }
     284
     285    /**
     286     * get the video time from a SRC
     287     * @param  video
     288     * @return integer
     289     */
     290    function getVideoTime(video){
     291        storedTime = getVideoTimeSrc(video.src);
     292        if (storedTime > video.duration)
     293            storedTime = 0;
     294
     295        return storedTime;
     296    }
     297
     298
     299    function getVideoTimeSrc(videoSrc){
     300        // First, retrieve from local storage
     301        let storedTime = localStorage.getItem('bvideo-' + btoa(videoSrc));
     302
     303        // TODO needed improvement here!!
     304        // Only Ajax if stored time is empty, saves queries
     305        // but we may have different values if used in different browsers
     306        if (storedTime == null) {
     307            // Ajax call
     308            $.post(betterVideo_ajax.ajax_url, {
     309                _ajax_nonce: betterVideo_ajax.nonce, // Nonce
     310                action: "bbpl_get_video_time", // Action
     311                video: videoSrc, // Video URL
     312            }, function(data) { // Callback
     313                storedTime = data[0];
     314            }).fail(handleAjaxError);
     315        }
    253316       
    254         }
    255 
    256         /**
    257          * we mark a video as played, we use the btoa of the current url and we store the btoa of the video src
    258          * @param  id_video we get the src from the a
    259          */
    260         function mark_played_video(id_video)
    261         {
    262             //getting the source of the a
    263             a = $('a[data-bvideo_id~="'+id_video+'"]');
    264             src = a.attr("href");
    265 
    266             // if it was not in the array before, then store
    267             if(is_played_video(src) == false)
    268             { 
    269                 var watched_videos;
    270 
    271                 watched_videos = localStorage.getItem('bvideo-played-'+ current_url);
    272 
    273                 if (watched_videos == null)
    274                     watched_videos = [];
    275                 else
    276                     watched_videos = JSON.parse(watched_videos);
    277 
    278                 watched_videos.push(btoa(src));
    279                 localStorage.setItem('bvideo-played-'+ current_url, JSON.stringify(watched_videos));
    280 
    281                 //icon marked played
    282                 a.parent().prepend('&#10004;&nbsp;');
    283                 //remove backgorund color
    284                 a.parent().css("background-color","");
    285             }
    286         }
    287 
    288         /**
    289          * tells us if we have seen that video in this url
    290          * @param  string btoa src of the video
    291          * @return boolean   
    292          */
    293         function is_played_video(src)
    294         {
    295             watched_videos = localStorage.getItem('bvideo-played-'+ current_url);
    296 
    297             if (watched_videos == null)
    298                 return false;
    299 
    300             watched_videos = JSON.parse(watched_videos);
    301 
    302             if( watched_videos.indexOf(btoa(src)) != -1 )
    303                 return true;
    304             else
    305                 return false;
    306         }
    307    
    308     }
     317        return storedTime;
     318    }
     319
     320    /**
     321     * video is marked as played using -1
     322     * @param   video
     323     */
     324    function markPlayedVideo(video){
     325
     326        if (isPlayedVideo(video.src) == false)
     327            storeVideoTime(video,-1);
     328    }
     329
     330    /**
     331     * Tells us if we have seen that video in this URL
     332     * @param  string btoa src of the video
     333     * @return boolean   
     334     */
     335    function isPlayedVideo(videoSrc) {
     336        return getVideoTimeSrc(videoSrc) == -1;
     337    }
     338
     339    /**
     340     * Highlights the item on the playlist to know what is been playing
     341     * @return none
     342     */
     343    function listVideoHighlight(linkList) {
     344        // Highlight what's currently playing
     345        if (config.playingEmoji != '') {
     346            $("#bvideoCurrentVideoEmoji").remove();
     347            linkList.parent().prepend('<span id="bvideoCurrentVideoEmoji">' + config.playingEmoji + '&nbsp;</span>');
     348        }
     349        if (config.playingBackgroundColor != '') {
     350            $(".bvideoCurrentVideoColor").css("background-color", "");
     351            linkList.parent().addClass('bvideoCurrentVideoColor');
     352            linkList.parent().css("background-color", config.playingBackgroundColor);
     353        }
     354    }
     355
     356    // AJAX error handling function
     357    function handleAjaxError(xhr, textStatus, errorThrown) {
     358        console.error("AJAX Error: " + textStatus);
     359        console.error("Error Details: " + errorThrown);
     360    }
     361
    309362
    310363})
    311364
    312 //from https://stackoverflow.com/a/20463021
    313 function fileSize(a,b,c,d,e)
    314 {
    315     return (b=Math,c=b.log,d=1e3,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(e?2:0)+' '+(e?'kMGTPEZY'[--e]+'B':'Bytes')
     365// From https://stackoverflow.com/a/20463021
     366function fileSize(a, b, c, d, e) {
     367    return (b = Math, c = b.log, d = 1e3, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(e ? 2 : 0) + ' ' + (e ? 'kMGTPEZY'[--e] + 'B' : 'Bytes')
    316368}
Note: See TracChangeset for help on using the changeset viewer.