Commit 1f8b307d authored by MediaFormat's avatar MediaFormat

Service registration refactor, Separate widgets, support for PeerTube

parent 39266ca5
#ignore system files
.DS_Store
#bootstrap slim
assets/bootstrap/*
!assets/bootstrap/css/bootstrap.min.css
!assets/bootstrap/css/bootstrap.min.css.map
......@@ -9,293 +9,148 @@
will-change: transform;
}
.status {
padding: 8px 10px 8px 68px;
position: relative;
min-height: 54px;
border-bottom: 1px solid #c0cdd9;
cursor: default;
opacity: 1;
-webkit-animation: fade .15s linear;
animation: fade .15s linear;
}
.status__prepend {
margin-left: 68px;
color: #444b5d;
padding: 8px 0 2px;
font-size: 14px;
position: relative;
}
.status__prepend-icon-wrapper {
left: -26px;
position: absolute;
}
.fa-fw {
width: 1.28571429em;
text-align: center;
.peertube-timeline__header {
width: 100vw;
overflow-x: auto;
padding-left: 15px;
padding-right: 15px;
margin-bottom: 10px;
}
.fa {
display: inline-block;
}
.account__header {
overflow: hidden;
}
.account__header__image {
overflow: hidden;
height: 145px;
position: relative;
background: #e6ebf0;
}
.account__header__info {
position: absolute;
top: 10px;
left: 10px;
}
.account__header__image img {
object-fit: cover;
display: block;
.actor,
.actor-info {
width: 100%;
height: 100%;
margin: 0;
}
.account__header__bar {
position: relative;
background: #fff;
padding: 5px;
border-bottom: 1px solid #b3c3d1;
}
.account__header__tabs {
.actor {
display: -webkit-box;
display: flex;
align-items: flex-start;
padding: 7px 5px;
margin-top: -55px;
}
.account__header__bar .avatar {
display: block;
flex: 0 0 auto;
width: 94px;
margin-left: -2px;
}
.account__header__tabs .spacer {
flex: 1 1 auto;
margin-top: 20px;
margin-bottom: 20px;
}
.account__header__tabs__buttons .button {
margin: 0 8px;
color: #fff;
border-radius: 4px;
padding: 0px 16px;
height: 36px;
line-height: 36px;
}
.account__header__tabs__name {
padding: 5px;
}
.account__header__tabs__name h1 {
font-size: 16px;
line-height: 24px;
color: #000;
font-weight: 500;
margin: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.account__header__tabs__name h1 small {
display: block;
font-size: 14px;
color: #282c37;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
}
.account__header__extra {
margin-top: 4px;
.actor img {
-o-object-fit: cover;
object-fit: cover;
border-radius: 50%;
width: 80px;
height: 80px;
min-width: 80px;
margin-right: 20px;
}
.actor .actor-info {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-pack: center;
justify-content: center;
}
.account__header__bio {
overflow: hidden;
margin: 0 -5px;
.actor .actor-display-link {
text-decoration: none;
}
.account__header__bio .account__header__content {
padding: 20px 15px 5px;
color: #000;
.actor .actor-info .actor-names .actor-display-name {
font-size: 23px;
font-weight: 700;
}
.account__header__content {
color: #282c37;
.actor-info .actor-names .actor-name {
margin-left: 7px;
position: relative;
top: 3px;
font-size: 14px;
font-weight: 400;
overflow: hidden;
word-break: normal;
word-wrap: break-word;
}
.account__display-name,
.detailed-status__application,
.detailed-status__datetime,
.detailed-status__display-name,
.status__display-name,
.status__relative-time {
text-decoration: none;
}
.status__display-name {
color: #444b5d;
}
.status__expand {
width: 68px;
position: absolute;
left: 0;
top: 0;
height: 100%;
cursor: pointer;
}
.status__info {
font-size: 15px;
}
.status__info .status__display-name {
display: block;
max-width: 100%;
padding-right: 25px;
color: #777272;
}
.status__avatar {
height: 48px;
left: 10px;
position: absolute;
top: 10px;
width: 48px;
.video { margin-bottom: 1.5em; }
.videos .video-miniature {
padding-right: 0;
height: auto;
width: 100%;
margin-bottom: 5px;
}
.account__avatar {
border-radius: 4px;
background: transparent no-repeat;
background-position: 50%;
background-clip: padding-box;
.video-thumbnail {
display: -webkit-box;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
position: relative;
border-radius: 3px;
overflow: hidden;
background-color: #ececec;
-webkit-transition: -webkit-filter .2s;
transition: -webkit-filter .2s ease;
transition: filter .2s ease;
transition: filter .2s ease,-webkit-filter .2s ease;
}
.account__avatar-overlay {
width: 48px;
height: 48px;
background-size: 48px 48px;
.videos .video-miniature .video-thumbnail {
margin: 0;
width: 100%;
height: auto;
border-radius: 0;
}
.account__avatar-overlay-base {
border-radius: 4px;
background: transparent no-repeat;
background-position: 50%;
background-clip: padding-box;
width: 36px;
height: 36px;
background-size: 36px 36px;
.videos .video-miniature .video-thumbnail img {
width: 100%;
height: auto;
}
.account__avatar-overlay-overlay {
border-radius: 4px;
background: transparent no-repeat;
background-position: 50%;
background-clip: padding-box;
width: 24px;
height: 24px;
background-size: 24px 24px;
.video-thumbnail .play-overlay {
position: absolute;
bottom: 0;
right: 0;
z-index: 1;
}
.display-name {
display: block;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.display-name__account {
font-size: 14px;
}
.account__display-name strong, .status__display-name strong {
color: #000;
}
.display-name__html {
font-weight: 500;
}
.notification__relative_time, .status__relative-time {
color: #444b5d;
float: right;
font-size: 14px;
}
.status-card.compact {
border-color: #ccd7e0;
}
.status-card {
bottom: 0;
width: inherit;
height: inherit;
opacity: 0;
background-color: rgba(0,0,0,.7);
}
.video-thumbnail .play-overlay,
.video-thumbnail .play-overlay .icon {
-webkit-transition: .2s;
transition: all .2s ease;
}
.video-thumbnail .play-overlay .icon {
width: 0;
height: 0;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%,-50%) scale(.5);
transform: translate(-50%,-50%) scale(.5);
border-top: 13px solid transparent;
border-bottom: 13px solid transparent;
border-left: 18px solid rgba(255,255,255,.95);
}
.video-miniature .video-bottom {
display: -webkit-box;
display: flex;
font-size: 14px;
border: 1px solid #c0cdd9;
border-radius: 4px;
color: #444b5d;
margin-top: 14px;
text-decoration: none;
overflow: hidden;
cursor: pointer;
}
.status-card.compact .status-card__image {
flex: 0 0 60px;
}
.status-card__image {
flex: 0 0 100px;
background: #c0cdd9;
position: relative;
}
.status-card__image-image {
border-radius: 4px 0 0 4px;
display: block;
margin: 0;
width: 100%;
height: 100%;
object-fit: cover;
background-size: cover;
background-position: 50%;
.video-thumbnail .video-thumbnail-duration-overlay {
display: inline-block;
background-color: rgba(0,0,0,.7);
color: #fff;
position: absolute;
right: 5px;
bottom: 5px;
padding: 0 5px;
border-radius: 3px;
font-size: 12px;
font-weight: 700;
}
.video-miniature-name{
font-weight: 600;
margin: 0 0 5px;
text-decoration: none;
text-overflow: ellipsis;
}
.status-card.compact .status-card__content {
padding: 10px 8px 8px;
.video-miniature-created-at-views {
font-size: 0.75em;
}
.status-card__content {
flex: 1 1 auto;
overflow: hidden;
padding: 14px 14px 14px 8px;
.video-miniature-created-at-views .views::before {
content: ' - '
}
.status-card__title {
display: block;
font-weight: 500;
margin-bottom: 5px;
color: #282c37;
.video-miniature-account {
hite-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-decoration: none;
}
.status-card__description {
color: #282c37;
}
.status-card__host {
display: block;
margin-top: 5px;
font-size: 13px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.status__content summary {
background: #eee;
border-radius: 5px;
padding: 2px 8px;
cursor: pointer;
display: inline-block;
}
.status__content .media-gallery__item{
margin: 1em 0;
}
i.fa-retweet {
background-image: url('../img/retoot.svg');
background-position: 0 0;
height: 19px;
vertical-align: middle;
width: 22px;
color: #ccc;
opacity: .75;
z-index: 10;
position: relative;
font-size: 0.75em;
color: #585858;
}
......@@ -48,25 +48,25 @@ class FediClient
return $this->instance_url.'/oauth/authorize?'.$params;
}
public function register_client($redirect_uri, $scopes = 'read') {
$response = $this->_get('/api/v1/oauth-clients/local');
if (!isset($response->client_id)){
return "ERROR";
}
$this->app = $response;
$params = http_build_query(array(
'scope' => $scopes,
'client_id' =>$this->app->client_id,
'client_secret' =>$this->app->client_secret
));
$access_token = $this->_post('/api/v1/oauth-clients/local');
// return $this->instance_url.'/users/token?'.$params;
}
// public function register_client($redirect_uri, $scopes = 'read') {
//
// $response = $this->_get('/api/v1/oauth-clients/local');
//
// if (!isset($response->client_id)){
// return "ERROR";
// }
//
// $this->app = $response;
//
// $params = http_build_query(array(
// 'scope' => $scopes,
// 'client_id' =>$this->app->client_id,
// 'client_secret' =>$this->app->client_secret
// ));
//
// $access_token = $this->_post('/api/v1/oauth-clients/local');
// // return $this->instance_url.'/users/token?'.$params;
// }
public function verify_credentials($access_token){
......@@ -138,26 +138,15 @@ class FediClient
return $response;
}
public function getVideos($media = 'false', $pinned = 'false', $replies = 'false', $max_id = null, $since_id = null, $min_id = null, $limit = 10, $reblogs = 'false') {
$headers = array(
'Authorization'=> 'Bearer '.$this->access_token
);
public function getVideos($account_id, $is_channel) {
$account_id = self::$acct_id;
$headers = array();
// $query = http_build_query(array(
// 'only_media' => $media,
// 'pinned' => $pinned,
// 'exclude_replies' => $replies,
// 'max_id' => $max_id,
// 'since_id' => $since_id,
// 'min_id' => $min_id,
// 'limit' => $limit,
// 'exclude_reblogs' => $reblogs
// ));
$response = $this->_get("/api/v1/accounts/{$account_id}/videos", null, $headers);
if(!is_null($is_channel)){
$response = $this->_get("/api/v1/video-channels/{$account_id}/videos", null, $headers);
} else {
$response = $this->_get("/api/v1/accounts/{$account_id}/videos", null, $headers);
}
return $response;
}
......
<?php
class FediEmbedi_Mastodon extends WP_Widget {
/**
* Sets up a new FediEmbedi widget instance.
*
* @since 2.8.0
*/
public function __construct() {
$widget_ops = array(
'classname' => 'mastodon_widget',
'description' => __( 'Display a profile timeline', 'fediembedi' ),
'customize_selective_refresh' => true,
);
parent::__construct( 'mastodon', _x( 'Mastodon', 'fediembedi' ), $widget_ops );
}
/**
* Outputs the content for the current Search widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Search widget instance.
*/
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
//fedi instance
$fedi_instance = get_option('fediembedi-mastodon-instance');
$access_token = get_option('fediembedi-mastodon-token');
$client = new \FediClient($fedi_instance, $access_token);
$cred = $client->verify_credentials($access_token);
//widget options
$show_header = (!empty($instance['show_header'])) ? $instance['show_header'] : '';
$only_media = (!empty($instance['only_media'])) ? $instance['only_media'] : '';
$pinned = (!empty($instance['pinned'])) ? $instance['pinned'] : '';
$exclude_replies = (!empty($instance['exclude_replies'])) ? $instance['exclude_replies'] : '';
$exclude_reblogs = (!empty($instance['exclude_reblogs'])) ? $instance['exclude_reblogs'] : '';
$number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$height = isset( $instance['height'] ) ? esc_attr( $instance['height'] ) : '100%';
//if(WP_DEBUG_DISPLAY === true): echo '<details><summary>'. $instance_type .'</summary><pre>'; var_dump($status); echo '</pre></details>'; endif;
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
};
//getStatus from remote instance
$status = $client->getStatus($only_media, $pinned, $exclude_replies, null, null, null, $number, $exclude_reblogs);
include(plugin_dir_path(__FILE__) . 'templates/mastodon.tpl.php' );
echo $args['after_widget'];
}
/**
* Outputs the settings form for the Search widget.
*
* @since 2.8.0
*
* @param array $instance Current settings.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array( 'title' => '') );
//Radio inputs : https://wordpress.stackexchange.com/a/276659/87622
$show_header = (!empty( $instance['show_header'])) ? $instance['show_header'] : NULL;
$only_media = (!empty( $instance['only_media'])) ? $instance['only_media'] : NULL;
$pinned = (!empty($instance['pinned'])) ? $instance['pinned'] : NULL;
$exclude_replies = (!empty($instance['exclude_replies'])) ? $instance['exclude_replies'] : NULL;
$exclude_reblogs = (!empty($instance['exclude_reblogs'])) ? $instance['exclude_reblogs'] : NULL;
$number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$height = isset( $instance['height'] ) ? esc_attr( $instance['height'] ) : '';
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'fediembedi'); ?>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($instance['title']); ?>" />
</label>
</p>
<p>
<label>
<input
type="checkbox"
<?php checked( $instance[ 'show_header' ], '1' ); ?>
id="<?php echo $this->get_field_id( '1' ); ?>"
name="<?php echo $this->get_field_name('show_header'); ?>"
value="1"
/><?php _e( 'Show header', 'fediembedi' ); ?>
</label>
</p>
<p>
<label>
<input
type="checkbox"
<?php checked( $instance[ 'only_media' ], '1' ); ?>
id="<?php echo $this->get_field_id( '1' ); ?>"
name="<?php echo $this->get_field_name('only_media'); ?>"
value="1"
/><?php _e( 'Only show media', 'fediembedi' ); ?>
</label>
</p>
<p>
<label>
<input
type="checkbox"
<?php checked( $instance[ 'pinned' ], '1' ); ?>
id="<?php echo $this->get_field_id( '1' ); ?>"
name="<?php echo $this->get_field_name('pinned'); ?>"
value="1"
/><?php _e( 'Only show pinned statuses', 'fediembedi' ); ?>
</label>
</p>
<p>
<label>
<input
type="checkbox"
<?php checked( $instance[ 'exclude_replies' ], '1' ); ?>
id="<?php echo $this->get_field_id( '1' ); ?>"
name="<?php echo $this->get_field_name('exclude_replies'); ?>"
value="1"
/><?php _e( 'Hide replies', 'fediembedi' ); ?>
</label>
</p>
<p>
<label>
<input
type="checkbox"
<?php checked( $instance[ 'exclude_reblogs' ], '1' ); ?>
id="<?php echo $this->get_field_id( '1' ); ?>"
name="<?php echo $this->get_field_name('exclude_reblogs'); ?>"
value="1"
/><?php _e( 'Hide reblogs', 'fediembedi' ); ?>
</label>
</p>
<p>
<label for="<?php echo $this->get_field_id( 'number' ); ?>"><?php _e( 'Number of posts to display:' ); ?><br>
<input class="tiny-text" id="<?php echo $this->get_field_id( 'number' ); ?>" name="<?php echo $this->get_field_name( 'number' ); ?>" type="number" step="1" min="1" value="<?php echo $number; ?>" size="3" />
<small>Max: 20</small>
</label>
</p>
<p>
<label for="<?php echo $this->get_field_id( 'height' ); ?>"><?php _e( 'Widget height:' ); ?><br>
<input class="" id="<?php echo $this->get_field_id( 'height' ); ?>" name="<?php echo $this->get_field_name( 'height' ); ?>" type="text" value="<?php echo $height; ?>" placeholder="500px" size="5" />
<small><?php _e( 'Default: 100%', 'fediembedi' ); ?></small>
</label>
</p>
<?php
}
/**
* Handles updating settings for the current Search widget instance.
*
* @since 2.8.0
*
* @param array $new_instance New settings for this instance as input by the user via
* WP_Widget::form().
* @param array $old_instance Old settings for this instance.
* @return array Updated settings.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$new_instance = wp_parse_args( (array) $new_instance, array( 'title' => '' ) );
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['show_header'] = $new_instance['show_header'];
$instance['only_media'] = $new_instance['only_media'];
$instance['pinned'] = $new_instance['pinned'];
$instance['exclude_replies'] = $new_instance['exclude_replies'];
$instance['exclude_reblogs'] = $new_instance['exclude_reblogs'];
$instance['number'] = (int) $new_instance['number'];
$instance['height'] = sanitize_text_field( $new_instance['height'] );
return $instance;
}
}
<?php
class FediEmbedi_PeerTube extends WP_Widget {
/**
* Sets up a new FediEmbedi widget instance.
*
* @since 2.8.0
*/
public function __construct() {
$widget_ops = array(
'classname' => 'peertube_widget',
'description' => __( 'Display a profile timeline', 'fediembedi' ),
'customize_selective_refresh' => true,
);
parent::__construct( 'peertube', _x( 'PeerTube', 'fediembedi' ), $widget_ops );
}
/**
* Outputs the content for the current Search widget instance.
*
* @since 2.8.0
*
* @param array $args Display arguments including 'before_title', 'after_title',
* 'before_widget', and 'after_widget'.
* @param array $instance Settings for the current Search widget instance.
*/
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
//fedi instance
$fedi_instance = (!empty($instance['peertube'])) ? $instance['peertube'] : '';
$actor = (!empty($instance['actor'])) ? $instance['actor'] : '';
$is_channel = (!empty($instance['channel'])) ? $instance['channel'] : null;//radio channel or account
$client = new \FediClient($fedi_instance);
//widget options
$show_header = (!empty($instance['show_header'])) ? $instance['show_header'] : null;
$number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
$height = isset( $instance['height'] ) ? esc_attr( $instance['height'] ) : '100%';
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];