Skip to:
Content

BuddyPress.org

Ticket #5548: 5548.patch

File 5548.patch, 20.1 KB (added by imath, 6 years ago)
  • src/bp-core/admin/bp-core-settings.php

    diff --git src/bp-core/admin/bp-core-settings.php src/bp-core/admin/bp-core-settings.php
    index e112df7..23f040a 100644
    function bp_admin_setting_callback_avatar_uploads() { 
    185185<?php
    186186}
    187187
     188/**
     189 * Allow members to use their device's camera
     190 *
     191 * @since BuddyPress (2.1.0)
     192 *
     193 * @uses checked() To display the checked attribute
     194 */
     195function bp_admin_setting_callback_webcam_avatars() {
     196?>
     197
     198        <input id="bp-enable-webcam-avatars" name="bp-enable-webcam-avatars" type="checkbox" value="1" <?php checked( bp_enable_webcam_avatars( false ) ); ?> />
     199        <label for="bp-enable-webcam-avatars"><?php _e( 'Allow members to use it to upload their avatars', 'buddypress' ); ?></label>
     200
     201<?php
     202}
     203
    188204/** Groups Section ************************************************************/
    189205
    190206/**
  • src/bp-core/bp-core-admin.php

    diff --git src/bp-core/bp-core-admin.php src/bp-core/bp-core-admin.php
    index 8942a82..5677ec3 100644
    class BP_Admin { 
    398398                    // Allow avatar uploads
    399399                    add_settings_field( 'bp-disable-avatar-uploads', __( 'Avatar Uploads',   'buddypress' ), 'bp_admin_setting_callback_avatar_uploads',   'buddypress', $avatar_setting );
    400400                    register_setting  ( 'buddypress',         'bp-disable-avatar-uploads',   'intval'                                                                                    );
     401
     402                    if ( 'bp_xprofile' == $avatar_setting ) {
     403                                add_settings_field( 'bp-enable-webcam-avatars', __( 'Member&#39;s device camera',   'buddypress' ), 'bp_admin_setting_callback_webcam_avatars',   'buddypress', $avatar_setting );
     404                        register_setting  ( 'buddypress',               'bp-enable-webcam-avatars',   'intval'                                                                                          );
     405                    }
    401406                }
    402407        }
    403408
  • src/bp-core/bp-core-avatars.php

    diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php
    index 93e7781..f89f009 100644
    function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
    677677}
    678678
    679679/**
     680 * Handle avatar webcam capture.
     681 *
     682 * @since BuddyPress (2.1.0)
     683 *
     684 * @param string $data base64 encoded image.
     685 * @param int $item_id.
     686 * @return bool True on success, false on failure.
     687 */
     688function bp_core_avatar_handle_capture( $data = '', $item_id = 0 ) {
     689        if ( empty( $data ) || empty( $item_id ) ) {
     690                return false;
     691        }
     692
     693        $avatar_dir = bp_core_avatar_upload_path() . '/avatars';
     694
     695        if( ! file_exists( $avatar_dir ) ) {
     696                mkdir( $avatar_dir );
     697        }
     698
     699        $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $avatar_dir . '/' . $item_id, $item_id, 'user', 'avatars' );
     700       
     701        if( ! file_exists( $avatar_folder_dir ) ) {
     702                mkdir( $avatar_folder_dir );
     703        }
     704
     705        $original_file = $avatar_folder_dir . '/webcam-capture-' . $item_id . '.png';
     706
     707        if ( file_put_contents( $original_file, $data ) ) {
     708                $avatar_to_crop = str_replace( bp_core_avatar_upload_path(), '', $original_file );
     709               
     710                // Fake a crop
     711                $crop_args = array( 'item_id' => $item_id, 'original_file' => $avatar_to_crop, 'crop_x' => 0, 'crop_y' => 0 );
     712
     713                return bp_core_avatar_handle_crop( $crop_args );
     714        } else {
     715                return false;
     716        }
     717}
     718
     719/**
    680720 * Crop an uploaded avatar.
    681721 *
    682722 * $args has the following parameters:
  • src/bp-core/bp-core-cssjs.php

    diff --git src/bp-core/bp-core-cssjs.php src/bp-core/bp-core-cssjs.php
    index b9acd5a..fbacae0 100644
    function bp_core_register_common_scripts() { 
    2727       
    2828        // Array of common scripts
    2929        $scripts = apply_filters( 'bp_core_register_common_scripts', array(
    30                 'bp-confirm'          => 'confirm',
    31                 'bp-widget-members'   => 'widget-members',
    32                 'bp-jquery-query'     => 'jquery-query',
    33                 'bp-jquery-cookie'    => 'jquery-cookie',
    34                 'bp-jquery-scroll-to' => 'jquery-scroll-to',
     30                'bp-confirm'          => array( 'file' => 'confirm',          'footer' => false ),
     31                'bp-widget-members'   => array( 'file' => 'widget-members',   'footer' => false ),
     32                'bp-jquery-query'     => array( 'file' => 'jquery-query',     'footer' => false ),
     33                'bp-jquery-cookie'    => array( 'file' => 'jquery-cookie',    'footer' => false ),
     34                'bp-jquery-scroll-to' => array( 'file' => 'jquery-scroll-to', 'footer' => false ),
     35                'bp-webcam-avatar'    => array( 'file' => 'webcam-avatar',    'footer' => true  ),
    3536        ) );
    3637
    3738        // Register scripts commonly used by BuddyPress themes
    38         foreach ( $scripts as $id => $file ) {
    39                 wp_register_script( $id, $url . $file . $min, array( 'jquery' ), $ver );
     39        foreach ( $scripts as $id => $script ) {
     40                wp_register_script( $id, $url . $script['file'] . $min, array( 'jquery' ), $ver, $script['footer'] );
    4041        }
    4142}
    4243add_action( 'bp_enqueue_scripts', 'bp_core_register_common_scripts', 1 );
  • src/bp-core/bp-core-options.php

    diff --git src/bp-core/bp-core-options.php src/bp-core/bp-core-options.php
    index 580ceb1..da14f3a 100644
    function bp_disable_avatar_uploads( $default = true ) { 
    472472}
    473473
    474474/**
     475 * Are members able to use their device's camera ?
     476 *
     477 * @since BuddyPress (2.1.0)
     478 *
     479 * @uses bp_get_option() To get the avatar uploads option.
     480 *
     481 * @param bool $default Optional. Fallback value if not found in the database.
     482 *        Default: true.
     483 * @return bool True if using device's camera is allowed, otherwise false.
     484 */
     485function bp_enable_webcam_avatars( $default = false ) {
     486        return (bool) apply_filters( 'bp_enable_webcam_avatars', (bool) bp_get_option( 'bp-enable-webcam-avatars', $default ) );
     487}
     488
     489/**
    475490 * Are members able to delete their own accounts?
    476491 *
    477492 * @since BuddyPress (1.6.0)
  • src/bp-core/js/webcam-avatar.js

    diff --git src/bp-core/js/webcam-avatar.js src/bp-core/js/webcam-avatar.js
    index e69de29..51ef091 100644
     
     1/**
     2 * WebCam Avatars
     3 */
     4( function( $ ) {
     5
     6        var explain = $( 'body.change-avatar div.profile p').first().html(),
     7                video = $( '#bp-webcam-video' ).get(0),
     8                canvas = $( '#bp-webcam-canvas' ).get(0),
     9                videoStream = null,
     10                capture_enable = save_enable = false,
     11                capture;
     12
     13        if ( navigator.getUserMedia || navigator.oGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia ) {
     14                $( 'body.change-avatar div.profile p').first().html( explain + ' ' + BP_WebCam_Avatar.alternative );
     15        }
     16
     17        $( 'body.change-avatar div.profile').on( 'click', '#bp-webcam', function( event ) {
     18                event.preventDefault();
     19
     20                $( '#bp-webcam-form' ).show();
     21                useStream();
     22        });
     23
     24
     25        function log( text, mclass ) {
     26                $( '#bp-webcam-message' ).html( '<p>' + text + '</p>' );
     27                $( '#bp-webcam-message' ).prop( 'class', '' );
     28                $( '#bp-webcam-message' ).addClass( mclass );
     29        }
     30
     31        $( '#bp-webcam-capture-btn').on( 'click', function( event ){
     32                event.preventDefault();
     33
     34                if( ! capture_enable ) {
     35                        log( BP_WebCam_Avatar.loading, 'info' );
     36                        return;
     37                } else {
     38
     39                        if ( $( '#bp-canvas-preview' ).length ) {
     40                                $( '#bp-canvas-preview' ).remove();
     41                                $( '#bp-webcam-canvas' ).addClass( 'noborder' );
     42                        }
     43
     44                        $( '.bp-webcam-canvas-container input[type="submit"]' ).removeClass( 'hide' );
     45                        canvas.width = video.videoWidth * 0.234375;
     46                        canvas.height = video.videoHeight * 0.3125;
     47                        canvas.getContext( '2d' ).drawImage( video, 80, 0, 480, 480, 0, 0, 150, 150 );
     48                        capture = canvas.toDataURL( "image/png" );
     49                        save_enable = true;
     50                        log( BP_WebCam_Avatar.ready, 'success' );
     51                        return;
     52                }
     53        } );
     54
     55        $( '#bp-webcam-form' ).on( 'submit', function( event ){
     56               
     57                $( '#bp-webcam-capture' ).val( capture );
     58                if ( ! $('#bp-webcam-capture').val().length ) {
     59                        event.preventDefault();
     60                        log( BP_WebCam_Avatar.nocapture, 'error' );
     61                        return;
     62                }
     63
     64        } );
     65       
     66        function noStream() {
     67                log( BP_WebCam_Avatar.noaccess, 'error' );
     68        }
     69
     70        function stop() {
     71                capture_enable = false;
     72                save_enable = true;
     73                if ( videoStream ) {
     74                        if (videoStream.stop) videoStream.stop();
     75                        else if (videoStream.msStop) videoStream.msStop();
     76                        videoStream.onended = null;
     77                        videoStream = null;
     78                }
     79                if ( video ) {
     80                        video.onerror = null;
     81                        video.pause();
     82                        if (video.mozSrcObject) {
     83                                video.mozSrcObject = null;
     84                        }                               
     85                        video.src = "";
     86                }
     87        }
     88
     89        function gotStream(stream) {
     90                videoStream = stream;
     91
     92                log( BP_WebCam_Avatar.loaded, 'success' );
     93               
     94                video.onerror = function () {
     95                        log( BP_WebCam_Avatar.videoerror, 'error' );
     96                        if (video) stop();
     97                };
     98
     99                stream.onended = noStream;
     100
     101                if ( window.webkitURL ) {
     102                        video.src = window.webkitURL.createObjectURL( stream );
     103                } else if ( video.mozSrcObject !== undefined ) {
     104                        video.mozSrcObject = stream;
     105                        video.play();
     106                } else if ( navigator.mozGetUserMedia ) {
     107                        video.src = stream;
     108                        video.play();
     109                } else if ( window.URL ) {
     110                        video.src = window.URL.createObjectURL( stream );
     111                } else {
     112                        video.src = stream;
     113                }
     114
     115                capture_enable = true;
     116        }
     117
     118        function useStream() {
     119                if ( ( typeof window === 'undefined') || ( typeof navigator === 'undefined' ) ) {
     120                        log( BP_WebCam_Avatar.errormsg, 'error' );
     121                } else if ( ! ( video && canvas ) ) {
     122                        log( BP_WebCam_Avatar.errormsg, 'error' );
     123                } else {
     124                        log( BP_WebCam_Avatar.requesting, 'info' );
     125                        if (navigator.getUserMedia) navigator.getUserMedia({video:true}, gotStream, noStream);
     126                        else if (navigator.oGetUserMedia) navigator.oGetUserMedia({video:true}, gotStream, noStream);
     127                        else if (navigator.mozGetUserMedia) navigator.mozGetUserMedia({video:true}, gotStream, noStream);
     128                        else if (navigator.webkitGetUserMedia) navigator.webkitGetUserMedia({video:true}, gotStream, noStream);
     129                        else if (navigator.msGetUserMedia) navigator.msGetUserMedia({video:true, audio:false}, gotStream, noStream);
     130                }
     131        }
     132
     133} )( jQuery );
  • src/bp-templates/bp-legacy/css/buddypress.css

    diff --git src/bp-templates/bp-legacy/css/buddypress.css src/bp-templates/bp-legacy/css/buddypress.css
    index 36a16c7..b6c0ec9 100644
    body.register #buddypress div.page ul { 
    14411441        margin: 0;
    14421442}
    14431443
     1444/* WebCam Avatar */
     1445#buddypress #bp-webcam-form{
     1446        width:410px;
     1447        margin:0 auto;
     1448        overflow: hidden;
     1449        display: none;
     1450}
     1451
     1452#buddypress #bp-webcam-form .bp-webcam-video-container,
     1453#buddypress #bp-webcam-form .bp-webcam-canvas-container {
     1454        position:relative;
     1455        float:left;
     1456        width:200px;
     1457        margin-right:5px;
     1458}
     1459
     1460#buddypress #bp-webcam-form .bp-webcam-video-container input,
     1461#buddypress #bp-webcam-form .bp-webcam-canvas-container input {
     1462        display:block;
     1463        text-align:center;
     1464        margin:0 auto;
     1465}
     1466
     1467#buddypress #bp-webcam-form .bp-webcam-canvas-container input.hide {
     1468        display:none;
     1469}
     1470
     1471#buddypress #bp-webcam-form .bp-webcam-video-container #bp-webcam-mask-left,
     1472#buddypress #bp-webcam-form .bp-webcam-video-container #bp-webcam-mask-right{
     1473        position:absolute;
     1474        background:#FFF;
     1475        z-index:10000;
     1476        width:25px;
     1477        height:150px;
     1478        top:0;
     1479}
     1480
     1481#buddypress #bp-webcam-form .bp-webcam-video-container #bp-webcam-mask-left{
     1482        left:0;
     1483}
     1484#buddypress #bp-webcam-form .bp-webcam-video-container #bp-webcam-mask-right{
     1485        left:175px;
     1486}
     1487#buddypress #bp-webcam-form .bp-webcam-video-container #bp-webcam-video{
     1488        height:150px;
     1489        margin-bottom:15px;
     1490}
     1491#buddypress #bp-webcam-form .bp-webcam-canvas-container #bp-webcam-canvas{
     1492        width:150px;
     1493        height:150px;
     1494        border:dashed 4px #eee;
     1495        display:block;
     1496        margin:0 auto;
     1497        margin-bottom:15px;
     1498}
     1499
     1500#buddypress #bp-webcam-form .bp-webcam-canvas-container #bp-webcam-canvas.noborder {
     1501        border:none;
     1502}
     1503
     1504#buddypress #bp-webcam-form .bp-webcam-canvas-container #bp-canvas-preview{
     1505        position:absolute;
     1506        line-height: 150px;
     1507        top:0px;
     1508        text-align:center;
     1509        width:100%;
     1510}
     1511
     1512#buddypress #bp-webcam-form #bp-webcam-message {
     1513        margin: 0 0 15px;
     1514}
     1515
     1516#buddypress #bp-webcam-form #bp-webcam-message p {
     1517        padding: 10px 15px;
     1518}
     1519
     1520#buddypress #bp-webcam-form #bp-webcam-message.info p {
     1521        background-color: #ffd;
     1522        border: 1px solid #cb2;
     1523        color: #440;
     1524}
     1525
     1526#buddypress #bp-webcam-form #bp-webcam-message.error p {
     1527        background-color: #fdc;
     1528        border: 1px solid #a00;
     1529        color: #800;
     1530}
     1531
     1532#buddypress #bp-webcam-form #bp-webcam-message.success p {
     1533        background-color: #efc;
     1534        border: 1px solid #591;
     1535        color: #250;
     1536}
     1537
    14441538/*--------------------------------------------------------------
    144515393.11 - Widgets
    14461540--------------------------------------------------------------*/
  • src/bp-xprofile/bp-xprofile-cssjs.php

    diff --git src/bp-xprofile/bp-xprofile-cssjs.php src/bp-xprofile/bp-xprofile-cssjs.php
    index 8fb4f67..9b41382 100644
    function xprofile_add_admin_js() { 
    4242        }
    4343}
    4444add_action( 'admin_enqueue_scripts', 'xprofile_add_admin_js', 1 );
     45
     46/**
     47 * Enqueue the jQuery libraries for handling webcam avatar uploads
     48 *
     49 * @since BuddyPress (2.1.0)
     50 */
     51function bp_xprofile_add_webcam_avatar_js() {
     52        if ( ! bp_enable_webcam_avatars() || ! bp_is_user_change_avatar() || 'upload-image' != bp_get_avatar_admin_step() ) {
     53                return false;
     54        }
     55
     56        wp_enqueue_script( 'bp-webcam-avatar' );
     57        wp_localize_script( 'bp-webcam-avatar', 'BP_WebCam_Avatar', array(
     58                'alternative' => __( 'You can also use your <a href="#" id="bp-webcam">device&#39;s camera</a>.', 'buddypress' ),
     59                'requesting'  => __( 'Requesting video stream, please authorize this website to access to your camera.', 'buddypress'),
     60                'loading'     => __( 'Please wait for the video to load.', 'buddypress' ),
     61                'loaded'      => __( 'Video stream loaded. You can use the capture button to display the avatar preview.', 'buddypress' ),
     62                'noaccess'    => __( 'You denied this website to access to your camera. Please use the upload form.', 'buddypress' ),
     63                'errormsg'    => __( 'Your browser is not supported. Please use the upload form.', 'buddypress' ),
     64                'videoerror'  => __( 'Video error. Please use the upload form.', 'buddypress' ),
     65                'ready'       => __( 'Avatar ready, use the save button to validate.', 'buddypress' ),
     66                'preview'     => __( 'Preview', 'buddypress' ),
     67                'nocapture'   => __( 'No avatar was captured, please try again.', 'buddypress' ),
     68        ) );
     69}
     70add_action( 'bp_enqueue_scripts', 'bp_xprofile_add_webcam_avatar_js' );
  • src/bp-xprofile/bp-xprofile-screens.php

    diff --git src/bp-xprofile/bp-xprofile-screens.php src/bp-xprofile/bp-xprofile-screens.php
    index 380aac7..8137730 100644
    function xprofile_screen_change_avatar() { 
    189189                }
    190190        }
    191191
     192        $avatar_message = array();
     193
     194        // Handle the capture of WebCam Avatars
     195        if ( ! empty( $_POST['save-webcam-avatar'] ) ) {
     196                // Check the nonce
     197                check_admin_referer( 'bp_webcam_avatar', '_webcam_avatar_nonce' );
     198
     199                $webcam_avatar = false;
     200
     201                if ( ! empty( $_POST['_bp_webcam_capture'] ) ) {
     202                        $webcam_avatar = str_replace( array( 'data:image/png;base64,', ' ' ), array( '', '+' ), $_POST['_bp_webcam_capture'] );
     203                        $webcam_avatar = base64_decode( $webcam_avatar );
     204                }
     205
     206                if ( ! bp_core_avatar_handle_capture( $webcam_avatar, bp_displayed_user_id() ) ) {
     207                        $avatar_message = array( 'error' => __( 'There was a problem saving that avatar, please try again.', 'buddypress' ) );
     208                } else {
     209                        $avatar_message = array( 'success' => __( 'Your new avatar was uploaded successfully.', 'buddypress' ) );
     210                }
     211        }
     212
    192213        // If the image cropping is done, crop the image and save a full/thumb version
    193214        if ( isset( $_POST['avatar-crop-submit'] ) ) {
    194215
    function xprofile_screen_change_avatar() { 
    205226                );
    206227
    207228                if ( ! bp_core_avatar_handle_crop( $args ) ) {
    208                         bp_core_add_message( __( 'There was a problem cropping your avatar.', 'buddypress' ), 'error' );
     229                        $avatar_message = array( 'error' => __( 'There was a problem cropping your avatar.', 'buddypress' ) );
    209230                } else {
     231                        $avatar_message = array( 'success' =>  __( 'Your new avatar was uploaded successfully.', 'buddypress' ) );
     232                }
     233        }
     234
     235        if ( ! empty( $avatar_message ) ) {
     236                if ( ! empty( $avatar_message['success'] ) ) {
    210237                        do_action( 'xprofile_avatar_uploaded' );
    211                         bp_core_add_message( __( 'Your new avatar was uploaded successfully.', 'buddypress' ) );
     238                        bp_core_add_message( $avatar_message['success'] );
    212239                        bp_core_redirect( bp_displayed_user_domain() );
     240                } else {
     241                        bp_core_add_message( $avatar_message['error'], 'error' );
    213242                }
    214243        }
    215244
  • src/bp-xprofile/bp-xprofile-template.php

    diff --git src/bp-xprofile/bp-xprofile-template.php src/bp-xprofile/bp-xprofile-template.php
    index 1d69313..173a4c4 100644
    function bp_profile_group_name( $deprecated = true ) { 
    627627                return apply_filters( 'bp_get_profile_group_name', $group->name );
    628628        }
    629629
    630 function bp_avatar_upload_form() {
    631         global $bp;
    632 
    633         if ( !(int) $bp->site_options['bp-disable-avatar-uploads'] )
    634                 bp_core_avatar_admin( null, bp_loggedin_user_domain() . $bp->profile->slug . '/change-avatar/', bp_loggedin_user_domain() . $bp->profile->slug . '/delete-avatar/' );
    635         else
    636                 _e( 'Avatar uploads are currently disabled. Why not use a <a href="http://gravatar.com" target="_blank">gravatar</a> instead?', 'buddypress' );
    637 }
    638 
    639630function bp_profile_last_updated() {
    640631
    641632        $last_updated = bp_get_profile_last_updated();
    function bp_current_profile_group_id() { 
    666657                return apply_filters( 'bp_get_current_profile_group_id', $profile_group_id ); // admin/profile/edit/[group-id]
    667658        }
    668659
    669 function bp_avatar_delete_link() {
    670         echo bp_get_avatar_delete_link();
    671 }
    672         function bp_get_avatar_delete_link() {
    673                 global $bp;
    674 
    675                 return apply_filters( 'bp_get_avatar_delete_link', wp_nonce_url( bp_displayed_user_domain() . $bp->profile->slug . '/change-avatar/delete-avatar/', 'bp_delete_avatar_link' ) );
    676         }
    677 
    678660function bp_edit_profile_button() {
    679661        global $bp;
    680662
    function bp_profile_settings_visibility_select( $args = '' ) { 
    815797                // Output the dropdown list
    816798                return apply_filters( 'bp_profile_settings_visibility_select', $retval, $r, $args );
    817799        }
     800
     801
     802/** Avatars ****************************************************************/
     803
     804function bp_avatar_upload_form() {
     805        global $bp;
     806
     807        if ( !(int) $bp->site_options['bp-disable-avatar-uploads'] )
     808                bp_core_avatar_admin( null, bp_loggedin_user_domain() . $bp->profile->slug . '/change-avatar/', bp_loggedin_user_domain() . $bp->profile->slug . '/delete-avatar/' );
     809        else
     810                _e( 'Avatar uploads are currently disabled. Why not use a <a href="http://gravatar.com" target="_blank">gravatar</a> instead?', 'buddypress' );
     811}
     812
     813function bp_avatar_delete_link() {
     814        echo bp_get_avatar_delete_link();
     815}
     816        function bp_get_avatar_delete_link() {
     817                global $bp;
     818
     819                return apply_filters( 'bp_get_avatar_delete_link', wp_nonce_url( bp_displayed_user_domain() . $bp->profile->slug . '/change-avatar/delete-avatar/', 'bp_delete_avatar_link' ) );
     820        }
     821
     822function bp_avatar_webcam() {
     823        echo bp_get_avatar_webcam();
     824}
     825add_action( 'bp_after_profile_avatar_upload_content', 'bp_avatar_webcam' );
     826
     827        function bp_get_avatar_webcam() {
     828                if ( ! bp_enable_webcam_avatars() || ! bp_is_user_change_avatar() || 'upload-image' != bp_get_avatar_admin_step() ) {
     829                        return false;
     830                }
     831
     832                $output = '<form action="" method="post" id="bp-webcam-form" class="standard-form">' . "\n";
     833                $output .= '<div id="bp-webcam-message"></div>' . "\n";
     834                $output .= '<div class="bp-webcam-video-container">' . "\n";
     835                $output .= '<video id="bp-webcam-video" autoplay="autoplay"></video>' . "\n";
     836                $output .= '<div id="bp-webcam-mask-left"></div>' . "\n";
     837                $output .= '<div id="bp-webcam-mask-right"></div>' . "\n";
     838                $output .= '<input type="button" id="bp-webcam-capture-btn" class="bp-primary-action" value="' . esc_html__( 'Capture', 'buddypress' ) .'"/>' . "\n";
     839                $output .= '</div>' . "\n";
     840
     841                $output .= '<div class="bp-webcam-canvas-container">';
     842                $output .= '<canvas id="bp-webcam-canvas"></canvas>';
     843                $output .= '<div id="bp-canvas-preview">'. esc_html__( 'Preview', 'buddypress' ) .'</div>';
     844                $output .= '<input type="submit" name="save-webcam-avatar" class="bp-primary-action hide" value="' . esc_html__( 'Save', 'buddypress' ) .'"/>' . "\n";
     845                $output .= '<input type="hidden" id="bp-webcam-capture" name="_bp_webcam_capture"/>';
     846                $output .= wp_nonce_field( 'bp_webcam_avatar', '_webcam_avatar_nonce', true , false );
     847                $output .= '</div>';
     848                $output .= '</form>';
     849               
     850                return apply_filters( 'bp_get_avatar_webcam', $output );
     851        }