Very small optimizations and first upload
|
@ -0,0 +1,2 @@
|
|||
config.ini
|
||||
.ftpconfig
|
64
README.md
|
@ -1,2 +1,62 @@
|
|||
# halcyon
|
||||
A Mastodon web client that looks like Twitter - Demo at https://halcyon.cybre.space
|
||||
# Halcyon for Mastodon
|
||||
A Mastodon web client that looks like Twitter
|
||||
|
||||
>The original author of this genious piece of software was inactive for a while and then shut down his demo instance and deleted this repository. I love Halcyon, it's the thing which makes Mastodon the best social network in the world. I took the Code from the Halcyon fork of cybre.space which still works but doesn't seem to get updates, too. I uploaded it here to make the original link work again and don't link into the big nothing. I'm working on much other stuff, too, what is why I won't be very active here in the near future but I do things which are required to keep it working and if I have much more time, I already know some nice features which could come. As for now I don't have an own demo instance but the one from cybre.space works pretty good and when I changed many things, I will open an own one.
|
||||
|
||||
<img src="https://halcyon.cybre.space/login/assets/images/preview0.png">
|
||||
|
||||
## Demo
|
||||
https://halcyon.cybre.space/
|
||||
Please note that this demo is not owned by me and I have not control over it. Currently I'm not providing an own demo so I link to that one. That may change in future.
|
||||
|
||||
## Features
|
||||
- Twitter like UI, familiar interface.
|
||||
- Able to use on all instances.
|
||||
- No tracking, No ads.
|
||||
|
||||
## Requirement
|
||||
- Apache
|
||||
- PHP
|
||||
- MySQL
|
||||
|
||||
## Setup
|
||||
I didn't prepared setup script so you have to setup manually...
|
||||
|
||||
### PDO MySQL
|
||||
|
||||
After installed PHP, run this.
|
||||
|
||||
```bash
|
||||
sudo pecl install pdo_mysql
|
||||
sudo vi php.ini
|
||||
```
|
||||
|
||||
change to this
|
||||
|
||||
```php.ini
|
||||
extension=mysqli.so
|
||||
extension=pdo_mysql.so
|
||||
```
|
||||
|
||||
### MySQL
|
||||
After installed MySQL, create a user, run this.
|
||||
```sql
|
||||
CREATE DATABASE DATABASE_NAME DEFAULT CHARACTER SET utf8;
|
||||
CREATE TABLE DATABASE_NAME.instances(domain varchar(261), client_id varchar(64), client_secret varchar(64));
|
||||
```
|
||||
and make file `/config.ini` like this
|
||||
```config.ini
|
||||
~~~ line 3 ~~~
|
||||
api_client_name = <APP NAME>
|
||||
api_client_website = <APP WEBSITE LINK>
|
||||
~~~ line 8 ~~~
|
||||
db_host = <DATABASE HOST DOMAIN>
|
||||
db_user = <DATABASE USERNAME>
|
||||
db_pass = <DATABASE PASSWORD>
|
||||
db_name = <DATABASE NAME>
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
- [Kirschn/mastodon.js](https://github.com/Kirschn/mastodon.js)
|
||||
- [yks118/Mastodon-api-php](https://github.com/yks118/Mastodon-api-php)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Roadmap
|
||||
|
||||
These plans may change if I think something else is more important or if I consider something here as not that important!
|
||||
|
||||
## Next version
|
||||
- [x] Oauth login
|
||||
- [x] Support responsive
|
||||
- [ ] Add meida attachment's next/prev button
|
||||
|
||||
## Future
|
||||
- [ ] Multi account
|
||||
- [ ] Emoji picker
|
||||
- [ ] Native profile edit
|
||||
- [ ] Dark theme
|
||||
- [ ] Translation support
|
||||
- [ ] Mobile devices support
|
||||
- [ ] PHP PSR4 / Autoload
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 KwangSeon Yun
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,970 @@
|
|||
<?php
|
||||
// defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Class Mastodon_api
|
||||
*
|
||||
* PHP version 7.1
|
||||
*
|
||||
* Mastodon https://mastodon.social/
|
||||
* API LIST https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md
|
||||
*
|
||||
* @author KwangSeon Yun <middleyks@hanmail.net>
|
||||
* @copyright KwangSeon Yun
|
||||
* @license https://raw.githubusercontent.com/yks118/Mastodon-api-php/master/LICENSE MIT License
|
||||
* @link https://github.com/yks118/Mastodon-api-php
|
||||
*/
|
||||
class Mastodon_api {
|
||||
private $mastodon_url = '';
|
||||
private $client_id = '';
|
||||
private $client_secret = '';
|
||||
|
||||
private $token = array();
|
||||
private $scopes = array();
|
||||
|
||||
public function __construct () {}
|
||||
|
||||
public function __destruct () {}
|
||||
|
||||
/**
|
||||
* _post
|
||||
*
|
||||
* curl post
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
private function _post ($url,$data = array()) {
|
||||
$parameters = array();
|
||||
$parameters[CURLOPT_POST] = 1;
|
||||
|
||||
// set access_token
|
||||
if (isset($this->token['access_token'])) {
|
||||
$data['access_token'] = $this->token['access_token'];
|
||||
}
|
||||
|
||||
if (count($data)) {
|
||||
$parameters[CURLOPT_POSTFIELDS] = http_build_query($data);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* _get
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
private function _get ($url,$data = array()) {
|
||||
$parameters = array();
|
||||
|
||||
// set authorization bearer
|
||||
if (isset($this->token['access_token'])) {
|
||||
$authorization = 'Authorization: '.$this->token['token_type'].' '.$this->token['access_token'];
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type: application/json',$authorization);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
if (count($data)) {
|
||||
$url .= '?'.http_build_query($data);
|
||||
}
|
||||
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* _patch
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
*
|
||||
* @return array $parameters
|
||||
*/
|
||||
private function _patch ($url,$data = array()) {
|
||||
$parameters = array();
|
||||
$parameters[CURLOPT_CUSTOMREQUEST] = 'PATCH';
|
||||
|
||||
// set authorization bearer
|
||||
if (isset($this->token['access_token'])) {
|
||||
$authorization = 'Authorization: '.$this->token['token_type'].' '.$this->token['access_token'];
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type: application/json',$authorization);
|
||||
}
|
||||
|
||||
if (count($data)) {
|
||||
$parameters[CURLOPT_POSTFIELDS] = json_encode($data);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* _delete
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
private function _delete ($url) {
|
||||
$parameters = array();
|
||||
$parameters[CURLOPT_CUSTOMREQUEST] = 'DELETE';
|
||||
|
||||
// set authorization bearer
|
||||
if (isset($this->token['access_token'])) {
|
||||
$authorization = 'Authorization: '.$this->token['token_type'].' '.$this->token['access_token'];
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type: application/json',$authorization);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_content_curl
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $parameters
|
||||
*
|
||||
* @return array $data
|
||||
*/
|
||||
protected function get_content_curl ($url,$parameters = array()) {
|
||||
$data = array();
|
||||
|
||||
// set CURLOPT_USERAGENT
|
||||
if (!isset($parameters[CURLOPT_USERAGENT])) {
|
||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||
$parameters[CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];
|
||||
} else {
|
||||
// default IE11
|
||||
$parameters[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko';
|
||||
}
|
||||
}
|
||||
|
||||
// check curl_init
|
||||
if (function_exists('curl_init')) {
|
||||
$ch = curl_init();
|
||||
|
||||
// url 설정
|
||||
curl_setopt($ch,CURLOPT_URL,$url);
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
curl_setopt($ch,$key,$value);
|
||||
}
|
||||
|
||||
// https
|
||||
if (!isset($parameters[CURLOPT_SSL_VERIFYPEER])) {
|
||||
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
|
||||
}
|
||||
if (!isset($parameters[CURLOPT_SSLVERSION])) {
|
||||
curl_setopt($ch,CURLOPT_SSLVERSION,6);
|
||||
}
|
||||
|
||||
// no header
|
||||
if (!isset($parameters[CURLOPT_HEADER])) {
|
||||
curl_setopt($ch,CURLOPT_HEADER,0);
|
||||
}
|
||||
|
||||
// POST / GET (default : GET)
|
||||
if (!isset($parameters[CURLOPT_POST]) && !isset($parameters[CURLOPT_CUSTOMREQUEST])) {
|
||||
curl_setopt($ch,CURLOPT_POST,0);
|
||||
}
|
||||
|
||||
// response get php value
|
||||
if (!isset($parameters[CURLOPT_RETURNTRANSFER])) {
|
||||
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
|
||||
}
|
||||
|
||||
// HTTP2
|
||||
if (!isset($parameters[CURLOPT_HTTP_VERSION])) {
|
||||
curl_setopt($ch,CURLOPT_HTTP_VERSION,3);
|
||||
}
|
||||
if (!isset($parameters[CURLINFO_HEADER_OUT])) {
|
||||
curl_setopt($ch,CURLINFO_HEADER_OUT,TRUE);
|
||||
}
|
||||
|
||||
$data['html'] = json_decode(curl_exec($ch),true);
|
||||
$data['response'] = curl_getinfo($ch);
|
||||
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_url
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function set_url ($path) {
|
||||
$this->mastodon_url = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_client
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $secret
|
||||
*/
|
||||
public function set_client ($id,$secret) {
|
||||
$this->client_id = $id;
|
||||
$this->client_secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_token
|
||||
*
|
||||
* @param string $token
|
||||
* @param string $type
|
||||
*/
|
||||
public function set_token ($token,$type) {
|
||||
$this->token['access_token'] = $token;
|
||||
$this->token['token_type'] = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_scopes
|
||||
*
|
||||
* @param array $scopes read / write / follow
|
||||
*/
|
||||
public function set_scopes ($scopes) {
|
||||
$this->scopes = $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* create_app
|
||||
*
|
||||
* @param string $client_name
|
||||
* @param array $scopes read / write / follow
|
||||
* @param string $redirect_uris
|
||||
* @param string $website
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id']
|
||||
* string $response['redirect_uri']
|
||||
* string $response['client_id']
|
||||
* string $response['client_secret']
|
||||
*/
|
||||
public function create_app ($client_name,$scopes = array(),$redirect_uris = '',$website = '') {
|
||||
$parameters = array();
|
||||
|
||||
if (count($scopes) == 0) {
|
||||
if (count($this->scopes) == 0) {
|
||||
$scopes = array('read','write','follow');
|
||||
} else {
|
||||
$scopes = $this->scopes;
|
||||
}
|
||||
}
|
||||
|
||||
$parameters['client_name'] = $client_name;
|
||||
$parameters['scopes'] = implode(' ',$scopes);
|
||||
|
||||
if (empty($redirect_uris)) {
|
||||
$parameters['redirect_uris'] = 'urn:ietf:wg:oauth:2.0:oob';
|
||||
} else {
|
||||
$parameters['redirect_uris'] = $redirect_uris;
|
||||
}
|
||||
|
||||
if ($website) {
|
||||
$parameters['website'] = $website;
|
||||
}
|
||||
|
||||
$response = $this->_post('/api/v1/apps',$parameters);
|
||||
|
||||
if (isset($response['html']['client_id'])) {
|
||||
$this->client_id = $response['html']['client_id'];
|
||||
$this->client_secret = $response['html']['client_secret'];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* login
|
||||
*
|
||||
* @param string $id E-mail Address
|
||||
* @param string $password Password
|
||||
*
|
||||
* @return array $response
|
||||
* string $response['access_token']
|
||||
* string $response['token_type'] bearer
|
||||
* string $response['scope'] read
|
||||
* int $response['created_at'] time
|
||||
*/
|
||||
public function login ($id,$password) {
|
||||
$parameters = array();
|
||||
$parameters['client_id'] = $this->client_id;
|
||||
$parameters['client_secret'] = $this->client_secret;
|
||||
$parameters['grant_type'] = 'password';
|
||||
$parameters['username'] = $id;
|
||||
$parameters['password'] = $password;
|
||||
|
||||
if (count($this->scopes) == 0) {
|
||||
$parameters['scope'] = implode(' ',array('read','write','follow'));
|
||||
} else {
|
||||
$parameters['scope'] = implode(' ',$this->scopes);
|
||||
}
|
||||
|
||||
$response = $this->_post('/oauth/token',$parameters);
|
||||
|
||||
if (isset($response['html']["access_token"])) {
|
||||
$this->token['access_token'] = $response['html']['access_token'];
|
||||
$this->token['token_type'] = $response['html']['token_type'];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function get_access_token ($redirect_uri,$code) {
|
||||
$parameters = array();
|
||||
$parameters['grant_type'] = 'authorization_code';
|
||||
$parameters['redirect_uri'] = $redirect_uri;
|
||||
$parameters['client_id'] = $this->client_id;
|
||||
$parameters['client_secret'] = $this->client_secret;
|
||||
$parameters['code'] = $code;
|
||||
$response = $this->_post('/oauth/token',$parameters);
|
||||
|
||||
if (isset($response['html']["access_token"])) {
|
||||
$this->token['access_token'] = $response['html']['access_token'];
|
||||
$this->token['token_type'] = $response['html']['token_type'];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id']
|
||||
* string $response['username']
|
||||
* string $response['acct']
|
||||
* string $response['display_name'] The name to display in the user's profile
|
||||
* bool $response['locked']
|
||||
* string $response['created_at']
|
||||
* int $response['followers_count']
|
||||
* int $response['following_count']
|
||||
* int $response['statuses_count']
|
||||
* string $response['note'] A new biography for the user
|
||||
* string $response['url']
|
||||
* string $response['avatar'] A base64 encoded image to display as the user's avatar
|
||||
* string $response['avatar_static']
|
||||
* string $response['header'] A base64 encoded image to display as the user's header image
|
||||
* string $response['header_static']
|
||||
*/
|
||||
public function accounts ($id) {
|
||||
$response = $this->_get('/api/v1/accounts/'.$id);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_verify_credentials
|
||||
*
|
||||
* Getting the current user
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_verify_credentials () {
|
||||
$response = $this->_get('/api/v1/accounts/verify_credentials');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_update_credentials
|
||||
*
|
||||
* Updating the current user
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['display_name'] The name to display in the user's profile
|
||||
* string $parameters['note'] A new biography for the user
|
||||
* string $parameters['avatar'] A base64 encoded image to display as the user's avatar
|
||||
* string $parameters['header'] A base64 encoded image to display as the user's header image
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_update_credentials ($parameters) {
|
||||
$response = $this->_patch('/api/v1/accounts/update_credentials',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_followers
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_followers ($id) {
|
||||
$response = $this->_get('/api/v1/accounts/'.$id.'/followers');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_following
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_following ($id) {
|
||||
$response = $this->_get('/api/v1/accounts/'.$id.'/following');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_statuses
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_statuses ($id) {
|
||||
$response = $this->_get('/api/v1/accounts/'.$id.'/statuses');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_follow
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_follow ($id) {
|
||||
$response = $this->_post('/api/v1/accounts/'.$id.'/follow');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_unfollow
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_unfollow ($id) {
|
||||
$response = $this->_post('/api/v1/accounts/'.$id.'/unfollow');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_block
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_block ($id) {
|
||||
$response = $this->_post('/api/v1/accounts/'.$id.'/block');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_unblock
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_unblock ($id) {
|
||||
$response = $this->_post('/api/v1/accounts/'.$id.'/unblock');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_mute
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_mute ($id) {
|
||||
$response = $this->_post('/api/v1/accounts/'.$id.'/mute');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_unmute
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_unmute ($id) {
|
||||
$response = $this->_post('/api/v1/accounts/'.$id.'/unmute');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_relationships
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param array $parameters
|
||||
* int $parameters['id']
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id']
|
||||
* bool $response['following']
|
||||
* bool $response['followed_by']
|
||||
* bool $response['blocking']
|
||||
* bool $response['muting']
|
||||
* bool $response['requested']
|
||||
*/
|
||||
public function accounts_relationships ($parameters) {
|
||||
$response = $this->_get('/api/v1/accounts/relationships',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_search
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['q']
|
||||
* int $parameters['limit'] default : 40
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_search ($parameters) {
|
||||
$response = $this->_get('/api/v1/accounts/search',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* blocks
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function blocks () {
|
||||
$response = $this->_get('/api/v1/blocks');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* favourites
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function favourites () {
|
||||
$response = $this->_get('/api/v1/favourites');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follow_requests
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function follow_requests () {
|
||||
$response = $this->_get('/api/v1/follow_requests');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follow_requests_authorize
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function follow_requests_authorize ($id) {
|
||||
$response = $this->_post('/api/v1/follow_requests/authorize',array('id'=>$id));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follow_requests_reject
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
* @return array $response
|
||||
*/
|
||||
public function follow_requests_reject ($id) {
|
||||
$response = $this->_post('/api/v1/follow_requests/reject',array('id'=>$id));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follows
|
||||
*
|
||||
* Following a remote user
|
||||
*
|
||||
* @param string $uri username@domain of the person you want to follow
|
||||
* @return array $response
|
||||
*/
|
||||
public function follows ($uri) {
|
||||
$response = $this->_post('/api/v1/follows',array('uri'=>$uri));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* instance
|
||||
*
|
||||
* Getting instance information
|
||||
*
|
||||
* @return array $response
|
||||
* string $response['uri']
|
||||
* string $response['title']
|
||||
* string $response['description']
|
||||
* string $response['email']
|
||||
*/
|
||||
public function instance () {
|
||||
$response = $this->_get('/api/v1/instance');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* media
|
||||
*
|
||||
* Uploading a media attachment
|
||||
*
|
||||
* @param string $file_path local path / http path
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id'] ID of the attachment
|
||||
* string $response['type'] One of: "image", "video", "gifv"
|
||||
* string $response['url'] URL of the locally hosted version of the image
|
||||
* string $response['remote_url'] For remote images, the remote URL of the original image
|
||||
* string $response['preview_url'] URL of the preview image
|
||||
* string $response['text_url'] Shorter URL for the image, for insertion into text (only present on local images)
|
||||
*/
|
||||
public function media ($file_path) {
|
||||
$url = $this->mastodon_url.'/api/v1/media';
|
||||
$parameters = $data = array();
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type'=>'multipart/form-data');
|
||||
$parameters[CURLOPT_POST] = true;
|
||||
|
||||
// set access_token
|
||||
if (isset($this->token['access_token'])) {
|
||||
$parameters[CURLOPT_POSTFIELDS]['access_token'] = $this->token['access_token'];
|
||||
}
|
||||
|
||||
if (is_file($file_path)) {
|
||||
$mime_type = mime_content_type($file_path);
|
||||
|
||||
$cf = curl_file_create($file_path,$mime_type,'file');
|
||||
$parameters[CURLOPT_POSTFIELDS]['file'] = $cf;
|
||||
}
|
||||
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutes
|
||||
*
|
||||
* Fetching a user's mutes
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function mutes () {
|
||||
$response = $this->_get('/api/v1/mutes');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* notifications
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function notifications ($id = 0) {
|
||||
$url = '/api/v1/notifications';
|
||||
|
||||
if ($id > 0) {
|
||||
$url .= '/'.$id;
|
||||
}
|
||||
|
||||
$response = $this->_get($url);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* notifications_clear
|
||||
*
|
||||
* Clearing notifications
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function notifications_clear () {
|
||||
$response = $this->_post('/api/v1/notifications/clear');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_reports
|
||||
*
|
||||
* Fetching a user's reports
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function get_reports () {
|
||||
$response = $this->_get('/api/v1/reports');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* post_reports
|
||||
*
|
||||
* Reporting a user
|
||||
*
|
||||
* @param array $parameters
|
||||
* int $parameters['account_id'] The ID of the account to report
|
||||
* int $parameters['status_ids'] The IDs of statuses to report (can be an array)
|
||||
* string $parameters['comment'] A comment to associate with the report.
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function post_reports ($parameters) {
|
||||
$response = $this->_post('/api/v1/reports',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* search
|
||||
*
|
||||
* Searching for content
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['q'] The search query
|
||||
* string $parameters['resolve'] Whether to resolve non-local accounts
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function search ($parameters) {
|
||||
$response = $this->_get('/api/v1/search',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses
|
||||
*
|
||||
* Fetching a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses ($id) {
|
||||
$response = $this->_get('/api/v1/statuses/'.$id);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_context
|
||||
*
|
||||
* Getting status context
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_context ($id) {
|
||||
$response = $this->_get('/api/v1/statuses/'.$id.'/context');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_card
|
||||
*
|
||||
* Getting a card associated with a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_card ($id) {
|
||||
$response = $this->_get('/api/v1/statuses/'.$id.'/card');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_reblogged_by
|
||||
*
|
||||
* Getting who reblogged a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_reblogged_by ($id) {
|
||||
$response = $this->_get('/api/v1/statuses/'.$id.'/reblogged_by');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_favourited_by
|
||||
*
|
||||
* Getting who favourited a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_favourited_by ($id) {
|
||||
$response = $this->_get('/api/v1/statuses/'.$id.'/favourited_by');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* post_statuses
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['status'] The text of the status
|
||||
* int $parameters['in_reply_to_id'] (optional): local ID of the status you want to reply to
|
||||
* int $parameters['media_ids'] (optional): array of media IDs to attach to the status (maximum 4)
|
||||
* string $parameters['sensitive'] (optional): set this to mark the media of the status as NSFW
|
||||
* string $parameters['spoiler_text'] (optional): text to be shown as a warning before the actual content
|
||||
* string $parameters['visibility'] (optional): either "direct", "private", "unlisted" or "public"
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function post_statuses ($parameters) {
|
||||
$response = $this->_post('/api/v1/statuses',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete_statuses
|
||||
*
|
||||
* Deleting a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response empty
|
||||
*/
|
||||
public function delete_statuses ($id) {
|
||||
$response = $this->_delete('/api/v1/statuses/'.$id);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_reblog
|
||||
*
|
||||
* Reblogging a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_reblog ($id) {
|
||||
$response = $this->_post('/api/v1/statuses/'.$id.'/reblog');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_unreblog
|
||||
*
|
||||
* Unreblogging a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_unreblog ($id) {
|
||||
$response = $this->_post('/api/v1/statuses/'.$id.'/unreblog');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_favourite
|
||||
*
|
||||
* Favouriting a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_favourite ($id) {
|
||||
$response = $this->_post('/api/v1/statuses/'.$id.'/favourite');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_unfavourite
|
||||
*
|
||||
* Unfavouriting a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_unfavourite ($id) {
|
||||
$response = $this->_post('/api/v1/statuses/'.$id.'/unfavourite');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* timelines_home
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function timelines_home () {
|
||||
$response = $this->_get('/api/v1/timelines/home');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* timelines_public
|
||||
*
|
||||
* @param array $parameters
|
||||
* bool $parameters['local'] Only return statuses originating from this instance
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function timelines_public ($parameters = array()) {
|
||||
$response = $this->_get('/api/v1/timelines/public',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* timelines_tag
|
||||
*
|
||||
* @param string $hashtag
|
||||
* @param array $parameters
|
||||
* bool $parameters['local'] Only return statuses originating from this instance
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function timelines_tag ($hashtag,$parameters = array()) {
|
||||
$response = $this->_get('/api/v1/timelines/tag/'.$hashtag,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# Mastodon-api-php
|
||||
A GNU Social-compatible microblogging server https://mastodon.social PHP API
|
||||
|
||||
## How to use
|
||||
require_once '/path/Mastodon_api.php';<br />
|
||||
<br />
|
||||
$mastodon_api = new Mastodon_api();<br />
|
||||
$mastodon_api->set_url('Mastodon url');<br />
|
||||
<br />
|
||||
// print_r($mastodon_api->create_app('APP Name',null,null,'Mastodon url'));<br />
|
||||
$mastodon_api->set_client('client_id','client_secret');<br />
|
||||
<br />
|
||||
// print_r($mastodon_api->login('your login email','your login password'));<br />
|
||||
$mastodon_api->set_token('access_token','token_type');<br />
|
||||
<br />
|
||||
$mastodon_api->timelines_home();
|
||||
|
||||
## Test Mastodon
|
||||
https://ery.kr
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
#!/usr/bin/env php
|
||||
namespace HalcyonSuite\HalcyonForMastodon;
|
||||
|
||||
require_once('database.php');
|
||||
require_once('Mastodon-api-php/Mastodon_api.php');
|
||||
|
||||
use HalcyonSuite\HalcyonForMastodon\Database;
|
||||
use PDO;
|
||||
use Exception;
|
||||
|
||||
/*-------------------
|
||||
class for halcyon
|
||||
--------------------*/
|
||||
class Mastodon extends \Mastodon_api
|
||||
{
|
||||
|
||||
function __construct(){
|
||||
$appSettings = parse_ini_file('../../config.ini', true);
|
||||
|
||||
$this->clientName = $appSettings["App"]["api_client_name"];
|
||||
$this->clientRedirectUris = $appSettings["App"]["api_client_website"].'/auth urn:ietf:wg:oauth:2.0:oob';
|
||||
$this->clientWebsite = $appSettings["App"]["api_client_website"];
|
||||
$this->clientScopes = array('read', 'write', 'follow');
|
||||
$this->instances = array();
|
||||
|
||||
$this->dbHost = $appSettings["Mysql"]["db_host"];
|
||||
$this->dbUser = $appSettings["Mysql"]["db_user"];
|
||||
$this->dbPass = $appSettings["Mysql"]["db_pass"];
|
||||
$this->dbName = $appSettings["Mysql"]["db_name"];
|
||||
|
||||
$this->database = new Database($this->dbHost, $this->dbUser, $this->dbPass, $this->dbName);
|
||||
$this->readInstances();
|
||||
}
|
||||
|
||||
/* note: $domainって書いてあるけど、ドメインじゃなくてURLです。すみません */
|
||||
|
||||
private function newInstance($domain)
|
||||
{
|
||||
$res = $this->create_app($this->clientName, $this->clientScopes, $this->clientRedirectUris, $this->clientWebsite);
|
||||
if (isset($res['html']['client_id'])) {
|
||||
$this->instances[$domain] = $res['html'];
|
||||
$this->database->dbExecute("insert into instances(domain, client_id, client_secret) values(?,?,?)", array($domain, $res['html']['client_id'], $res['html']['client_secret']));
|
||||
// insert into instances(domain, client_id, client_secret) values($domain, $client_id, $client_secret)
|
||||
}else{
|
||||
throw new Exception("Invalid instance");
|
||||
}
|
||||
}
|
||||
|
||||
public function selectInstance($domain)
|
||||
{
|
||||
$this->set_url($domain);
|
||||
if (!$this->instanceExists($domain)) {
|
||||
$this->newInstance($domain);
|
||||
}
|
||||
$this->set_client($this->instances[$domain]['client_id'], $this->instances[$domain]['client_secret']);
|
||||
}
|
||||
|
||||
public function getInstance($domain)
|
||||
{
|
||||
$this->set_url($domain);
|
||||
if (!$this->instanceExists($domain)) {
|
||||
$this->newInstance($domain);
|
||||
}
|
||||
return array('client_id' => $this->instances[$domain]['client_id'], 'client_secret' => $this->instances[$domain]['client_secret']);
|
||||
}
|
||||
|
||||
public function instanceExists($domain)
|
||||
{
|
||||
return isset($this->instances[$domain]);
|
||||
}
|
||||
|
||||
private function readInstances()
|
||||
{
|
||||
$stmt = $this->database->dbExecute("select domain,client_id,client_secret from instances");
|
||||
foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $row){
|
||||
$this->instances[$row['domain']] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
#!/usr/bin/env php
|
||||
namespace HalcyonSuite\HalcyonForMastodon;
|
||||
use PDO;
|
||||
use Exception;
|
||||
|
||||
class Database{
|
||||
public function __construct($dbhost, $dbuser, $dbpass, $dbname){
|
||||
$this->dbhost = $dbhost;
|
||||
$this->dbuser = $dbuser;
|
||||
$this->dbpass = $dbpass;
|
||||
$this->dbname = $dbname;
|
||||
$this->dsn = "mysql:dbname=".$this->dbname.";host=".$this->dbhost.";charset=utf8";
|
||||
$this->connecting = false;
|
||||
$this->dbConnect();
|
||||
}
|
||||
|
||||
public function dbConnect($commit=True){
|
||||
try{
|
||||
$dbh = new PDO($this->dsn, $this->dbuser, $this->dbpass);
|
||||
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
if(!$commit){
|
||||
$dbh->beginTransaction();
|
||||
}
|
||||
}catch (PDOException $e){
|
||||
throw new Exception($e);
|
||||
}
|
||||
$this->dbh = $dbh;
|
||||
$this->connecting = true;
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
public function dbClose(){
|
||||
$this->dbh = Null;
|
||||
$this->connecting = false;
|
||||
}
|
||||
|
||||
public function dbExecute($sql, $attr = null){
|
||||
if ($attr === null) {
|
||||
$attr = array();
|
||||
}
|
||||
if (!$this->connecting) {
|
||||
$this->dbConnect();
|
||||
}
|
||||
$stmt = $this->dbh->prepare($sql);
|
||||
$stmt->execute($attr);
|
||||
return $stmt;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,11 @@
|
|||
; Registar App Settings
|
||||
[App]
|
||||
api_client_name = APPLICATION'S NAME
|
||||
api_client_website = HTTPS://YOURDOMAIN.COM/
|
||||
|
||||
; MySQL Settings
|
||||
[Mysql]
|
||||
db_host = YOUR DATABASE'S HOST
|
||||
db_user = YOUR DATABASE'S USER
|
||||
db_pass = YOUR DATABASE'S PASSWORD
|
||||
db_name = YOUR DATABASE'S NAME
|
|
@ -0,0 +1,56 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
RewriteCond %{HTTP_HOST} ^www\.(.+?)$
|
||||
RewriteRule ^(.*)$ https://$1 [R=301,L]
|
||||
|
||||
RewriteCond %{SERVER_PORT} 80
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
||||
|
||||
# Main
|
||||
RewriteBase /
|
||||
RewriteRule ^home/?$ / [R=301]
|
||||
|
||||
RewriteBase /login
|
||||
RewriteRule ^login/?$ login/login\.php [NC,L,QSA]
|
||||
RewriteRule ^auth/?$ login/auth\.php [NC,L,QSA]
|
||||
RewriteRule ^logout/?$ login/logout\.php [NC,L,QSA]
|
||||
RewriteRule ^terms/?$ login/terms\.php [NC,L,QSA]
|
||||
|
||||
# LTL
|
||||
RewriteBase /local
|
||||
RewriteRule ^local/?$ local\.php [NC,L]
|
||||
|
||||
# FTL
|
||||
RewriteBase /federated
|
||||
RewriteRule ^federated/?$ federated\.php [NC,L]
|
||||
|
||||
# Notice
|
||||
RewriteBase /notifications
|
||||
RewriteRule ^notifications/?$ notifications\.php [NC,L]
|
||||
|
||||
# Search
|
||||
RewriteBase /search
|
||||
RewriteRule ^search/?$ search_hash_tag\.php [NC,L,QSA]
|
||||
RewriteRule ^search/users/?$ search_user\.php [NC,L,QSA]
|
||||
|
||||
# User
|
||||
RewriteBase /
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/?$ user\.php?user=@$1@$2\.$3 [NC,L,QSA]
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/status/(.+?)?$ user\.php?user=@$1@$2\.$3&status=$4 [NC,L,QSA]
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/media/?$ user_only_media\.php?user=@$1@$2\.$3 [NC,L,QSA]
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/with_replies/?$ user_include_replies\.php?user=@$1@$2\.$3 [NC,L,QSA]
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/followers/?$ user_followers\.php?user=@$1@$2\.$3 [NC,L,QSA]
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/following/?$ user_following\.php?user=@$1@$2\.$3 [NC,L,QSA]
|
||||
RewriteRule ^@(.+)@(.+)\.([a-z]+)/favourites/?$ user_favorite\.php?user=@$1@$2\.$3 [NC,L,QSA]
|
||||
|
||||
# Image
|
||||
RewriteBase /
|
||||
RewriteRule ^avatars/original/missing\.png$ assets/images/missing\.png [NC,L]
|
||||
RewriteRule ^headers/original/missing\.png$ assets/images/missing_header\.png [NC,L]
|
||||
|
||||
# 404
|
||||
RewriteRule ^404/?$ 404\.php [NC,L,QSA]
|
||||
ErrorDocument 404 /404
|
||||
|
||||
</IfModule>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Halcyon / ?</title>
|
||||
|
||||
<link rel="shortcut icon" href="/assets/images/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/404.css" media="all" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<article>
|
||||
|
||||
<h1>404</h1>
|
||||
<h2>Sorry, something went wrong.</h2>
|
||||
|
||||
</article>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,169 @@
|
|||
@charset "utf-8";
|
||||
|
||||
/*--------------------------------------
|
||||
Reset
|
||||
--------------------------------------*/
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: top;
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: red!important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
.no-events {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.disallow_select {
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.text_ellipsis {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
blockquote * {
|
||||
margin: 0;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content:'';
|
||||
content:none;
|
||||
}
|
||||
|
||||
article,aside,details,figcaption,figure,
|
||||
footer,header,hgroup,menu,nav,section {
|
||||
display:block;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
button, input[type="submit"], input[type="button"]{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Twitter Emoji Prefix */
|
||||
img.emoji {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin: 0 .05em 0 .1em;
|
||||
vertical-align: -0.1em;
|
||||
}
|
||||
|
||||
.emoji_poss .auth_emoji {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
Base
|
||||
--------------------------------------*/
|
||||
|
||||
html {
|
||||
font-family : "Helvetica Neue",Helvetica,"ヒラギノ角ゴ Pro W3",
|
||||
"Hiragino Kaku Gothic Pro",Meiryo,"メイリオ","MS Pゴシック",Arial,sans-serif;
|
||||
font-size : 100%;
|
||||
line-height : 1;
|
||||
color: #333;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
word-wrap:break-word;
|
||||
background-color: #189EFC;
|
||||
}
|
||||
|
||||
article {
|
||||
margin: auto;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 248px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 56px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-weight: 200;
|
||||
}
|
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 361 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,258 @@
|
|||
/*-----------------------------------
|
||||
get Link from XHR Header
|
||||
-----------------------------------*/
|
||||
|
||||
function getLinkFromXHRHeader(xhrheaderstring) {
|
||||
const re = xhrheaderstring.match(/link: <.+api\/v1\/(.+?)>; rel="(.+?)", <.+api\/v1\/(.+?)>; rel="(.+?)"/);
|
||||
let di = new Object();
|
||||
if(re){
|
||||
di[re[2]] = re[1];
|
||||
di[re[4]] = re[3];
|
||||
}
|
||||
return di;
|
||||
}
|
||||
|
||||
/*----------------------------------
|
||||
Make relative URL
|
||||
----------------------------------*/
|
||||
|
||||
function getRelativeURL(url, id, options) {
|
||||
|
||||
const array = url.split('/');
|
||||
|
||||
if ( array.length >= 4 ) {
|
||||
if ( !options ) {
|
||||
var options = ""
|
||||
};
|
||||
|
||||
if (id) {
|
||||
// IF WITHIN ID
|
||||
if (array[array.length-1].substr(0,1) === '@') {
|
||||
const link = '/'+array[array.length-1]+'@'+array[2]+options+'?mid='+id+'&';
|
||||
return link;
|
||||
} else {
|
||||
const link = '/@'+array[array.length-1]+'@'+array[2]+options+'?mid='+id+'&';
|
||||
return link;
|
||||
}
|
||||
|
||||
} else {
|
||||
// IF WITHOUT ID (URL ONLY)
|
||||
if (array[array.length-1].substr(0,1) === '@') {
|
||||
const link = '/'+array[array.length-1]+'@'+array[2]+options;
|
||||
return link;
|
||||
} else {
|
||||
const link = '/@'+array[array.length-1]+'@'+array[2]+options;
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------
|
||||
Replace Mastodon link for Halcyon
|
||||
-----------------------------------*/
|
||||
|
||||
function replaceInternalLink(){
|
||||
// REPLIES
|
||||
$(".h-card > a").each(function(i) {
|
||||
$(this).attr('href',getRelativeURL($(this).attr('href')));
|
||||
});
|
||||
// HASHTAGS
|
||||
$(".toot_article a").each(function(i) {
|
||||
const tags = $(this).attr('href').match(/https:\/\/.+..+\/tags\/(.+)\/?/);
|
||||
if (tags) {
|
||||
$(this).attr('href','/search?q='+tags[1]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*-----------------------------------
|
||||
Datetime exchange
|
||||
-----------------------------------*/
|
||||
|
||||
function getConversionedDate(key, value) {
|
||||
if (value === null ||
|
||||
value.constructor !== String ||
|
||||
value.search(/^\d{4}-\d{2}-\d{2}/g) === -1)
|
||||
return value;
|
||||
return new Date(value);
|
||||
}
|
||||
|
||||
/*----------------------------------
|
||||
Relative Datetime
|
||||
----------------------------------*/
|
||||
|
||||
function getRelativeDatetime(current_time, posted_time) {
|
||||
const calendar = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
|
||||
var posted_time_original = posted_time,
|
||||
posted_time = getConversionedDate(null, posted_time_original).getTime(),
|
||||
elapsedTime = Math.ceil((current_time-posted_time)/1000);
|
||||
|
||||
if (elapsedTime < 60) {
|
||||
const datetime = "・" + elapsedTime + "s";
|
||||
return datetime;
|
||||
|
||||
} else if (elapsedTime < 120) {
|
||||
const datetime = "・1m";
|
||||
return datetime;
|
||||
|
||||
} else if (elapsedTime < (60*60)) {
|
||||
const datetime = "・" + (Math.floor(elapsedTime / 60) < 10 ? " " : "") + Math.floor(elapsedTime / 60) + "m";
|
||||
return datetime;
|
||||
|
||||
} else if (elapsedTime < (120*60)) {
|
||||
const datetime = "・1h";
|
||||
return datetime;
|
||||
|
||||
} else if (elapsedTime < (24*60*60)) {
|
||||
const datetime = "・" + (Math.floor(elapsedTime / 3600) < 10 ? " " : "") + Math.floor(elapsedTime / 3600) + "h";
|
||||
return datetime;
|
||||
|
||||
} else {
|
||||
const datetime = "・" + calendar[posted_time_original.getMonth()] + " " + posted_time_original.getDate();
|
||||
return datetime;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------
|
||||
ResetApp
|
||||
-----------------------------------*/
|
||||
|
||||
function resetApp() {
|
||||
|
||||
/* IMPORTANT */
|
||||
current_id = Number(localStorage.getItem("current_id"));
|
||||
current_instance = localStorage.getItem("current_instance");
|
||||
authtoken = localStorage.getItem("current_authtoken");
|
||||
|
||||
// Start api
|
||||
api = new MastodonAPI({
|
||||
instance: 'https://'+current_instance,
|
||||
api_user_token: authtoken
|
||||
});
|
||||
|
||||
// Set local storage items
|
||||
api.get("accounts/verify_credentials", function(AccountObj) {
|
||||
|
||||
// SAVE PROFILE FOR LOCALSTORAGE (ENABLE BETWEEN ONE SESSION)
|
||||
localStorage.setItem("current_display_name", AccountObj["display_name"]);
|
||||
localStorage.setItem("current_acct", AccountObj["acct"]);
|
||||
localStorage.setItem("current_url", getRelativeURL(AccountObj["url"],AccountObj["id"]));
|
||||
localStorage.setItem("current_header", AccountObj["header"]);
|
||||
localStorage.setItem("current_avatar", AccountObj["avatar"]);
|
||||
localStorage.setItem("current_statuses_count", AccountObj["statuses_count"]);
|
||||
localStorage.setItem("current_following_count", AccountObj["following_count"]);
|
||||
localStorage.setItem("current_followers_count", AccountObj["followers_count"]);
|
||||
localStorage.setItem("current_statuses_count_link", getRelativeURL(AccountObj["url"],AccountObj["id"]));
|
||||
localStorage.setItem("current_following_count_link", getRelativeURL(AccountObj["url"],AccountObj["id"],'/following'));
|
||||
localStorage.setItem("current_followers_count_link", getRelativeURL(AccountObj["url"],AccountObj["id"],'/followers'));
|
||||
localStorage.setItem("current_favourites_link", getRelativeURL(AccountObj["url"],AccountObj["id"],'/favourites'));
|
||||
|
||||
// PROFILE
|
||||
current_display_name = localStorage.getItem("current_display_name");
|
||||
current_acct = localStorage.getItem("current_acct");
|
||||
current_url = localStorage.getItem("current_url");
|
||||
current_header = localStorage.getItem("current_header");
|
||||
current_avatar = localStorage.getItem("current_avatar");
|
||||
current_statuses_count = localStorage.getItem("current_statuses_count");
|
||||
current_following_count = localStorage.getItem("current_following_count");
|
||||
current_followers_count = localStorage.getItem("current_followers_count");
|
||||
current_statuses_count_link = localStorage.getItem("current_statuses_count_link");
|
||||
current_following_count_link = localStorage.getItem("current_following_count_link");
|
||||
current_followers_count_link = localStorage.getItem("current_followers_count_link");
|
||||
current_favourites_link = localStorage.getItem("current_favourites_link");
|
||||
|
||||
// REPLACE USER'S INFORMATIONS
|
||||
$(".js_current_profile_displayname").text(current_display_name);
|
||||
$(".js_current_profile_username").text(current_acct);
|
||||
$(".js_current_profile_link").attr('href', current_url);
|
||||
$(".js_current_header_image").attr('src', current_header);
|
||||
$(".js_current_profile_image").attr('src', current_avatar);
|
||||
$(".js_current_toots_count").text(current_statuses_count);
|
||||
$(".js_current_following_count").text(current_following_count);
|
||||
$(".js_current_followers_count").text(current_followers_count);
|
||||
$(".current_toots_count_link").attr('href', current_statuses_count_link);
|
||||
$(".current_following_count_link").attr('href', current_following_count_link);
|
||||
$(".current_followers_count_link").attr('href', current_followers_count_link);
|
||||
|
||||
replace_emoji();
|
||||
|
||||
});
|
||||
|
||||
$.cookie("session", "true", { path: '/' });
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------
|
||||
RefreshApp
|
||||
-----------------------------------*/
|
||||
|
||||
function refreshApp() {
|
||||
|
||||
// IMPORTANT
|
||||
current_id = Number(localStorage.getItem("current_id"));
|
||||
current_instance = localStorage.getItem("current_instance");
|
||||
authtoken = localStorage.getItem("current_authtoken");
|
||||
|
||||
// Start api
|
||||
api = new MastodonAPI({
|
||||
instance: "https://"+current_instance,
|
||||
api_user_token: authtoken
|
||||
});
|
||||
|
||||
// PROFILE
|
||||
current_display_name = localStorage.getItem("current_display_name");
|
||||
current_acct = localStorage.getItem("current_acct");
|
||||
current_url = localStorage.getItem("current_url");
|
||||
current_header = localStorage.getItem("current_header");
|
||||
current_avatar = localStorage.getItem("current_avatar");
|
||||
current_statuses_count = localStorage.getItem("current_statuses_count");
|
||||
current_following_count = localStorage.getItem("current_following_count");
|
||||
current_followers_count = localStorage.getItem("current_followers_count");
|
||||
current_statuses_count_link = localStorage.getItem("current_statuses_count_link");
|
||||
current_following_count_link = localStorage.getItem("current_following_count_link");
|
||||
current_followers_count_link = localStorage.getItem("current_followers_count_link");
|
||||
current_favourites_link = localStorage.getItem("current_favourites_link");
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------
|
||||
Profile
|
||||
-----------------------------------*/
|
||||
|
||||
function setCurrentProfile() {
|
||||
|
||||
// REPLACE USER'S INFORMATIONS
|
||||
$(".js_current_profile_displayname").text(current_display_name);
|
||||
$(".js_current_profile_username").text(current_acct);
|
||||
$(".js_current_profile_link").attr("href", current_url);
|
||||
$(".js_current_header_image").attr("src", current_header);
|
||||
$(".js_current_profile_image").attr("src", current_avatar);
|
||||
$(".js_current_toots_count").text(current_statuses_count);
|
||||
$(".js_current_following_count").text(current_following_count);
|
||||
$(".js_current_followers_count").text(current_followers_count);
|
||||
$(".current_toots_count_link").attr("href", current_statuses_count_link);
|
||||
$(".current_following_count_link").attr("href", current_following_count_link);
|
||||
$(".current_followers_count_link").attr("href", current_followers_count_link);
|
||||
|
||||
replace_emoji();
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------
|
||||
Set User recent images
|
||||
----------------------------------*/
|
||||
|
||||
function putMessage(Message) {
|
||||
|
||||
$('#overlay_message').addClass('view');
|
||||
$('#overlay_message section span').text(Message);
|
||||
|
||||
setTimeout(function(){
|
||||
$("#overlay_message").removeClass("view");
|
||||
},3000);
|
||||
|
||||
};
|
|
@ -0,0 +1,73 @@
|
|||
HEAD
|
||||
-----
|
||||
|
||||
1.4.1
|
||||
-----
|
||||
- Added support for CommonJS.
|
||||
|
||||
- Added support for package managers: Jam (http://jamjs.org), volo (http://volojs.org), Component (http://component.io), jspm (http://jspm.io).
|
||||
|
||||
- The expires option now interpretes fractions of numbers (e.g. days) correctly.
|
||||
|
||||
1.4.0
|
||||
-----
|
||||
- Support for AMD.
|
||||
|
||||
- Removed deprecated method `$.cookie('name', null)` for deleting a cookie,
|
||||
use `$.removeCookie('name')`.
|
||||
|
||||
- `$.cookie('name')` now returns `undefined` in case such cookie does not exist
|
||||
(was `null`). Because the return value is still falsy, testing for existence
|
||||
of a cookie like `if ( $.cookie('foo') )` keeps working without change.
|
||||
|
||||
- Renamed bower package definition (component.json -> bower.json) for usage
|
||||
with up-to-date bower.
|
||||
|
||||
- Badly encoded cookies no longer throw exception upon reading but do return
|
||||
undefined (similar to how we handle JSON parse errors with json = true).
|
||||
|
||||
- Added conversion function as optional last argument for reading,
|
||||
so that values can be changed to a different representation easily on the fly.
|
||||
Useful for parsing numbers for instance:
|
||||
|
||||
```javascript
|
||||
$.cookie('foo', '42');
|
||||
$.cookie('foo', Number); // => 42
|
||||
```
|
||||
|
||||
1.3.1
|
||||
-----
|
||||
- Fixed issue where it was no longer possible to check for an arbitrary cookie,
|
||||
while json is set to true, there was a SyntaxError thrown from JSON.parse.
|
||||
|
||||
- Fixed issue where RFC 2068 decoded cookies were not properly read.
|
||||
|
||||
1.3.0
|
||||
-----
|
||||
- Configuration options: `raw`, `json`. Replaces raw option, becomes config:
|
||||
|
||||
```javascript
|
||||
$.cookie.raw = true; // bypass encoding/decoding the cookie value
|
||||
$.cookie.json = true; // automatically JSON stringify/parse value
|
||||
```
|
||||
|
||||
Thus the default options now cleanly contain cookie attributes only.
|
||||
|
||||
- Removing licensing under GPL Version 2, the plugin is now released under MIT License only
|
||||
(keeping it simple and following the jQuery library itself here).
|
||||
|
||||
- Bugfix: Properly handle RFC 2068 quoted cookie values.
|
||||
|
||||
- Added component.json for bower.
|
||||
|
||||
- Added jQuery plugin package manifest.
|
||||
|
||||
- `$.cookie()` returns all available cookies.
|
||||
|
||||
1.2.0
|
||||
-----
|
||||
- Adding `$.removeCookie('foo')` for deleting a cookie, using `$.cookie('foo', null)` is now deprecated.
|
||||
|
||||
1.1
|
||||
---
|
||||
- Adding default options.
|
|
@ -0,0 +1,51 @@
|
|||
##Issues
|
||||
|
||||
- Report issues or feature requests on [GitHub Issues](https://github.com/carhartl/jquery-cookie/issues).
|
||||
- If reporting a bug, please add a [simplified example](http://sscce.org/).
|
||||
|
||||
##Pull requests
|
||||
- Create a new topic branch for every separate change you make.
|
||||
- Create a test case if you are fixing a bug or implementing an important feature.
|
||||
- Make sure the build runs successfully.
|
||||
|
||||
## Development
|
||||
|
||||
###Tools
|
||||
We use the following tools for development:
|
||||
|
||||
- [Qunit](http://qunitjs.com/) for tests.
|
||||
- [NodeJS](http://nodejs.org/download/) required to run grunt.
|
||||
- [Grunt](http://gruntjs.com/getting-started) for task management.
|
||||
|
||||
###Getting started
|
||||
Install [NodeJS](http://nodejs.org/).
|
||||
Install globally grunt-cli using the following command:
|
||||
|
||||
$ npm install -g grunt-cli
|
||||
|
||||
Browse to the project root directory and install the dev dependencies:
|
||||
|
||||
$ npm install -d
|
||||
|
||||
To execute the build and tests run the following command in the root of the project:
|
||||
|
||||
$ grunt
|
||||
|
||||
You should see a green message in the console:
|
||||
|
||||
Done, without errors.
|
||||
|
||||
###Tests
|
||||
You can also run the tests in the browser.
|
||||
Start a test server from the project root:
|
||||
|
||||
$ grunt connect:tests
|
||||
|
||||
This will automatically open the test suite at http://127.0.0.1:9998 in the default browser, with livereload enabled.
|
||||
|
||||
_Note: we recommend cleaning all the browser cookies before running the tests, that can avoid false positive failures._
|
||||
|
||||
###Automatic build
|
||||
You can build automatically after a file change using the following command:
|
||||
|
||||
$ grunt watch
|
|
@ -0,0 +1,168 @@
|
|||
/*jshint node:true, quotmark:single */
|
||||
'use strict';
|
||||
|
||||
module.exports = function (grunt) {
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
qunit: {
|
||||
all: 'test/index.html'
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: true
|
||||
},
|
||||
grunt: 'Gruntfile.js',
|
||||
source: 'src/**/*.js',
|
||||
tests: 'test/**/*.js'
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %> v<%= pkg.version %> | <%= pkg.license %> */\n'
|
||||
},
|
||||
build: {
|
||||
files: {
|
||||
'build/jquery.cookie-<%= pkg.version %>.min.js': 'src/jquery.cookie.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
livereload: true
|
||||
},
|
||||
files: '{src,test}/**/*.js',
|
||||
tasks: 'default'
|
||||
},
|
||||
compare_size: {
|
||||
files: [
|
||||
'build/jquery.cookie-<%= pkg.version %>.min.js',
|
||||
'src/jquery.cookie.js'
|
||||
],
|
||||
options: {
|
||||
compress: {
|
||||
gz: function (fileContents) {
|
||||
return require('gzip-js').zip(fileContents, {}).length;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
connect: {
|
||||
saucelabs: {
|
||||
options: {
|
||||
port: 9999,
|
||||
base: ['.', 'test']
|
||||
}
|
||||
},
|
||||
tests: {
|
||||
options: {
|
||||
port: 9998,
|
||||
base: ['.', 'test'],
|
||||
open: 'http://127.0.0.1:9998',
|
||||
keepalive: true,
|
||||
livereload: true
|
||||
}
|
||||
}
|
||||
},
|
||||
'saucelabs-qunit': {
|
||||
all: {
|
||||
options: {
|
||||
urls: ['http://127.0.0.1:9999'],
|
||||
build: process.env.TRAVIS_JOB_ID,
|
||||
browsers: [
|
||||
// iOS
|
||||
{
|
||||
browserName: 'iphone',
|
||||
platform: 'OS X 10.9',
|
||||
version: '7.1'
|
||||
},
|
||||
{
|
||||
browserName: 'ipad',
|
||||
platform: 'OS X 10.9',
|
||||
version: '7.1'
|
||||
},
|
||||
// Android
|
||||
{
|
||||
browserName: 'android',
|
||||
platform: 'Linux',
|
||||
version: '4.3'
|
||||
},
|
||||
// OS X
|
||||
{
|
||||
browserName: 'safari',
|
||||
platform: 'OS X 10.9',
|
||||
version: '7'
|
||||
},
|
||||
{
|
||||
browserName: 'safari',
|
||||
platform: 'OS X 10.8',
|
||||
version: '6'
|
||||
},
|
||||
{
|
||||
browserName: 'firefox',
|
||||
platform: 'OS X 10.9',
|
||||
version: '28'
|
||||
},
|
||||
// Windows
|
||||
{
|
||||
browserName: 'internet explorer',
|
||||
platform: 'Windows 8.1',
|
||||
version: '11'
|
||||
},
|
||||
{
|
||||
browserName: 'internet explorer',
|
||||
platform: 'Windows 8',
|
||||
version: '10'
|
||||
},
|
||||
{
|
||||
browserName: 'internet explorer',
|
||||
platform: 'Windows 7',
|
||||
version: '11'
|
||||
},
|
||||
{
|
||||
browserName: 'internet explorer',
|
||||
platform: 'Windows 7',
|
||||
version: '10'
|
||||
},
|
||||
{
|
||||
browserName: 'internet explorer',
|
||||
platform: 'Windows 7',
|
||||
version: '9'
|
||||
},
|
||||
{
|
||||
browserName: 'internet explorer',
|
||||
platform: 'Windows 7',
|
||||
version: '8'
|
||||
},
|
||||
{
|
||||
browserName: 'firefox',
|
||||
platform: 'Windows 7',
|
||||
version: '29'
|
||||
},
|
||||
{
|
||||
browserName: 'chrome',
|
||||
platform: 'Windows 7',
|
||||
version: '34'
|
||||
},
|
||||
// Linux
|
||||
{
|
||||
browserName: 'firefox',
|
||||
platform: 'Linux',
|
||||
version: '29'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Loading dependencies
|
||||
for (var key in grunt.file.readJSON('package.json').devDependencies) {
|
||||
if (key !== 'grunt' && key.indexOf('grunt') === 0) {
|
||||
grunt.loadNpmTasks(key);
|
||||
}
|
||||
}
|
||||
|
||||
grunt.registerTask('default', ['jshint', 'qunit', 'uglify', 'compare_size']);
|
||||
grunt.registerTask('saucelabs', ['connect:saucelabs', 'saucelabs-qunit']);
|
||||
grunt.registerTask('ci', ['jshint', 'qunit', 'saucelabs']);
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
Copyright 2014 Klaus Hartl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,162 @@
|
|||
# IMPORTANT!
|
||||
|
||||
This project was moved to https://github.com/js-cookie/js-cookie, check [the discussion](https://github.com/carhartl/jquery-cookie/issues/349).
|
||||
|
||||
New issues should be opened at https://github.com/js-cookie/js-cookie/issues
|
||||
|
||||
# jquery.cookie [![Build Status](https://travis-ci.org/carhartl/jquery-cookie.png?branch=master)](https://travis-ci.org/carhartl/jquery-cookie) [![Code Climate](https://codeclimate.com/github/carhartl/jquery-cookie.png)](https://codeclimate.com/github/carhartl/jquery-cookie)
|
||||
|
||||
A simple, lightweight jQuery plugin for reading, writing and deleting cookies.
|
||||
|
||||
**If you're viewing this, you're reading the documentation for the old repository.
|
||||
[View documentation for the latest backwards compatible release (1.5.1).](https://github.com/js-cookie/js-cookie/tree/v1.5.1)**
|
||||
|
||||
## Build Status Matrix
|
||||
|
||||
[![Selenium Test Status](https://saucelabs.com/browser-matrix/jquery-cookie.svg)](https://saucelabs.com/u/jquery-cookie)
|
||||
|
||||
## Installation
|
||||
|
||||
Include script *after* the jQuery library (unless you are packaging scripts somehow else):
|
||||
|
||||
```html
|
||||
<script src="/path/to/jquery.cookie.js"></script>
|
||||
```
|
||||
|
||||
**Do not include the script directly from GitHub (http://raw.github.com/...).** The file is being served as text/plain and as such being blocked
|
||||
in Internet Explorer on Windows 7 for instance (because of the wrong MIME type). Bottom line: GitHub is not a CDN.
|
||||
|
||||
The plugin can also be loaded as AMD or CommonJS module.
|
||||
|
||||
## Usage
|
||||
|
||||
Create session cookie:
|
||||
|
||||
```javascript
|
||||
$.cookie('name', 'value');
|
||||
```
|
||||
|
||||
Create expiring cookie, 7 days from then:
|
||||
|
||||
```javascript
|
||||
$.cookie('name', 'value', { expires: 7 });
|
||||
```
|
||||
|
||||
Create expiring cookie, valid across entire site:
|
||||
|
||||
```javascript
|
||||
$.cookie('name', 'value', { expires: 7, path: '/' });
|
||||
```
|
||||
|
||||
Read cookie:
|
||||
|
||||
```javascript
|
||||
$.cookie('name'); // => "value"
|
||||
$.cookie('nothing'); // => undefined
|
||||
```
|
||||
|
||||
Read all available cookies:
|
||||
|
||||
```javascript
|
||||
$.cookie(); // => { "name": "value" }
|
||||
```
|
||||
|
||||
Delete cookie:
|
||||
|
||||
```javascript
|
||||
// Returns true when cookie was successfully deleted, otherwise false
|
||||
$.removeCookie('name'); // => true
|
||||
$.removeCookie('nothing'); // => false
|
||||
|
||||
// Need to use the same attributes (path, domain) as what the cookie was written with
|
||||
$.cookie('name', 'value', { path: '/' });
|
||||
// This won't work!
|
||||
$.removeCookie('name'); // => false
|
||||
// This will work!
|
||||
$.removeCookie('name', { path: '/' }); // => true
|
||||
```
|
||||
|
||||
*Note: when deleting a cookie, you must pass the exact same path, domain and secure options that were used to set the cookie, unless you're relying on the default options that is.*
|
||||
|
||||
## Configuration
|
||||
|
||||
### raw
|
||||
|
||||
By default the cookie value is encoded/decoded when writing/reading, using `encodeURIComponent`/`decodeURIComponent`. Bypass this by setting raw to true:
|
||||
|
||||
```javascript
|
||||
$.cookie.raw = true;
|
||||
```
|
||||
|
||||
### json
|
||||
|
||||
Turn on automatic storage of JSON objects passed as the cookie value. Assumes `JSON.stringify` and `JSON.parse`:
|
||||
|
||||
```javascript
|
||||
$.cookie.json = true;
|
||||
```
|
||||
|
||||
## Cookie Options
|
||||
|
||||
Cookie attributes can be set globally by setting properties of the `$.cookie.defaults` object or individually for each call to `$.cookie()` by passing a plain object to the options argument. Per-call options override the default options.
|
||||
|
||||
### expires
|
||||
|
||||
expires: 365
|
||||
|
||||
Define lifetime of the cookie. Value can be a `Number` which will be interpreted as days from time of creation or a `Date` object. If omitted, the cookie becomes a session cookie.
|
||||
|
||||
### path
|
||||
|
||||
path: '/'
|
||||
|
||||
Define the path where the cookie is valid. *By default the path of the cookie is the path of the page where the cookie was created (standard browser behavior).* If you want to make it available for instance across the entire domain use `path: '/'`. Default: path of page where the cookie was created.
|
||||
|
||||
**Note regarding Internet Explorer:**
|
||||
|
||||
> Due to an obscure bug in the underlying WinINET InternetGetCookie implementation, IE’s document.cookie will not return a cookie if it was set with a path attribute containing a filename.
|
||||
|
||||
(From [Internet Explorer Cookie Internals (FAQ)](http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx))
|
||||
|
||||
This means one cannot set a path using `path: window.location.pathname` in case such pathname contains a filename like so: `/check.html` (or at least, such cookie cannot be read correctly).
|
||||
|
||||
### domain
|
||||
|
||||
domain: 'example.com'
|
||||
|
||||
Define the domain where the cookie is valid. Default: domain of page where the cookie was created.
|
||||
|
||||
### secure
|
||||
|
||||
secure: true
|
||||
|
||||
If true, the cookie transmission requires a secure protocol (https). Default: `false`.
|
||||
|
||||
## Converters
|
||||
|
||||
Provide a conversion function as optional last argument for reading, in order to change the cookie's value
|
||||
to a different representation on the fly.
|
||||
|
||||
Example for parsing a value into a number:
|
||||
|
||||
```javascript
|
||||
$.cookie('foo', '42');
|
||||
$.cookie('foo', Number); // => 42
|
||||
```
|
||||
|
||||
Dealing with cookies that have been encoded using `escape` (3rd party cookies):
|
||||
|
||||
```javascript
|
||||
$.cookie.raw = true;
|
||||
$.cookie('foo', unescape);
|
||||
```
|
||||
|
||||
You can pass an arbitrary conversion function.
|
||||
|
||||
## Contributing
|
||||
|
||||
Check out the [Contributing Guidelines](CONTRIBUTING.md)
|
||||
|
||||
## Authors
|
||||
|
||||
[Klaus Hartl](https://github.com/carhartl)
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "jquery.cookie",
|
||||
"version": "1.4.1",
|
||||
"main": [
|
||||
"src/jquery.cookie.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">=1.2"
|
||||
},
|
||||
"ignore": [
|
||||
"test",
|
||||
".*",
|
||||
"*.json",
|
||||
"*.md",
|
||||
"*.txt",
|
||||
"Gruntfile.js"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "jquery.cookie",
|
||||
"repo": "carhartl/jquery-cookie",
|
||||
"description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies",
|
||||
"version": "1.4.1",
|
||||
"keywords": [],
|
||||
"dependencies": {},
|
||||
"development": {},
|
||||
"license": "MIT",
|
||||
"main": "src/jquery.cookie.js",
|
||||
"scripts": [
|
||||
"src/jquery.cookie.js"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "cookie",
|
||||
"version": "1.4.1",
|
||||
"title": "jQuery Cookie",
|
||||
"description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies.",
|
||||
"author": {
|
||||
"name": "Klaus Hartl",
|
||||
"url": "https://github.com/carhartl"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Klaus Hartl",
|
||||
"url": "https://github.com/carhartl"
|
||||
},
|
||||
{
|
||||
"name": "Fagner Martins",
|
||||
"url": "https://github.com/FagnerMartinsBrack"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://raw.github.com/carhartl/jquery-cookie/master/MIT-LICENSE.txt"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">=1.2"
|
||||
},
|
||||
"bugs": "https://github.com/carhartl/jquery-cookie/issues",
|
||||
"homepage": "https://github.com/carhartl/jquery-cookie",
|
||||
"docs": "https://github.com/carhartl/jquery-cookie#readme"
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "jquery.cookie",
|
||||
"version": "1.4.1",
|
||||
"description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies.",
|
||||
"main": "src/jquery.cookie.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/carhartl/jquery-cookie.git"
|
||||
},
|
||||
"author": "Klaus Hartl",
|
||||
"license": "MIT",
|
||||
"gitHead": "bd3c9713222bace68d25fe2128c0f8633cad1269",
|
||||
"readmeFilename": "README.md",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"grunt-contrib-uglify": "~0.2.0",
|
||||
"grunt-contrib-qunit": "~0.2.0",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-compare-size": "~0.4.0",
|
||||
"grunt-saucelabs": "~7.0.0",
|
||||
"grunt-contrib-connect": "~0.7.1",
|
||||
"gzip-js": "~0.3.0"
|
||||
},
|
||||
"volo": {
|
||||
"url": "https://raw.github.com/carhartl/jquery-cookie/v{version}/src/jquery.cookie.js"
|
||||
},
|
||||
"jspm": {
|
||||
"main": "jquery.cookie",
|
||||
"files": ["src/jquery.cookie.js"],
|
||||
"buildConfig": {
|
||||
"uglify": true
|
||||
}
|
||||
},
|
||||
"jam": {
|
||||
"dependencies": {
|
||||
"jquery": ">=1.2"
|
||||
},
|
||||
"main": "src/jquery.cookie.js",
|
||||
"include": [
|
||||
"src/jquery.cookie.js"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"browser": true,
|
||||
"camelcase": true,
|
||||
"jquery": true,
|
||||
"quotmark": "single",
|
||||
"globals": {
|
||||
"define": true,
|
||||
"module": true,
|
||||
"require": true
|
||||
},
|
||||
|
||||
"extends": "../.jshintrc"
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*!
|
||||
* jQuery Cookie Plugin v1.4.1
|
||||
* https://github.com/carhartl/jquery-cookie
|
||||
*
|
||||
* Copyright 2006, 2014 Klaus Hartl
|
||||
* Released under the MIT license
|
||||
*/
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD (Register as an anonymous module)
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS
|
||||
module.exports = factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
var pluses = /\+/g;
|
||||
|
||||
function encode(s) {
|
||||
return config.raw ? s : encodeURIComponent(s);
|
||||
}
|
||||
|
||||
function decode(s) {
|
||||
return config.raw ? s : decodeURIComponent(s);
|
||||
}
|
||||
|
||||
function stringifyCookieValue(value) {
|
||||
return encode(config.json ? JSON.stringify(value) : String(value));
|
||||
}
|
||||
|
||||
function parseCookieValue(s) {
|
||||
if (s.indexOf('"') === 0) {
|
||||
// This is a quoted cookie as according to RFC2068, unescape...
|
||||
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
||||
}
|
||||
|
||||
try {
|
||||
// Replace server-side written pluses with spaces.
|
||||
// If we can't decode the cookie, ignore it, it's unusable.
|
||||
// If we can't parse the cookie, ignore it, it's unusable.
|
||||
s = decodeURIComponent(s.replace(pluses, ' '));
|
||||
return config.json ? JSON.parse(s) : s;
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function read(s, converter) {
|
||||
var value = config.raw ? s : parseCookieValue(s);
|
||||
return $.isFunction(converter) ? converter(value) : value;
|
||||
}
|
||||
|
||||
var config = $.cookie = function (key, value, options) {
|
||||
|
||||
// Write
|
||||
|
||||
if (arguments.length > 1 && !$.isFunction(value)) {
|
||||
options = $.extend({}, config.defaults, options);
|
||||
|
||||
if (typeof options.expires === 'number') {
|
||||
var days = options.expires, t = options.expires = new Date();
|
||||
t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
|
||||
}
|
||||
|
||||
return (document.cookie = [
|
||||
encode(key), '=', stringifyCookieValue(value),
|
||||
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
||||
options.path ? '; path=' + options.path : '',
|
||||
options.domain ? '; domain=' + options.domain : '',
|
||||
options.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// Read
|
||||
|
||||
var result = key ? undefined : {},
|
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all. Also prevents odd result when
|
||||
// calling $.cookie().
|
||||
cookies = document.cookie ? document.cookie.split('; ') : [],
|
||||
i = 0,
|
||||
l = cookies.length;
|
||||
|
||||
for (; i < l; i++) {
|
||||
var parts = cookies[i].split('='),
|
||||
name = decode(parts.shift()),
|
||||
cookie = parts.join('=');
|
||||
|
||||
if (key === name) {
|
||||
// If second argument (value) is a function it's a converter...
|
||||
result = read(cookie, value);
|
||||
break;
|
||||
}
|
||||
|
||||
// Prevent storing a cookie that we couldn't decode.
|
||||
if (!key && (cookie = read(cookie)) !== undefined) {
|
||||
result[name] = cookie;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
config.defaults = {};
|
||||
|
||||
$.removeCookie = function (key, options) {
|
||||
// Must not alter options, thus extending a fresh object...
|
||||
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
|
||||
return !$.cookie(key);
|
||||
};
|
||||
|
||||
}));
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"browser": true,
|
||||
"jquery": true,
|
||||
"qunit": true,
|
||||
|
||||
"-W053": true,
|
||||
|
||||
"extends": "../.jshintrc"
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jquery.cookie Test Suite</title>
|
||||
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css">
|
||||
<script src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
|
||||
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
|
||||
<script src="../src/jquery.cookie.js"></script>
|
||||
<script src="tests.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
|
||||
<script src="../src/jquery.cookie.js"></script>
|
||||
<script>
|
||||
try {
|
||||
Object.defineProperty(document, "cookie", { get: function() { return "first=one; ; second=two"; } });
|
||||
window.testValue = $.cookie("second");
|
||||
window.ok = true;
|
||||
} catch (er) {
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,345 @@
|
|||
// Required for exposing test results to the Sauce Labs API.
|
||||
// Can be removed when the following issue is fixed:
|
||||
// https://github.com/axemclion/grunt-saucelabs/issues/84
|
||||
QUnit.done(function (details) {
|
||||
window.global_test_results = details;
|
||||
});
|
||||
|
||||
|
||||
var lifecycle = {
|
||||
teardown: function () {
|
||||
$.cookie.defaults = {};
|
||||
delete $.cookie.raw;
|
||||
delete $.cookie.json;
|
||||
$.each($.cookie(), $.removeCookie);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module('read', lifecycle);
|
||||
|
||||
test('simple value', function () {
|
||||
expect(1);
|
||||
document.cookie = 'c=v';
|
||||
strictEqual($.cookie('c'), 'v', 'should return value');
|
||||
});
|
||||
|
||||
test('empty value', function () {
|
||||
expect(1);
|
||||
// IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, which
|
||||
// resulted in a bug while reading such a cookie.
|
||||
$.cookie('c', '');
|
||||
strictEqual($.cookie('c'), '', 'should return value');
|
||||
});
|
||||
|
||||
test('not existing', function () {
|
||||
expect(1);
|
||||
strictEqual($.cookie('whatever'), undefined, 'return undefined');
|
||||
});
|
||||
|
||||
test('RFC 2068 quoted string', function () {
|
||||
expect(1);
|
||||
document.cookie = 'c="v@address.com\\"\\\\\\""';
|
||||
strictEqual($.cookie('c'), 'v@address.com"\\"', 'should decode RFC 2068 quoted string');
|
||||
});
|
||||
|
||||
test('decode', function () {
|
||||
expect(1);
|
||||
document.cookie = encodeURIComponent(' c') + '=' + encodeURIComponent(' v');
|
||||
strictEqual($.cookie(' c'), ' v', 'should decode key and value');
|
||||
});
|
||||
|
||||
test('decode pluses to space for server side written cookie', function () {
|
||||
expect(1);
|
||||
document.cookie = 'c=foo+bar';
|
||||
strictEqual($.cookie('c'), 'foo bar', 'should convert pluses back to space');
|
||||
});
|
||||
|
||||
test('raw = true', function () {
|
||||
expect(2);
|
||||
$.cookie.raw = true;
|
||||
|
||||
document.cookie = 'c=%20v';
|
||||
strictEqual($.cookie('c'), '%20v', 'should not decode value');
|
||||
|
||||
// see https://github.com/carhartl/jquery-cookie/issues/50
|
||||
$.cookie('c', 'foo=bar');
|
||||
strictEqual($.cookie('c'), 'foo=bar', 'should include the entire value');
|
||||
});
|
||||
|
||||
test('json = true', function () {
|
||||
expect(1);
|
||||
|
||||
if ('JSON' in window) {
|
||||
$.cookie.json = true;
|
||||
$.cookie('c', { foo: 'bar' });
|
||||
deepEqual($.cookie('c'), { foo: 'bar' }, 'should parse JSON');
|
||||
} else {
|
||||
ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
test('not existing with json = true', function () {
|
||||
expect(1);
|
||||
|
||||
if ('JSON' in window) {
|
||||
$.cookie.json = true;
|
||||
strictEqual($.cookie('whatever'), undefined, "won't throw exception");
|
||||
} else {
|
||||
ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
test('string with json = true', function () {
|
||||
expect(1);
|
||||
|
||||
if ('JSON' in window) {
|
||||
$.cookie.json = true;
|
||||
$.cookie('c', 'v');
|
||||
strictEqual($.cookie('c'), 'v', 'should return value');
|
||||
} else {
|
||||
ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
test('invalid JSON string with json = true', function () {
|
||||
expect(1);
|
||||
|
||||
if ('JSON' in window) {
|
||||
$.cookie('c', 'v');
|
||||
$.cookie.json = true;
|
||||
strictEqual($.cookie('c'), undefined, "won't throw exception, returns undefined");
|
||||
} else {
|
||||
ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
test('invalid URL encoding', function () {
|
||||
expect(1);
|
||||
document.cookie = 'bad=foo%';
|
||||
strictEqual($.cookie('bad'), undefined, "won't throw exception, returns undefined");
|
||||
// Delete manually here because it requires raw === true...
|
||||
$.cookie.raw = true;
|
||||
$.removeCookie('bad');
|
||||
});
|
||||
|
||||
asyncTest('malformed cookie value in IE (#88, #117)', function () {
|
||||
expect(1);
|
||||
// Sandbox in an iframe so that we can poke around with document.cookie.
|
||||
var iframe = $('<iframe src="malformed_cookie.html"></iframe>')[0];
|
||||
$(iframe).on('load', function () {
|
||||
start();
|
||||
if (iframe.contentWindow.ok) {
|
||||
strictEqual(iframe.contentWindow.testValue, 'two', 'reads all cookie values, skipping duplicate occurences of "; "');
|
||||
} else {
|
||||
// Skip the test where we can't stub document.cookie using
|
||||
// Object.defineProperty. Seems to work fine in
|
||||
// Chrome, Firefox and IE 8+.
|
||||
ok(true, 'N/A');
|
||||
}
|
||||
});
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
|
||||
test('Call to read all when there are cookies', function () {
|
||||
$.cookie('c', 'v');
|
||||
$.cookie('foo', 'bar');
|
||||
deepEqual($.cookie(), { c: 'v', foo: 'bar' }, 'returns object containing all cookies');
|
||||
});
|
||||
|
||||
test('Call to read all when there are no cookies at all', function () {
|
||||
deepEqual($.cookie(), {}, 'returns empty object');
|
||||
});
|
||||
|
||||
test('Call to read all with json: true', function () {
|
||||
$.cookie.json = true;
|
||||
$.cookie('c', { foo: 'bar' });
|
||||
deepEqual($.cookie(), { c: { foo: 'bar' } }, 'returns JSON parsed cookies');
|
||||
});
|
||||
|
||||
test('Call to read all with a badly encoded cookie', function () {
|
||||
expect(1);
|
||||
document.cookie = 'bad=foo%';
|
||||
document.cookie = 'good=foo';
|
||||
deepEqual($.cookie(), { good: 'foo' }, 'returns object containing all decodable cookies');
|
||||
// Delete manually here because it requires raw === true...
|
||||
$.cookie.raw = true;
|
||||
$.removeCookie('bad');
|
||||
});
|
||||
|
||||
|
||||
module('write', lifecycle);
|
||||
|
||||
test('String primitive', function () {
|
||||
expect(1);
|
||||
$.cookie('c', 'v');
|
||||
strictEqual($.cookie('c'), 'v', 'should write value');
|
||||
});
|
||||
|
||||
test('String object', function () {
|
||||
expect(1);
|
||||
$.cookie('c', new String('v'));
|
||||
strictEqual($.cookie('c'), 'v', 'should write value');
|
||||
});
|
||||
|
||||
test('value "[object Object]"', function () {
|
||||
expect(1);
|
||||
$.cookie('c', '[object Object]');
|
||||
strictEqual($.cookie('c'), '[object Object]', 'should write value');
|
||||
});
|
||||
|
||||
test('number', function () {
|
||||
expect(1);
|
||||
$.cookie('c', 1234);
|
||||
strictEqual($.cookie('c'), '1234', 'should write value');
|
||||
});
|
||||
|
||||
test('null', function () {
|
||||
expect(1);
|
||||
$.cookie('c', null);
|
||||
strictEqual($.cookie('c'), 'null', 'should write value');
|
||||
});
|
||||
|
||||
test('undefined', function () {
|
||||
expect(1);
|
||||
$.cookie('c', undefined);
|
||||
strictEqual($.cookie('c'), 'undefined', 'should write value');
|
||||
});
|
||||
|
||||
test('expires option as days from now', function () {
|
||||
expect(1);
|
||||
var sevenDaysFromNow = new Date();
|
||||
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 21);
|
||||
strictEqual($.cookie('c', 'v', { expires: 21 }), 'c=v; expires=' + sevenDaysFromNow.toUTCString(),
|
||||
'should write the cookie string with expires');
|
||||
});
|
||||
|
||||
test('expires option as fraction of a day', function () {
|
||||
expect(1);
|
||||
|
||||
var now = new Date().getTime();
|
||||
var expires = Date.parse($.cookie('c', 'v', { expires: 0.5 }).replace(/.+expires=/, ''));
|
||||
|
||||
// When we were using Date.setDate() fractions have been ignored
|
||||
// and expires resulted in the current date. Allow 1000 milliseconds
|
||||
// difference for execution time.
|
||||
ok(expires > now + 1000, 'should write expires attribute with the correct date');
|
||||
});
|
||||
|
||||
test('expires option as Date instance', function () {
|
||||
expect(1);
|
||||
var sevenDaysFromNow = new Date();
|
||||
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 7);
|
||||
strictEqual($.cookie('c', 'v', { expires: sevenDaysFromNow }), 'c=v; expires=' + sevenDaysFromNow.toUTCString(),
|
||||
'should write the cookie string with expires');
|
||||
});
|
||||
|
||||
test('return value', function () {
|
||||
expect(1);
|
||||
strictEqual($.cookie('c', 'v'), 'c=v', 'should return written cookie string');
|
||||
});
|
||||
|
||||
test('defaults', function () {
|
||||
expect(2);
|
||||
$.cookie.defaults.path = '/foo';
|
||||
ok($.cookie('c', 'v').match(/path=\/foo/), 'should use options from defaults');
|
||||
ok($.cookie('c', 'v', { path: '/bar' }).match(/path=\/bar/), 'options argument has precedence');
|
||||
});
|
||||
|
||||
test('raw = true', function () {
|
||||
expect(1);
|
||||
$.cookie.raw = true;
|
||||
strictEqual($.cookie('c[1]', 'v[1]'), 'c[1]=v[1]', 'should not encode');
|
||||
// Delete manually here because it requires raw === true...
|
||||
$.removeCookie('c[1]');
|
||||
});
|
||||
|
||||
test('json = true', function () {
|
||||
expect(1);
|
||||
$.cookie.json = true;
|
||||
|
||||
if ('JSON' in window) {
|
||||
$.cookie('c', { foo: 'bar' });
|
||||
strictEqual(document.cookie, 'c=' + encodeURIComponent(JSON.stringify({ foo: 'bar' })), 'should stringify JSON');
|
||||
} else {
|
||||
ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
module('removeCookie', lifecycle);
|
||||
|
||||
test('deletion', function () {
|
||||
expect(1);
|
||||
$.cookie('c', 'v');
|
||||
$.removeCookie('c');
|
||||
strictEqual(document.cookie, '', 'should delete the cookie');
|
||||
});
|
||||
|
||||
test('when sucessfully deleted', function () {
|
||||
expect(1);
|
||||
$.cookie('c', 'v');
|
||||
strictEqual($.removeCookie('c'), true, 'returns true');
|
||||
});
|
||||
|
||||
test('when cookie does not exist', function () {
|
||||
expect(1);
|
||||
strictEqual($.removeCookie('c'), true, 'returns true');
|
||||
});
|
||||
|
||||
test('when deletion failed', function () {
|
||||
expect(1);
|
||||
$.cookie('c', 'v');
|
||||
|
||||
var originalCookie = $.cookie;
|
||||
$.cookie = function () {
|
||||
// Stub deletion...
|
||||
if (arguments.length === 1) {
|
||||
return originalCookie.apply(null, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
strictEqual($.removeCookie('c'), false, 'returns false');
|
||||
|
||||
$.cookie = originalCookie;
|
||||
});
|
||||
|
||||
test('with options', function () {
|
||||
expect(1);
|
||||
var options = { path: '/' };
|
||||
$.cookie('c', 'v', options);
|
||||
$.removeCookie('c', options);
|
||||
strictEqual(document.cookie, '', 'should delete the cookie');
|
||||
});
|
||||
|
||||
test('passing options reference', function () {
|
||||
expect(1);
|
||||
var options = { path: '/' };
|
||||
$.cookie('c', 'v', options);
|
||||
$.removeCookie('c', options);
|
||||
deepEqual(options, { path: '/' }, "won't alter options object");
|
||||
});
|
||||
|
||||
test('[] used in name', function () {
|
||||
expect(1);
|
||||
$.cookie.raw = true;
|
||||
document.cookie = 'c[1]=foo';
|
||||
$.removeCookie('c[1]');
|
||||
strictEqual(document.cookie, '', 'delete the cookie');
|
||||
});
|
||||
|
||||
|
||||
module('conversion', lifecycle);
|
||||
|
||||
test('read converter', function() {
|
||||
expect(1);
|
||||
$.cookie('c', '1');
|
||||
strictEqual($.cookie('c', Number), 1, 'converts read value');
|
||||
});
|
||||
|
||||
test('read converter with raw = true', function() {
|
||||
expect(1);
|
||||
$.cookie.raw = true;
|
||||
$.cookie('c', '1');
|
||||
strictEqual($.cookie('c', Number), 1, 'does not decode, but converts read value');
|
||||
});
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,3 @@
|
|||
Javascript Mastodon API Client Library for Browser Clients
|
||||
|
||||
Check out index.html for a "how-to"
|
|
@ -0,0 +1,117 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="mastodon.js"></script>
|
||||
<script>
|
||||
// initialize library
|
||||
// api_user_token has not to be set at this point if you don't have one yet
|
||||
// NOTE: It needs jQuery!
|
||||
var api = new MastodonAPI({
|
||||
instance: "",
|
||||
api_user_token: ""
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
// BASIC REST FUNCTIONS
|
||||
// you can use every api endpoint from https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md
|
||||
//
|
||||
|
||||
api.post("statuses", {status:"i like pineapple on pizza"}, function (data) {
|
||||
// will be called if the toot was successful
|
||||
// data is the http response object
|
||||
|
||||
//sidenote: please do not actually execute this request, you could be bullied by your friends
|
||||
});
|
||||
|
||||
api.get("accounts/1/following", [
|
||||
["since_id", 420],
|
||||
["max_id", 1337]
|
||||
], function(data) {
|
||||
// returns all users account id 1 is following in the id range from 420 to 1337
|
||||
// you don't have to supply the parameters, you can also just go with .get(endpoint, callback)
|
||||
});
|
||||
|
||||
api.delete("statuses/1", function (data) {
|
||||
//deletes toot with id 1
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
// STREAMING
|
||||
//
|
||||
|
||||
|
||||
//lets initialize a stream! stream types are
|
||||
// user for your local home TL and notifications
|
||||
// public for your federated TL
|
||||
// public:local for your home TL
|
||||
// hashtag&tag=fuckdonaldtrump for the stream of #fuckdonaldtrump
|
||||
|
||||
api.stream("user", function(data) {
|
||||
// data is an object containing two entries
|
||||
// event determines which type of data you got
|
||||
// payload is the actual data
|
||||
// event can be notification or update
|
||||
if (data.event === "notification") {
|
||||
// data.payload is a notification
|
||||
} else if (data.event === "update") {
|
||||
// status update for one of your timelines
|
||||
} else {
|
||||
// probably an error
|
||||
}
|
||||
})
|
||||
|
||||
// AUTH
|
||||
|
||||
// first, we register our application
|
||||
// for this we need no key since we don't have one yet
|
||||
api.registerApplication("my cool application name",
|
||||
window.location.href, // redirect uri, we will need this later on
|
||||
["read", "write", "follow"], //scopes
|
||||
"http://mycoolwebsite.com", //website on the login screen
|
||||
function(data) {
|
||||
// we got our application
|
||||
// lets save it to our browser storage
|
||||
localStorage.setItem("mastodon_client_id", data["client_id"]);
|
||||
localStorage.setItem("mastodon_client_secret", data["client_secret"]);
|
||||
localStorage.setItem("mastodon_client_redirect_uri", data["redirect_uri"]);
|
||||
// now, that we have saved our application data, generate an oauth url and send
|
||||
// our user to it!
|
||||
window.location.href = api.generateAuthLink(data["client_id"],
|
||||
data["redirect_uri"],
|
||||
"code", // oauth method
|
||||
["read", "write", "follow"] //scopes
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
// now we get to the part why the redirect uri was set to our current location
|
||||
// we can just access to code from the url hash
|
||||
if (window.location.href.indexOf("?code=") !== -1) {
|
||||
// nice, we got our auth code!
|
||||
// lets put it into a variable
|
||||
var authCode = window.location.href.replace(window.location.origin + window.location.pathname + "?code=", "");
|
||||
// nice variable clusterfuck, eh?
|
||||
// we have everything needed to access our oauth token
|
||||
api.getAccessTokenFromAuthCode(
|
||||
localStorage.getItem("mastodon_client_id"),
|
||||
localStorage.getItem("mastodon_client_secret"),
|
||||
localStorage.getItem("mastodon_client_redirect_uri"),
|
||||
authCode,
|
||||
function(data) {
|
||||
// AAAND DATA CONTAINS OUR TOKEN!
|
||||
// use api.setConfig("api_user_token", tokenvar) to set it without having to reinit the entire
|
||||
// library.
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,277 @@
|
|||
// mastodon javascript lib
|
||||
// by @kirschn@pleasehug.me 2017
|
||||
// no fucking copyright
|
||||
// do whatever you want with it
|
||||
// but please don't hurt it (and keep this header)
|
||||
|
||||
var MastodonAPI = function(config) {
|
||||
var apiBase = config.instance + "/api/v1/";
|
||||
return {
|
||||
setConfig: function (key, value) {
|
||||
// modify initial config afterwards
|
||||
config[key] = value;
|
||||
},
|
||||
getConfig: function(key) {
|
||||
//get config key
|
||||
return config[key];
|
||||
},
|
||||
get: function (endpoint) {
|
||||
// for GET API calls
|
||||
// can be called with two or three parameters
|
||||
// endpoint, callback
|
||||
// or
|
||||
// endpoint, queryData, callback
|
||||
// where querydata is an object {["paramname1", "paramvalue1], ["paramname2","paramvalue2"]}
|
||||
|
||||
// variables
|
||||
var queryData, callback,
|
||||
queryStringAppend = "?";
|
||||
|
||||
// check with which arguments we're supplied
|
||||
if (typeof arguments[1] === "function") {
|
||||
queryData = {};
|
||||
callback = arguments[1];
|
||||
} else {
|
||||
queryData = arguments[1];
|
||||
callback = arguments[2];
|
||||
}
|
||||
// build queryData Object into a URL Query String
|
||||
for (var i in queryData) {
|
||||
if (queryData.hasOwnProperty(i)) {
|
||||
if (typeof queryData[i] === "string") {
|
||||
queryStringAppend += queryData[i] + "&";
|
||||
} else if (typeof queryData[i] === "object") {
|
||||
queryStringAppend += queryData[i].name + "="+ queryData[i].data + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
// ajax function
|
||||
$.ajax({
|
||||
url: apiBase + endpoint + queryStringAppend,
|
||||
type: "GET",
|
||||
headers: {"Authorization": "Bearer " + config.api_user_token},
|
||||
success: function(data, textStatus, xhr) {
|
||||
|
||||
//weeey it was successful
|
||||
console.log("Successful GET API request to " +apiBase+endpoint);
|
||||
responce_headers = xhr.getAllResponseHeaders();
|
||||
|
||||
//aaand start the callback
|
||||
//might have to check what "textStatus" actually is, jquery docs are a bit dodgy
|
||||
callback(data,textStatus);
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
putMessage(`[${xhr.status}] ${xhr.responseJSON['error']}`);
|
||||
if ( xhr.status === 401 ) {
|
||||
location.href = "/logout"
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getArray: function (endpoint) {
|
||||
// for GET API calls
|
||||
// can be called with two or three parameters
|
||||
// endpoint, callback
|
||||
// or
|
||||
// endpoint, queryData, callback
|
||||
// where querydata is an object {["paramname1", "paramvalue1], ["paramname2","paramvalue2"]}
|
||||
|
||||
// variables
|
||||
var queryData, callback,
|
||||
queryStringAppend = "?";
|
||||
|
||||
// check with which arguments we're supplied
|
||||
if (typeof arguments[1] === "function") {
|
||||
queryData = {};
|
||||
callback = arguments[1];
|
||||
} else {
|
||||
queryData = arguments[1];
|
||||
callback = arguments[2];
|
||||
}
|
||||
// build queryData Object into a URL Query String
|
||||
for (var i in queryData) {
|
||||
if (queryData.hasOwnProperty(i)) {
|
||||
if (typeof queryData[i] === "string") {
|
||||
queryStringAppend += queryData[i] + "&";
|
||||
} else if (typeof queryData[i] === "object") {
|
||||
for ( var j in queryData[i].data ){
|
||||
queryStringAppend += queryData[i].name + "[]="+ queryData[i].data[j] + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ajax function
|
||||
$.ajax({
|
||||
url: apiBase + endpoint + queryStringAppend,
|
||||
type: "GET",
|
||||
headers: {"Authorization": "Bearer " + config.api_user_token},
|
||||
success: function(data, textStatus, xhr) {
|
||||
|
||||
//weeey it was successful
|
||||
console.log("Successful GET API request to " +apiBase+endpoint);
|
||||
responce_headers = xhr.getAllResponseHeaders();
|
||||
|
||||
//aaand start the callback
|
||||
//might have to check what "textStatus" actually is, jquery docs are a bit dodgy
|
||||
callback(data,textStatus);
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
putMessage(`[${xhr.status}] ${xhr.responseJSON['error']}`);
|
||||
if ( xhr.status === 401 ) {
|
||||
location.href = "/logout"
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getOther: function (domainAndEndpoint) {
|
||||
|
||||
var queryData, callback,
|
||||
queryStringAppend = "?";
|
||||
|
||||
// check with which arguments we're supplied
|
||||
if (typeof arguments[1] === "function") {
|
||||
queryData = {};
|
||||
callback = arguments[1];
|
||||
} else {
|
||||
queryData = arguments[1];
|
||||
callback = arguments[2];
|
||||
}
|
||||
// build queryData Object into a URL Query String
|
||||
for (var i in queryData) {
|
||||
if (queryData.hasOwnProperty(i)) {
|
||||
if (typeof queryData[i] === "string") {
|
||||
queryStringAppend += queryData[i] + "&";
|
||||
} else if (typeof queryData[i] === "object") {
|
||||
queryStringAppend += queryData[i].name + "="+ queryData[i].data + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
// ajax function
|
||||
$.ajax({
|
||||
url: domainAndEndpoint + queryStringAppend,
|
||||
type: "GET",
|
||||
success: function(data, textStatus, xhr) {
|
||||
|
||||
//weeey it was successful
|
||||
console.log("Successful GET API request to " +domainAndEndpoint);
|
||||
responce_headers = xhr.getAllResponseHeaders();
|
||||
|
||||
//aaand start the callback
|
||||
//might have to check what "textStatus" actually is, jquery docs are a bit dodgy
|
||||
callback(data,textStatus);
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
putMessage(`[${xhr.status}] ${xhr.responseJSON['error']}`);
|
||||
if ( xhr.status === 401 ) {
|
||||
location.href = "/logout"
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
post: function (endpoint) {
|
||||
// for POST API calls
|
||||
var postData, callback;
|
||||
// check with which arguments we're supplied
|
||||
if (typeof arguments[1] === "function") {
|
||||
postData = {};
|
||||
callback = arguments[1];
|
||||
} else {
|
||||
postData = arguments[1];
|
||||
callback = arguments[2];
|
||||
}
|
||||
$.ajax({
|
||||
url: apiBase + endpoint,
|
||||
type: "POST",
|
||||
data: postData,
|
||||
headers: {"Authorization": "Bearer " + config.api_user_token},
|
||||
success: function(data, textStatus) {
|
||||
console.log("Successful POST API request to " +apiBase+endpoint);
|
||||
callback(data,textStatus)
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
putMessage(`[${xhr.status}] ${xhr.responseJSON['error']}`);
|
||||
if ( xhr.status === 401 ) {
|
||||
location.href = "/logout"
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
postMedia: function (endpoint) {
|
||||
|
||||
// for POST API calls
|
||||
var postData, callback;
|
||||
// check with which arguments we're supplied
|
||||
if (typeof arguments[1] === "function") {
|
||||
postData = {};
|
||||
callback = arguments[1];
|
||||
} else {
|
||||
postData = arguments[1];
|
||||
callback = arguments[2];
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: apiBase + endpoint,
|
||||
type: "POST",
|
||||
data: postData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
headers: {"Authorization": "Bearer " + config.api_user_token},
|
||||
success: function(data, textStatus) {
|
||||
console.log("Successful POST API request to " +apiBase+endpoint);
|
||||
callback(data,textStatus)
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
putMessage(`[${xhr.status}] ${xhr.responseJSON['error']}`);
|
||||
if ( xhr.status === 401 ) {
|
||||
location.href = "/logout"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
delete: function (endpoint, callback) {
|
||||
// for DELETE API calls.
|
||||
$.ajax({
|
||||
url: apiBase + endpoint,
|
||||
type: "DELETE",
|
||||
headers: {"Authorization": "Bearer " + config.api_user_token},
|
||||
success: function(data, textStatus) {
|
||||
console.log("Successful DELETE API request to " +apiBase+endpoint);
|
||||
callback(data,textStatus)
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
putMessage(`[${xhr.status}] ${xhr.responseJSON['error']}`);
|
||||
if ( xhr.status === 401 ) {
|
||||
location.href = "/logout"
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
stream: function (streamType, onData) {
|
||||
// Event Stream Support
|
||||
// websocket streaming is undocumented. i had to reverse engineer the fucking web client.
|
||||
// streamType is either
|
||||
// user for your local home TL and notifications
|
||||
// public for your federated TL
|
||||
// public:local for your home TL
|
||||
// hashtag&tag=fuckdonaldtrump for the stream of #fuckdonaldtrump
|
||||
// callback gets called whenever new data ist recieved
|
||||
// callback { event: (eventtype), payload: {mastodon object as described in the api docs} }
|
||||
// eventtype could be notification (=notification) or update (= new toot in TL)
|
||||
var es = new WebSocket("wss://" + apiBase.substr(8)
|
||||
+"streaming?access_token=" + config.api_user_token + "&stream=" + streamType);
|
||||
var listener = function (event) {
|
||||
console.log("Got Data from Stream " + streamType);
|
||||
event = JSON.parse(event.data);
|
||||
event.payload = JSON.parse(event.payload);
|
||||
onData(event);
|
||||
};
|
||||
es.onmessage = listener;
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// node.js
|
||||
if (typeof module !== 'undefined') { module.exports = MastodonAPI; };
|
|
@ -0,0 +1,223 @@
|
|||
/**
|
||||
* http://www.openjs.com/scripts/events/keyboard_shortcuts/
|
||||
* Version : 2.01.B
|
||||
* By Binny V A
|
||||
* License : BSD
|
||||
*/
|
||||
shortcut = {
|
||||
'all_shortcuts':{},//All the shortcuts are stored in this array
|
||||
'add': function(shortcut_combination,callback,opt) {
|
||||
//Provide a set of default options
|
||||
var default_options = {
|
||||
'type':'keydown',
|
||||
'propagate':false,
|
||||
'disable_in_input':false,
|
||||
'target':document,
|
||||
'keycode':false
|
||||
}
|
||||
if(!opt) opt = default_options;
|
||||
else {
|
||||
for(var dfo in default_options) {
|
||||
if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
|
||||
}
|
||||
}
|
||||
|
||||
var ele = opt.target;
|
||||
if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
|
||||
var ths = this;
|
||||
shortcut_combination = shortcut_combination.toLowerCase();
|
||||
|
||||
//The function to be called at keypress
|
||||
var func = function(e) {
|
||||
e = e || window.event;
|
||||
|
||||
if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
|
||||
var element;
|
||||
if(e.target) element=e.target;
|
||||
else if(e.srcElement) element=e.srcElement;
|
||||
if(element.nodeType==3) element=element.parentNode;
|
||||
|
||||
if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
|
||||
}
|
||||
|
||||
//Find Which key is pressed
|
||||
if (e.keyCode) code = e.keyCode;
|
||||
else if (e.which) code = e.which;
|
||||
var character = String.fromCharCode(code).toLowerCase();
|
||||
|
||||
if(code == 188) character=","; //If the user presses , when the type is onkeydown
|
||||
if(code == 190) character="."; //If the user presses , when the type is onkeydown
|
||||
|
||||
var keys = shortcut_combination.split("+");
|
||||
//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
|
||||
var kp = 0;
|
||||
|
||||
//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
|
||||
var shift_nums = {
|
||||
"`":"~",
|
||||
"1":"!",
|
||||
"2":"@",
|
||||
"3":"#",
|
||||
"4":"$",
|
||||
"5":"%",
|
||||
"6":"^",
|
||||
"7":"&",
|
||||
"8":"*",
|
||||
"9":"(",
|
||||
"0":")",
|
||||
"-":"_",
|
||||
"=":"+",
|
||||
";":":",
|
||||
"'":"\"",
|
||||
",":"<",
|
||||
".":">",
|
||||
"/":"?",
|
||||
"\\":"|"
|
||||
}
|
||||
//Special Keys - and their codes
|
||||
var special_keys = {
|
||||
'esc':27,
|
||||
'escape':27,
|
||||
'tab':9,
|
||||
'space':32,
|
||||
'return':13,
|
||||
'enter':13,
|
||||
'backspace':8,
|
||||
|
||||
'scrolllock':145,
|
||||
'scroll_lock':145,
|
||||
'scroll':145,
|
||||
'capslock':20,
|
||||
'caps_lock':20,
|
||||
'caps':20,
|
||||
'numlock':144,
|
||||
'num_lock':144,
|
||||
'num':144,
|
||||
|
||||
'pause':19,
|
||||
'break':19,
|
||||
|
||||
'insert':45,
|
||||
'home':36,
|
||||
'delete':46,
|
||||
'end':35,
|
||||
|
||||
'pageup':33,
|
||||
'page_up':33,
|
||||
'pu':33,
|
||||
|
||||
'pagedown':34,
|
||||
'page_down':34,
|
||||
'pd':34,
|
||||
|
||||
'left':37,
|
||||
'up':38,
|
||||
'right':39,
|
||||
'down':40,
|
||||
|
||||
'f1':112,
|
||||
'f2':113,
|
||||
'f3':114,
|
||||
'f4':115,
|
||||
'f5':116,
|
||||
'f6':117,
|
||||
'f7':118,
|
||||
'f8':119,
|
||||
'f9':120,
|
||||
'f10':121,
|
||||
'f11':122,
|
||||
'f12':123
|
||||
}
|
||||
|
||||
var modifiers = {
|
||||
shift: { wanted:false, pressed:false},
|
||||
ctrl : { wanted:false, pressed:false},
|
||||
alt : { wanted:false, pressed:false},
|
||||
meta : { wanted:false, pressed:false} //Meta is Mac specific
|
||||
};
|
||||
|
||||
if(e.ctrlKey) modifiers.ctrl.pressed = true;
|
||||
if(e.shiftKey) modifiers.shift.pressed = true;
|
||||
if(e.altKey) modifiers.alt.pressed = true;
|
||||
if(e.metaKey) modifiers.meta.pressed = true;
|
||||
|
||||
for(var i=0; k=keys[i],i<keys.length; i++) {
|
||||
//Modifiers
|
||||
if(k == 'ctrl' || k == 'control') {
|
||||
kp++;
|
||||
modifiers.ctrl.wanted = true;
|
||||
|
||||
} else if(k == 'shift') {
|
||||
kp++;
|
||||
modifiers.shift.wanted = true;
|
||||
} else if(k == 'alt') {
|
||||
kp++;
|
||||
modifiers.alt.wanted = true;
|
||||
} else if(k == 'meta') {
|
||||
kp++;
|
||||
modifiers.meta.wanted = true;
|
||||
} else if(k.length > 1) { //If it is a special key
|
||||
if(special_keys[k] == code) kp++;
|
||||
|
||||
} else if(opt['keycode']) {
|
||||
if(opt['keycode'] == code) kp++;
|
||||
|
||||
} else { //The special keys did not match
|
||||
if(character == k) kp++;
|
||||
else {
|
||||
if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
|
||||
character = shift_nums[character];
|
||||
if(character == k) kp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(kp == keys.length &&
|
||||
modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
|
||||
modifiers.shift.pressed == modifiers.shift.wanted &&
|
||||
modifiers.alt.pressed == modifiers.alt.wanted &&
|
||||
modifiers.meta.pressed == modifiers.meta.wanted) {
|
||||
callback(e);
|
||||
|
||||
if(!opt['propagate']) { //Stop the event
|
||||
//e.cancelBubble is supported by IE - this will kill the bubbling process.
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
|
||||
//e.stopPropagation works in Firefox.
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.all_shortcuts[shortcut_combination] = {
|
||||
'callback':func,
|
||||
'target':ele,
|
||||
'event': opt['type']
|
||||
};
|
||||
//Attach the function with the event
|
||||
if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
|
||||
else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
|
||||
else ele['on'+opt['type']] = func;
|
||||
},
|
||||
|
||||
//Remove the shortcut - just specify the shortcut and I will remove the binding
|
||||
'remove':function(shortcut_combination) {
|
||||
shortcut_combination = shortcut_combination.toLowerCase();
|
||||
var binding = this.all_shortcuts[shortcut_combination];
|
||||
delete(this.all_shortcuts[shortcut_combination])
|
||||
if(!binding) return;
|
||||
var type = binding['event'];
|
||||
var ele = binding['target'];
|
||||
var callback = binding['callback'];
|
||||
|
||||
if(ele.detachEvent) ele.detachEvent('on'+type, callback);
|
||||
else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
|
||||
else ele['on'+type] = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main" class="federated">
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_current_user.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_load_options.php'); ?>
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/create_status.php'); ?>
|
||||
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
setTimeline("timelines/public");
|
||||
$("#federated_nav").addClass('view');
|
||||
$('title').text('Halcyon / Federated');
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
<!-- FOOTER -->
|
||||
<footer id="footer">
|
||||
<!-- Be enjoying your Mastodon!-->
|
||||
</footer>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/overlay_message.php'); ?>
|
||||
|
||||
<div id="js-overlay_content_wrap">
|
||||
<div id="js-overlay_content">
|
||||
|
||||
<div class="temporary_object">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="parmanent_object">
|
||||
<?php include dirname(__FILE__).('/widgets/overlay_create_status.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/overlay_single_reply.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/overlay_copy_link.php'); ?>
|
||||
</div>
|
||||
|
||||
<button class="close_button"><i class="fa fa-times" aria-hidden="true"></i></button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
<?php if (isset($_GET['status'])): ?>
|
||||
|
||||
setOverlayStatus('<?php echo $_GET['status']; ?>');
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
setCurrentProfile();
|
||||
badges_update();
|
||||
$('.header_settings_link').attr('href','https://'+current_instance+'/settings/preferences');
|
||||
$('.footer_widget_about').attr('href','https://'+current_instance+'/about');
|
||||
$('.footer_widget_instance').attr('href','https://'+current_instance+'/about/more');
|
||||
$('.footer_widget_terms').attr('href','https://'+current_instance+'/terms');
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
const what_to_follow_0 = JSON.parse(localStorage.getItem("what_to_follow_0"));
|
||||
const what_to_follow_1 = JSON.parse(localStorage.getItem("what_to_follow_1"));
|
||||
const what_to_follow_2 = JSON.parse(localStorage.getItem("what_to_follow_2"));
|
||||
|
||||
$('.what_to_follow_0 > .icon_box img').attr('src', what_to_follow_0.avatar);
|
||||
$('.what_to_follow_0 .label_box > a').attr('href', getRelativeURL(what_to_follow_0.url, what_to_follow_0.id) );
|
||||
$('.what_to_follow_0 .label_box > a > h3 .dn').text(what_to_follow_0.display_name);
|
||||
$('.what_to_follow_0 .label_box > a > h3 .un').text('@'+what_to_follow_0.username);
|
||||
$('.what_to_follow_0 .label_box > .follow_button').attr('mid', what_to_follow_0.id);
|
||||
$('.what_to_follow_0 .label_box > .follow_button').attr('data', what_to_follow_0.url);
|
||||
|
||||
$('.what_to_follow_1 > .icon_box img').attr('src', what_to_follow_1.avatar);
|
||||
$('.what_to_follow_1 .label_box > a').attr('href', getRelativeURL(what_to_follow_1.url, what_to_follow_1.id) );
|
||||
$('.what_to_follow_1 .label_box > a > h3 .dn').text(what_to_follow_1.display_name);
|
||||
$('.what_to_follow_1 .label_box > a > h3 .un').text('@'+what_to_follow_1.username);
|
||||
$('.what_to_follow_1 .label_box > .follow_button').attr('mid', what_to_follow_1.id);
|
||||
$('.what_to_follow_0 .label_box > .follow_button').attr('data', what_to_follow_1.url);
|
||||
|
||||
$('.what_to_follow_2 > .icon_box img').attr('src', what_to_follow_2.avatar);
|
||||
$('.what_to_follow_2 .label_box > a').attr('href', getRelativeURL(what_to_follow_2.url, what_to_follow_2.id) );
|
||||
$('.what_to_follow_2 .label_box > a > h3 .dn').text(what_to_follow_2.display_name);
|
||||
$('.what_to_follow_2 .label_box > a > h3 .un').text('@'+what_to_follow_2.username);
|
||||
$('.what_to_follow_2 .label_box > .follow_button').attr('mid', what_to_follow_2.id);
|
||||
$('.what_to_follow_0 .label_box > .follow_button').attr('data', what_to_follow_2.url);
|
||||
|
||||
replace_emoji();
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,160 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Halcyon</title>
|
||||
|
||||
<link rel="shortcut icon" href="/assets/images/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/style.css" media="all" />
|
||||
<link rel="stylesheet" type="text/css" href="//cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" media="all" />
|
||||
|
||||
<script src="//yastatic.net/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="/assets/js/halcyon/halcyonFunctions.js"></script>
|
||||
<script src="/assets/js/mastodon.js/mastodon.js"></script><!-- thx @kirschn -->
|
||||
<script src="/assets/js/jquery-cookie/src/jquery.cookie.js"></script>
|
||||
<script src="/assets/js/shortcut.js"></script>
|
||||
<script src="/assets/js/replace_emoji.js"></script>
|
||||
<script src="/assets/js/halcyon/halcyonUI.js"></script>
|
||||
<script src="//cdn.staticfile.org/twemoji/2.2.5/twemoji.min.js"></script>
|
||||
|
||||
<script>
|
||||
if (
|
||||
!localStorage.getItem("current_id") |
|
||||
!localStorage.getItem("current_instance") |
|
||||
!localStorage.getItem("current_authtoken")
|
||||
){
|
||||
location.href = "/login";
|
||||
} else {
|
||||
if( $.cookie("session") === "true" ) {
|
||||
refreshApp();
|
||||
} else if ( $.cookie("session") === undefined ) {
|
||||
resetApp();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<header id="header">
|
||||
|
||||
<div class="header_nav_wrap">
|
||||
|
||||
<!-- HEADER LEFT -->
|
||||
<nav class="header_left_box">
|
||||
<ul class="header_nav_list">
|
||||
<!-- HOME -->
|
||||
<li id="header_nav_item_home" class="header_nav_item">
|
||||
<a href="/" id="home_nav">
|
||||
<i class="fa fa-fw fa-home"></i>
|
||||
<span>Home</span>
|
||||
</a>
|
||||
<div class="home_badge nav_badge invisible"></div>
|
||||
</li>
|
||||
<!-- LOCAL -->
|
||||
<li id="header_nav_item_local" class="header_nav_item local_nav">
|
||||
<a href="/local" id="local_nav">
|
||||
<i class="fa fa-fw fa-users"></i>
|
||||
<span>Local</span>
|
||||
</a>
|
||||
<div class="local_badge nav_badge invisible"></div>
|
||||
</li>
|
||||
<!-- FEDERATED -->
|
||||
<li id="header_nav_item_federated" class="header_nav_item federated_nav">
|
||||
<a href="/federated" id="federated_nav">
|
||||
<i class="fa fa-fw fa-globe"></i>
|
||||
<span>Federated</span>
|
||||
</a>
|
||||
<div class="federated_badge nav_badge invisible"></div>
|
||||
</li>
|
||||
<!-- NOTIFICATIONS -->
|
||||
<li id="header_nav_item_notifications" class="header_nav_item notifications_nav">
|
||||
<a href="/notifications" id="notifications_nav">
|
||||
<i class="fa fa-fw fa-bell"></i>
|
||||
<span>Notifications</span>
|
||||
</a>
|
||||
<div class="notification_badge nav_badge invisible"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- HEADER CENTER -->
|
||||
<div class="header_center_box">
|
||||
<h1 class="header_nav_item mastodon_logo logo_box">
|
||||
<a href="/">
|
||||
<img src="/assets/images/logo_halcyon.png" alt="Halcyon for Mastodon" />
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<!-- HEADER RIGHT -->
|
||||
<nav class="header_right_box">
|
||||
|
||||
<ul class="header_nav_list">
|
||||
|
||||
<!-- SEARCH -->
|
||||
<li class="header_nav_item serch_form_wrap">
|
||||
<form class="search_form" action="/search" method="GET">
|
||||
<input id="search_form" class="search_form_input" placeholder="Search Mastodon" type="text" name="q" accesskey="/"/>
|
||||
<span class="search_form_submit">
|
||||
<button type="submit">
|
||||
<i class="fa fa-fw fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
</form>
|
||||
</li>
|
||||
|
||||
<!-- ACCOUNT -->
|
||||
<li class="header_nav_item my_account_wrap">
|
||||
|
||||
<button class="header_account_avatar">
|
||||
<div class="my_account">
|
||||
<img class="js_current_profile_image" />
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<nav class="header_my_account_nav invisible">
|
||||
<ul>
|
||||
<li>
|
||||
<a class="js_current_profile_link emoji_poss">
|
||||
<span class="js_current_profile_displayname display_name"></span>
|
||||
<span>View profile</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a class="header_settings_link" href="">Settings</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/logout">Log out</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
<!-- TOOT -->
|
||||
<li class="header_nav_item toot_button_wrap">
|
||||
|
||||
<button id="creat_status" class="toot_button" accesskey="n">
|
||||
<div class="toot_button_label">
|
||||
<i class="fa fa-fw fa-pencil-square-o"></i>
|
||||
<span>Toot</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
</header>
|
|
@ -0,0 +1,62 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main" class="home">
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
<?php include dirname(__FILE__).('/widgets/side_current_user.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_load_options.php'); ?>
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
<?php include dirname(__FILE__).('/widgets/create_status.php'); ?>
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
setTimeline("timelines/home");
|
||||
$("#home_nav").addClass('view');
|
||||
$('title').text('Halcyon');
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1 @@
|
|||
<?php include ('home.php'); ?>
|
|
@ -0,0 +1,76 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_current_user.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_load_options.php'); ?>
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/create_status.php'); ?>
|
||||
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
if (
|
||||
localStorage.getItem("setting_local_instance") === "default" |
|
||||
localStorage.getItem("setting_local_instance") === current_instance
|
||||
) {
|
||||
setTimeline("timelines/public", [{name:"local",data:"ture"}]);
|
||||
} else {
|
||||
setOtherTimeline(localStorage.getItem("setting_local_instance")+"/api/v1/", [{name:"local",data:"ture"}]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$("#local_nav").addClass('view');
|
||||
$('title').text('Halcyon / Local');
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,571 @@
|
|||
@charset "utf-8";
|
||||
|
||||
/*--------------------------------------
|
||||
Reset
|
||||
--------------------------------------*/
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: top;
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: red!important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
.no-events {
|
||||
pointer-events: none!important;
|
||||
}
|
||||
|
||||
.no-underline,
|
||||
.no-underline:hover {
|
||||
text-decoration: none!important;
|
||||
}
|
||||
|
||||
.disallow_select {
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.text_ellipsis {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.khmer_font {
|
||||
font-family: "Khmer MN", Helvetica, Arial, sans-serif!important;
|
||||
}
|
||||
|
||||
.gill_font {
|
||||
font-family: "Gill Sans", Helvetica, Arial, sans-serif!important;
|
||||
}
|
||||
|
||||
.trebuchet_font {
|
||||
font-family: "Trebuchet MS", Helvetica, Arial, sans-serif!important;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
blockquote * {
|
||||
margin: 0;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content:'';
|
||||
content:none;
|
||||
}
|
||||
|
||||
article,aside,details,figcaption,figure,
|
||||
footer,header,hgroup,menu,nav,section {
|
||||
display:block;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
textarea,
|
||||
select{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
appearance: none;
|
||||
}
|
||||
input:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0px 1000px transparent inset;
|
||||
}
|
||||
|
||||
/* Twitter Emoji Prefix */
|
||||
img.emoji {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin: 0 .05em 0 .1em;
|
||||
vertical-align: -0.1em;
|
||||
}
|
||||
|
||||
/*--------------------------------------
|
||||
Base
|
||||
--------------------------------------*/
|
||||
|
||||
html {
|
||||
font-family : "Trebuchet MS",Helvetica,"ヒラギノ角ゴ Pro W3",
|
||||
"Hiragino Kaku Gothic Pro",Meiryo,"メイリオ","MS Pゴシック",Arial,sans-serif;
|
||||
font-size : 100%;
|
||||
line-height : 1;
|
||||
color: #333;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
word-wrap:break-word;
|
||||
background-color: #F5F8FA;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
HEADER AREA
|
||||
-------------------------------------*/
|
||||
|
||||
#header {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
color: #fff;
|
||||
background-color: #222;
|
||||
box-shadow: 0px 3px 5px rgba(0,0,0,0.26);
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
#header #header_wrap {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#header #header_wrap > .header_box {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
HEADER AREA: TITLE
|
||||
-------------------------------------*/
|
||||
|
||||
#header #header_wrap .header_box.header_right_box {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_right_box .title_box {
|
||||
height: 100%;
|
||||
margin-left: 24px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
HEADER AREA: NAV
|
||||
-------------------------------------*/
|
||||
|
||||
#header #header_wrap .header_box.header_left_box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box nav {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box .nav_box ul {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box .nav_box ul a {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box .nav_box ul li {
|
||||
display: block;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
height: calc(100% - 5px*2 );
|
||||
margin-top: 5px;
|
||||
border-bottom: 0px solid #007BD0;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box .nav_box ul li span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
padding: 15px 24px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box .nav_box ul li span i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#header #header_wrap .header_box.header_left_box .nav_box ul li:hover {
|
||||
color: #189EFC;
|
||||
border-bottom-width: 5px;
|
||||
transition: 0.15s ease-out;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
MAIN
|
||||
-------------------------------------*/
|
||||
|
||||
#main {
|
||||
padding-top: 56px;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
FORM
|
||||
-------------------------------------*/
|
||||
|
||||
#main #login_form_wrap {
|
||||
width: 100%;
|
||||
height: 560px;
|
||||
padding: 56px 0;
|
||||
margin-bottom: -200px;
|
||||
box-sizing: border-box;
|
||||
background-image: url("/login/assets/images/background.jpg");
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form {
|
||||
position: relative;
|
||||
width: 640px;
|
||||
height: 220px;
|
||||
padding: 36px 24px;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
background: inherit;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #C9EFF8;
|
||||
text-align: center;
|
||||
box-shadow: 0px 5px 5px rgba(0,0,0,0.26);
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form.expand {
|
||||
width: 780px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form::before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
background: inherit;
|
||||
background-position: top center;
|
||||
filter: blur(3px);
|
||||
border-radius: 5px;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form form {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
z-index: 1;
|
||||
color: #C9EFF8;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form form a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form h2 {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form.expand h2 {
|
||||
font-size: 42px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form p {
|
||||
margin-bottom: 16px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form.expand p {
|
||||
opacity: 0;
|
||||
margin-bottom: 0;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_main {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
height: 32px;
|
||||
width: 276px;
|
||||
border: 1px solid #C9EFF8;
|
||||
border-radius: 32px;
|
||||
background-color: rgba(0,0,0,.3);
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form.expand .login_form_main {
|
||||
width: 360px;
|
||||
height: 42px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_main.active {
|
||||
box-shadow: 0px 3px 5px rgba(0,0,0,0.26);
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_main input[name="acct"] {
|
||||
display: block;
|
||||
-webkit-appearance : none;
|
||||
flex-grow: 1;
|
||||
padding: 4px 0 4px 14px;
|
||||
color: #C9EFF8;
|
||||
border: none;
|
||||
background: none;
|
||||
box-sizing: border-box;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form.expand .login_form_main input[name="acct"] {
|
||||
flex-grow: 2;
|
||||
padding: 8px 0 8px 14px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_main .login_form_continue {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
color: #C9EFF8;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_main .login_form_continue:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_agree {
|
||||
margin: 16px auto 0;
|
||||
}
|
||||
|
||||
#main #login_form_wrap .login_form .login_form_agree i {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
ARTICLE
|
||||
-------------------------------------*/
|
||||
|
||||
#article {
|
||||
position: relative;
|
||||
width: 640px;
|
||||
margin: auto;
|
||||
margin-bottom: 56px;
|
||||
padding: 24px 36px 36px;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 3px 3px 5px rgba(0,0,0,0.26);
|
||||
}
|
||||
|
||||
#article h2 {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
#article p {
|
||||
display: inline-block;
|
||||
margin-bottom: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
#article .image_wrap {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin: 0 -36px 24px;
|
||||
border-top: 0.5px solid #555;
|
||||
border-bottom: 0.5px solid #555;
|
||||
}
|
||||
|
||||
#article .image_wrap ul {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 370px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#article .image_wrap ul li {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
@keyframes fadeout {
|
||||
0% {opacity: 1;}
|
||||
100% {opacity: 0;}
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
|
||||
#article .image_wrap ul li.fadeout {
|
||||
animation-name: fadeout;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
#article .image_wrap ul li.fadein {
|
||||
animation-name: fadein;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
#article .image_wrap .switch_button {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
transition: 0.15s ease-out;
|
||||
}
|
||||
|
||||
#article .image_wrap:hover .switch_button {
|
||||
opacity: 1;
|
||||
transition: 0.15s ease-out;
|
||||
}
|
||||
|
||||
@keyframes switching_image_list {
|
||||
0% {background-color: rgba(0, 0, 0, .3);}
|
||||
50% {background-color: rgba(0, 0, 0, .8);}
|
||||
100% {background-color: rgba(0, 0, 0, .3);}
|
||||
}
|
||||
|
||||
#article .image_wrap:hover .switch_button.active {
|
||||
animation-name: switching_image_list;
|
||||
animation-duration: 0.35s;
|
||||
}
|
||||
|
||||
#article .image_wrap .switch_button.prev_button {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#article .image_wrap .switch_button.next_button {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
||||
#article a {
|
||||
color: #189EFC;
|
||||
}
|
||||
|
||||
/*-------------------------------------
|
||||
FOOTER
|
||||
-------------------------------------*/
|
||||
|
||||
#footer {
|
||||
width: 640px;
|
||||
padding: 24px 36px 12px;
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
box-shadow: 3px 3px 5px rgba(0,0,0,0.26);
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
#footer .footer_anchor {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #444;
|
||||
font-size: 36px;
|
||||
transition: 0.15s ease-out;
|
||||
}
|
||||
|
||||
#footer .footer_anchor:hover {
|
||||
color: #555;
|
||||
transition: 0.15s ease-out;
|
||||
}
|
||||
|
||||
#footer span {
|
||||
font-size: 14px;
|
||||
color: #ddd;
|
||||
margin: auto;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
After Width: | Height: | Size: 129 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 510 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 134 KiB |
|
@ -0,0 +1,55 @@
|
|||
$(function() {
|
||||
|
||||
$(document).on('change','.login_form_agree #agree', function(e) {
|
||||
const icon = $(this).parent().find('i.fa');
|
||||
if ( $(this).prop('checked') ) {
|
||||
icon.addClass("fa-check-square-o");
|
||||
icon.removeClass("fa-square-o");
|
||||
} else if ( !$(this).prop('checked') ) {
|
||||
icon.addClass("fa-square-o");
|
||||
icon.removeClass("fa-check-square-o");
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('focus', '#main #login_form_wrap .login_form .login_form_main input[name="acct"]', function(e) {
|
||||
$(this).parent().addClass('active')
|
||||
$(".login_form").addClass('expand');
|
||||
})
|
||||
|
||||
$(document).on('blur', '#main #login_form_wrap .login_form .login_form_main input[name="acct"]', function(e) {
|
||||
$(this).parent().removeClass('active')
|
||||
$(".login_form").removeClass('expand');
|
||||
})
|
||||
|
||||
$(document).on('mousedown', '.image_wrap .switch_button', function(e) {
|
||||
const self = $(this);
|
||||
self.addClass('active');
|
||||
setTimeout(function() {
|
||||
self.removeClass('active');
|
||||
}, 500);
|
||||
})
|
||||
|
||||
$(document).on('click', '.image_wrap .prev_button', function(e) {
|
||||
|
||||
const firstChild = $(this).parent(".image_wrap").find('ul li:first-child');
|
||||
firstChild.appendTo(".image_wrap ul");
|
||||
firstChild.addClass('fadein');
|
||||
setTimeout(function() {
|
||||
firstChild.removeClass('fadein');
|
||||
}, 500);
|
||||
|
||||
})
|
||||
|
||||
$(document).on('click', '.image_wrap .next_button', function(e) {
|
||||
|
||||
const lastChild = $(this).parent(".image_wrap").find('ul li:last-child');;
|
||||
lastChild.addClass('fadeout');
|
||||
setTimeout(function() {
|
||||
lastChild.prependTo(".image_wrap ul");
|
||||
lastChild.removeClass('fadeout');
|
||||
}, 500);
|
||||
|
||||
})
|
||||
|
||||
|
||||
})
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
|
||||
<script>
|
||||
if(
|
||||
localStorage.getItem('current_id') |
|
||||
localStorage.getItem('current_instance') |
|
||||
localStorage.getItem('current_authtoken')
|
||||
){
|
||||
location.href = '/logout';
|
||||
};
|
||||
</script>
|
||||
|
||||
<?php
|
||||
#!/usr/bin/env php
|
||||
#ini_set("display_errors", On);
|
||||
#error_reporting(E_ALL);
|
||||
require_once('../../authorize/Mastodon.php');
|
||||
use HalcyonSuite\HalcyonForMastodon\Mastodon;
|
||||
use Exception;
|
||||
|
||||
$api = new Mastodon();
|
||||
|
||||
if ($_GET['code']) {
|
||||
|
||||
$domain = htmlspecialchars((string)filter_input(INPUT_GET, 'host'), ENT_QUOTES);
|
||||
$URL = 'https://'.$domain;
|
||||
|
||||
$api->selectInstance($URL);
|
||||
$response = $api->get_access_token($api->clientWebsite.'/auth?&host='.$domain, htmlspecialchars((string)filter_input(INPUT_GET, 'code'), ENT_QUOTES));
|
||||
|
||||
if ($response['html']["access_token"]) {
|
||||
|
||||
$access_token = $response['html']["access_token"];
|
||||
$account_id = $api->accounts_verify_credentials()['html']['id'];
|
||||
|
||||
echo "
|
||||
<script>
|
||||
|
||||
localStorage.setItem('current_id', '$account_id');
|
||||
localStorage.setItem('current_instance', '$domain');
|
||||
localStorage.setItem('current_authtoken', '$access_token');
|
||||
|
||||
localStorage.setItem('setting_post_stream', 'manual');
|
||||
localStorage.setItem('setting_post_privacy', 'public');
|
||||
localStorage.setItem('setting_local_instance', 'default');
|
||||
localStorage.setItem('setting_search_filter', 'all');
|
||||
|
||||
localStorage.setItem('what_to_follow_0', JSON.stringify({id:'',username:'Halcyon',display_name:'Halcyon for Mastodon',url:'https://mastodon.social/@Halcyon',avatar:'https://files.mastodon.social/accounts/avatars/000/132/199/original/1ca33302b092376b.png'}));
|
||||
localStorage.setItem('what_to_follow_1', JSON.stringify({id:'',username:'Gargron',display_name:'Eugen',url:'https://mastodon.social/@Gargron',avatar:'https://files.mastodon.social/accounts/avatars/000/000/001/original/J3IHut1v.png'}));
|
||||
localStorage.setItem('what_to_follow_2', JSON.stringify({id:'',username:'Mastodon',display_name:'Mastodon',url:'https://mastodon.social/@Mastodon',avatar:'https://files.mastodon.social/accounts/avatars/000/013/179/original/logo-41b041930be24e8039129c8ac4ff4840ef467f40c3f2d5044db50a4b15ceb285.png'}));
|
||||
|
||||
location.href = '/';
|
||||
|
||||
</script>
|
||||
";
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<script src="//yastatic.net/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="/assets/js/mastodon.js/mastodon.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,234 @@
|
|||
<?php
|
||||
#!/usr/bin/env php
|
||||
#ini_set("display_errors", On);
|
||||
#error_reporting(E_ALL);
|
||||
require_once('../../authorize/Mastodon.php');
|
||||
use HalcyonSuite\HalcyonForMastodon\Mastodon;
|
||||
use Exception;
|
||||
?>
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Halcyon for Mastodon</title>
|
||||
<link rel="shortcut icon" href="/assets/images/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="/login/assets/css/style.css" media="all" />
|
||||
<link rel="stylesheet" type="text/css" href="//cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" media="all" />
|
||||
<script src="//yastatic.net/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="/assets/js/jquery-cookie/src/jquery.cookie.js"></script>
|
||||
<script src="/login/assets/js/halcyon_login.js"></script>
|
||||
|
||||
<script>
|
||||
if(
|
||||
localStorage.getItem("current_id") |
|
||||
localStorage.getItem("current_instance") |
|
||||
localStorage.getItem("current_authtoken")
|
||||
){
|
||||
location.href = "/";
|
||||
};
|
||||
</script>
|
||||
|
||||
<?php
|
||||
if (isset($_POST['acct'])) {
|
||||
$domain = explode("@", mb_strtolower(htmlspecialchars((string)filter_input(INPUT_POST, 'acct'), ENT_QUOTES)))[2];
|
||||
$URL = 'https://'.$domain;
|
||||
$api = new Mastodon();
|
||||
if ( !preg_match('/(^[a-z0-9\-\.\/]+?\.[a-z0-9-]+$)/', $domain) ) {
|
||||
header('Location: '.$api->clientWebsite.'/login?cause=domain', true, 303);
|
||||
die();
|
||||
} else {
|
||||
try {
|
||||
$client_id = $api->getInstance($URL)["client_id"];
|
||||
$authorizeURL = $URL.'/oauth/authorize?client_id='.$client_id.'&response_type=code&scope=read+write+follow&website='.$api->clientWebsite.'&redirect_uri='.urlencode($api->clientWebsite.'/auth?&host='.$domain);
|
||||
header("Location: {$authorizeURL}", true, 303);
|
||||
die();
|
||||
} catch (Exception $e) {
|
||||
header('Location: '.$api->clientWebsite.'/login?cause=domain', true, 303);
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<header id="header">
|
||||
|
||||
<div id="header_wrap">
|
||||
|
||||
<div id="header_title_wrap" class="header_box header_right_box">
|
||||
|
||||
<div class="header_box_child title_box">
|
||||
<a href="/">
|
||||
<!-- TITLE IMAGE -->
|
||||
<img src="/login/assets/images/halcyon-title.png" alt="Halcyon for mastodon"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="header_menu_wrap" class="header_box header_left_box">
|
||||
|
||||
<nav class="header_box_child nav_box">
|
||||
<ul>
|
||||
|
||||
<!-- NEWS-->
|
||||
<!--<a href="https://mastodon.social/@halcyon" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-newspaper-o" aria-hidden="true"></i>News</span>
|
||||
</li>
|
||||
</a>-->
|
||||
|
||||
<!-- SOURCE-->
|
||||
<a href="https://github.com/halcyon-suite/halcyon" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-code" aria-hidden="true"></i>Source</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<!-- TERMS -->
|
||||
<a class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-balance-scale" aria-hidden="true"></i>Terms</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<!-- CONTACT -->
|
||||
<a href="http://www.nikisoft.one/contact.php" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-envelope" aria-hidden="true"></i>Contact</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<!-- SIGN IN -->
|
||||
<a href="#login_form_wrap" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-user-circle-o" aria-hidden="true"></i>Login</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<div id="login_form_wrap">
|
||||
|
||||
<div class="login_form">
|
||||
|
||||
<form method="POST" >
|
||||
|
||||
<h2>Login to Halcyon</h2>
|
||||
<p>
|
||||
or <a href="https://joinmastodon.org/">create an account</a>
|
||||
</p>
|
||||
|
||||
<div class="session_aleart">
|
||||
<span></span>
|
||||
</div>
|
||||
|
||||
<div class="login_form_main">
|
||||
<input name="acct" type="text" class="login_form_input" placeholder="@halcyon@mastodon.social" required/>
|
||||
<label class="login_form_continue pointer">
|
||||
<i class="fa fa-chevron-circle-right" aria-hidden="true"></i>
|
||||
<input id="login_continue" type="submit" value="" class="invisible"></input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="login_form_agree">
|
||||
<label class="login_form_agree_check disallow_select pointer">
|
||||
<i class="fa fa-check-square-o" aria-hidden="true"></i>
|
||||
I agree with the <a href="/terms">Terms</a>
|
||||
<input id="agree" type="checkbox" required checked class="invisible"/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<article id="article">
|
||||
|
||||
<h2>What is Halcyon</h2>
|
||||
|
||||
<p>
|
||||
Halcyon is standard <span style="font-weight: bold">Twitter like client</span> of Mastodon, And you can use it just by login to your instance. Let's Toot like a tweet.
|
||||
</p>
|
||||
|
||||
<div class="image_wrap">
|
||||
|
||||
<ul>
|
||||
<li><img src="/login/assets/images/preview2.png" alt="halcyon_screenshot"/></li>
|
||||
<li><img src="/login/assets/images/preview1.png" alt="halcyon_screenshot"/></li>
|
||||
<li><img src="/login/assets/images/preview0.png" alt="halcyon_screenshot"/></li>
|
||||
</ul>
|
||||
|
||||
<button class="prev_button switch_button"><i class="fa fa-angle-left" aria-hidden="true"></i></button>
|
||||
<button class="next_button switch_button"><i class="fa fa-angle-right" aria-hidden="true"></i></button>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Contact / Feedback</h2>
|
||||
|
||||
<p>
|
||||
Mastodon: <a href="http://social.wiuwiu.de/@nipos" target="_blank">@nipos@social.wiuwiu.de</a><br />
|
||||
Email: <a href="http://www.nikisoft.one/contact.php" target="_blank">Use my contact form</a><br />
|
||||
Github: <a href="https://github.com/halcyon-suite" target="_blank">/halcyon-suite</a>
|
||||
</p>
|
||||
|
||||
<h2>Help us</h2>
|
||||
|
||||
<p>
|
||||
Bitcoin: 1D6GThQqHQYnruKYrKyW9JC86ZGWxjt1hK<br />
|
||||
</p>
|
||||
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<footer id="footer">
|
||||
<div class="footer_anchor">
|
||||
<a href="#">
|
||||
<i class="fa fa-angle-up" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
<span>Photo by <a href="https://www.flickr.com/photos/95387826@N08/">Michio Morimoto on Flickr</a> (CC BY 2.0)</span>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
<?php if (isset($_GET['cause'])): ?>
|
||||
<script>
|
||||
|
||||
$(function() {
|
||||
var cause = "<?= htmlspecialchars((string)filter_input(INPUT_GET, 'cause'), ENT_QUOTES) ?>";
|
||||
if ( cause === "domain" ) {
|
||||
$('.login_form_main').addClass('error');
|
||||
$('.session_aleart').removeClass('invisible');
|
||||
$('.session_aleart > span').text('This instance does not exsist.');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click','.login_form_main', function(e) {
|
||||
$(this).removeClass('error');
|
||||
});
|
||||
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
<script src="//yastatic.net/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="/assets/js/jquery-cookie/src/jquery.cookie.js"></script>
|
||||
<script>localStorage.clear();$.removeCookie('session');location.href="/login";</script>
|
|
@ -0,0 +1,128 @@
|
|||
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Halcyon for Mastodon</title>
|
||||
<link rel="shortcut icon" href="/assets/images/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="/login/assets/css/style.css" media="all" />
|
||||
<link rel="stylesheet" type="text/css" href="//cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" media="all" />
|
||||
<script src="//yastatic.net/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="/assets/js/jquery-cookie/src/jquery.cookie.js"></script>
|
||||
<script src="/login/assets/js/halcyon_login.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<header id="header">
|
||||
|
||||
<div id="header_wrap">
|
||||
|
||||
<div id="header_title_wrap" class="header_box header_right_box">
|
||||
|
||||
<div class="header_box_child title_box">
|
||||
<a href="/">
|
||||
<!-- TITLE IMAGE -->
|
||||
<img src="/login/assets/images/halcyon-title.png" alt="Halcyon for mastodon"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="header_menu_wrap" class="header_box header_left_box">
|
||||
|
||||
<nav class="header_box_child nav_box">
|
||||
<ul>
|
||||
|
||||
<!-- NEWS-->
|
||||
<!--<a href="https://mastodon.social/@halcyon" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-newspaper-o" aria-hidden="true"></i>News</span>
|
||||
</li>
|
||||
</a>-->
|
||||
|
||||
<!-- SOURCE-->
|
||||
<a href="https://github.com/halcyon-suite/halcyon" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-code" aria-hidden="true"></i>Source</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<!-- TERMS -->
|
||||
<a class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-balance-scale" aria-hidden="true"></i>Terms</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<!-- CONTACT -->
|
||||
<a href="http://www.nikisoft.one/contact.php" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-envelope" aria-hidden="true"></i>Contact</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
<!-- SIGN IN -->
|
||||
<a href="#login_form_wrap" class="no-underline">
|
||||
<li>
|
||||
<span><i class="fa fa-user-circle-o" aria-hidden="true"></i>Login</span>
|
||||
</li>
|
||||
</a>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
<article id="article">
|
||||
<h1>Halcyon Terms of Use</h1>
|
||||
<p class="description">This terms of use agreement is for the users of web service Halcyon for Mastodon (Halcyon for short) hosted at <a href="https://halcyon.social">halcyon.social</a>.</p>
|
||||
<br/>
|
||||
<h2>1. Agreement</h2>
|
||||
<p>By logging into Halcyon you agree to this terms of use agreement. Do not use this service if you do not agree to these terms.</p>
|
||||
<br/>
|
||||
<h2>2. Change</h2>
|
||||
<p>We reserve the right to modify these terms of use at any time if deemed necessary.</p>
|
||||
<br/>
|
||||
<h2>3. Account</h2>
|
||||
<p>Users can connect to various Mastodon accounts from Halcyon, and Halcyon will not interfere with those connection.</p>
|
||||
<br/>
|
||||
<h2>4. Content</h2>
|
||||
<p>Halcyon does not own the right to or hold responsibility for any text, image, animation, audio content accessible from Halcyon. The right and responsibility belong to the owners of instances that host those content.</p>
|
||||
<br/>
|
||||
<h2>5. Guideline</h2>
|
||||
<p>Halcyon reserves the right to terminate service for</p>
|
||||
<ul>
|
||||
<li>actions violating the laws of countries</li>
|
||||
<li>actions contrary to public order and standards of decency</li>
|
||||
<li>violation of third party’s right to intellectual property, brand, privacy, etc.</li>
|
||||
<li>acts of violence, sexual nature, of discrimination</li>
|
||||
<li>phishing or spamming</li>
|
||||
<li>actions causing problem to the network infrastructure of Halcyon</li>
|
||||
</ul>
|
||||
<br/>
|
||||
<h2>6. Disclaimer</h2>
|
||||
<p>Halcyon is not responsible for any damage caused by using this service.</p>
|
||||
<br/>
|
||||
<p>Last updated 2017/5/12</p>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
<footer id="footer">
|
||||
<div class="footer_anchor">
|
||||
<a href="#">
|
||||
<i class="fa fa-angle-up" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
<span>Photo by <a href="https://www.flickr.com/photos/95387826@N08/">Michio Morimoto on Flickr</a> (CC BY 2.0)</span>
|
||||
</footer>
|
||||
|
||||
</body>
|
|
@ -0,0 +1,69 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
<ul class="header_items">
|
||||
|
||||
<li class="item toots view">
|
||||
<a href="#">
|
||||
All
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new notiotification
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_what_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
$("#notifications_nav").addClass('view');
|
||||
|
||||
// reset count
|
||||
localStorage.setItem("notification_count", 0);
|
||||
|
||||
setNotifications();
|
||||
$('title').text('Halcyon / Notifications')
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,80 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/search_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_load_options.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
<ul class="header_items">
|
||||
|
||||
<li class="item toots view">
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column"></aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
<?php if (isset($_GET['q'])): ?>
|
||||
|
||||
$(function() {
|
||||
// find by mid
|
||||
const query = "<?= htmlspecialchars((string)filter_input(INPUT_GET, 'q'), ENT_QUOTES) ?>";
|
||||
$('#main > .article_wrap > .center_column > .timeline_header > .header_items > .item').text("#"+query);
|
||||
$('#js-search_title_box > h1').text(query);
|
||||
$('title').text('#'+query+' - Halcyon Search');
|
||||
$('#js-search_nav_toots').toggleClass('view');
|
||||
$('#js-search_nav_toots a ').attr('href','/search'+location.search);
|
||||
$('#js-search_nav_peoples a ').attr('href','/search/users'+location.search)
|
||||
|
||||
if ( localStorage.getItem("setting_search_filter") === "all" ) {
|
||||
setTimeline("timelines/tag/"+query);
|
||||
} else if ( localStorage.getItem("setting_search_filter") === "local" ) {
|
||||
setTimeline("timelines/tag/"+query, [{name:"local",data:"ture"}]);
|
||||
}
|
||||
|
||||
replace_emoji();
|
||||
|
||||
});
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,51 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/search_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<div id="js-follows_profile">
|
||||
|
||||
</div>
|
||||
|
||||
<footer id="js-follows_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
<?php if(isset($_GET['q'])): ?>
|
||||
const query = "<?= htmlspecialchars((string)filter_input(INPUT_GET, 'q'), ENT_QUOTES) ?>";
|
||||
$('title').text(query+' - Halcyon Search');
|
||||
$('#js-search_title_box > h1').text(query);
|
||||
$('#js-search_nav_peoples').toggleClass('view');
|
||||
$('#js-search_nav_toots a ').attr('href','/search'+location.search);
|
||||
$('#js-search_nav_peoples a ').attr('href','/search/users'+location.search);
|
||||
setUserSearch(query);
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,158 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<!-- Profile avatar -->
|
||||
<div class="profile_icon_box">
|
||||
<img id="js_profile_image" src="/assets/images/missing.png" mediaaccess="true"/>
|
||||
</div>
|
||||
|
||||
<!-- Display/username, bio-->
|
||||
<section class="profile_section_wrap">
|
||||
<h1 class="profile_displayname">
|
||||
<a id="js_profile_displayname" class="emoji_poss" href="#"></a>
|
||||
</h1>
|
||||
<h2 class="profile_username">
|
||||
@<a id="js_profile_username" href="#"></a><span class="profile_followed_by invisible">FOLLOWS YOU</span>
|
||||
</h2>
|
||||
<p id="js_profile_bio" class="profile_bio emoji_poss"></p>
|
||||
<?php include dirname(__FILE__).('/widgets/user_recent_images.php'); ?>
|
||||
</section>
|
||||
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<!-- TIMELINE HEADER -->
|
||||
<header class="timeline_header">
|
||||
<ul class="header_items">
|
||||
<!-- TOOT -->
|
||||
<li class="item toots view">
|
||||
<a id="toots_link">
|
||||
Toots
|
||||
</a>
|
||||
</li>
|
||||
<!--- TOOTS & REPLIES -->
|
||||
<li class="item wreplies">
|
||||
<a id="with_replies_link">
|
||||
Toots & replies
|
||||
</a>
|
||||
</li>
|
||||
<!-- MEDIA -->
|
||||
<li class="item media">
|
||||
<a id="media_link">
|
||||
Media
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<!-- UPDATE BUTTON -->
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- TIMELINE -->
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<!-- TIMELINE FOOTER -->
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
<!-- FOOTER -->
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</aside>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = "/user";
|
||||
|
||||
$("#toots_link").attr('href', location.pathname+location.search);
|
||||
$("#with_replies_link").attr('href', location.pathname+'/with_replies'+location.search);
|
||||
$("#media_link").attr('href', location.pathname+'/media'+location.search);
|
||||
$("#js-profile_nav_toots").toggleClass("view");
|
||||
$("#js-profile_nav_toots > a").attr('href', location.pathname+location.search);
|
||||
$("#js-profile_nav_following > a").attr('href', location.pathname+'/following'+location.search);
|
||||
$("#js-profile_nav_followers > a").attr('href', location.pathname+'/followers'+location.search);
|
||||
$("#js-profile_nav_favourites > a").attr('href', location.pathname+'/favourites'+location.search);
|
||||
|
||||
<?php if (isset($_GET['mid'])): ?>
|
||||
|
||||
$(function() {
|
||||
|
||||
// find by mid
|
||||
const account_id = <?= htmlspecialchars((string)filter_input(INPUT_GET, 'mid'), ENT_QUOTES) ?>;
|
||||
|
||||
api.get('accounts/'+account_id, function(userprofile) {
|
||||
|
||||
if ( userprofile !== null ) {
|
||||
$('title').text(replaced_emoji_return(userprofile.display_name)+' (@'+userprofile.acct+') | Halcyon');
|
||||
setAccount(userprofile);
|
||||
setTimeline("accounts/"+userprofile.id+"/statuses",[{name:'exclude_replies',data:'true'}]);
|
||||
setRecentImages(userprofile.id)
|
||||
} else {
|
||||
location.href = "/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
<?php elseif((isset($_GET['user']))): ?>
|
||||
|
||||
$(function(){
|
||||
|
||||
// find by url
|
||||
<?php
|
||||
$name = preg_split("/@/", $_GET['user'])[1];
|
||||
$domain = preg_split("/@/", $_GET['user'])[2];
|
||||
$url = "https://$domain/@$name";
|
||||
?>
|
||||
|
||||
const query = '<?= htmlspecialchars((string)filter_input(INPUT_GET, 'user'), ENT_QUOTES) ?>';
|
||||
api.get('search', [{name:'q',data:query},{name:'resolve',data:'true'}], function(search) {
|
||||
|
||||
if ( !search.accounts.length ) {
|
||||
location.href = "/404.php";
|
||||
} else if ( "@"+search.accounts[0].acct === query ) {
|
||||
$('title').text(replaced_emoji_return(search.accounts[0].display_name)+' (@'+search.accounts[0].acct+') | Halcyon');
|
||||
setAccount(search.accounts[0]);
|
||||
setTimeline("accounts/"+search.accounts[0].id+"/statuses",[{name:'exclude_replies',data:'true'}]);
|
||||
setRecentImages(search.accounts[0].id)
|
||||
} else {
|
||||
location.href = "/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,147 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<div class="profile_icon_box">
|
||||
<img id="js_profile_image" src="/assets/images/missing.png" mediaaccess="true"/>
|
||||
</div>
|
||||
|
||||
<section class="profile_section_wrap">
|
||||
|
||||
<h1 class="profile_displayname">
|
||||
<a id="js_profile_displayname" class="emoji_poss" href="#"></a>
|
||||
</h1>
|
||||
|
||||
<h2 class="profile_username">
|
||||
@<a id="js_profile_username" href="#"></a>
|
||||
</h2>
|
||||
|
||||
<p id="js_profile_bio" class="profile_bio emoji_poss"></p>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_recent_images.php'); ?>
|
||||
|
||||
</section>
|
||||
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
<ul class="header_items">
|
||||
|
||||
<li class="item toots view">
|
||||
<a id="toots_link">
|
||||
Favourites
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
$("#js-profile_nav_favourites").toggleClass("view");
|
||||
$("#js-profile_nav_toots > a").attr('href', './'+location.search);
|
||||
$("#js-profile_nav_following > a").attr('href', 'following'+location.search);
|
||||
$("#js-profile_nav_followers > a").attr('href', 'followers'+location.search);
|
||||
$("#js-profile_nav_favourites > a").attr('href', 'favourites'+location.search);
|
||||
|
||||
<?php if (isset($_GET['mid'])): ?>
|
||||
|
||||
$(function() {
|
||||
|
||||
// find by mid
|
||||
const account_id = <?php echo $_GET['mid']; ?>;
|
||||
|
||||
api.get('accounts/'+account_id, function(AccountObj) {
|
||||
|
||||
if ( AccountObj !== null ) {
|
||||
setAccount(AccountObj);
|
||||
setTimeline("favourites");
|
||||
setRecentImages(AccountObj.id);
|
||||
} else {
|
||||
location.href = "/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
<?php elseif((isset($_GET['user']))): ?>
|
||||
|
||||
$(function(){
|
||||
|
||||
// find by url
|
||||
<?php
|
||||
$name = preg_split("/@/", $_GET['user'])[1];
|
||||
$domain = preg_split("/@/", $_GET['user'])[2];
|
||||
$url = "https://$domain/@$name";
|
||||
?>
|
||||
|
||||
const query = '<?= htmlspecialchars((string)filter_input(INPUT_GET, 'user'), ENT_QUOTES) ?>';
|
||||
|
||||
api.get('search', [{name:'q',data:query},{name:'resolve',data:'true'}], function(search) {
|
||||
|
||||
if ( !search.accounts.length ) {
|
||||
location.href="/404.php";
|
||||
} else if ( "@"+search.accounts[0].acct === query ) {
|
||||
setAccount(search.accounts[0]);
|
||||
setTimeline("favourites");
|
||||
setRecentImages(search.accounts[0]);
|
||||
} else {
|
||||
location.href="/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,115 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<div class="profile_icon_box">
|
||||
<img id="js_profile_image" src="/assets/images/missing.png" mediaaccess="true"/>
|
||||
</div>
|
||||
|
||||
<section class="profile_section_wrap">
|
||||
|
||||
<h1 class="profile_displayname">
|
||||
<a id="js_profile_displayname" class="emoji_poss" href="#"></a>
|
||||
</h1>
|
||||
|
||||
<h2 class="profile_username">
|
||||
@<a id="js_profile_username" href="#"></a>
|
||||
</h2>
|
||||
|
||||
<p id="js_profile_bio" class="profile_bio emoji_poss"></p>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_recent_images.php'); ?>
|
||||
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<div id="js-follows_profile">
|
||||
|
||||
</div>
|
||||
|
||||
<footer id="js-follows_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
$("#js-profile_nav_followers").toggleClass("view");
|
||||
$("#js-profile_nav_toots > a").attr('href', './'+location.search);
|
||||
$("#js-profile_nav_following > a").attr('href', 'following'+location.search);
|
||||
$("#js-profile_nav_followers > a").attr('href', 'followers'+location.search);
|
||||
$("#js-profile_nav_favourites > a").attr('href','favourites'+location.search);
|
||||
|
||||
<?php if (isset($_GET['mid'])): ?>
|
||||
|
||||
$(function() {
|
||||
|
||||
// find by mid
|
||||
const account_id = <?= htmlspecialchars((string)filter_input(INPUT_GET, 'mid'), ENT_QUOTES) ?>;
|
||||
|
||||
api.get('accounts/'+account_id, function(AccountObj) {
|
||||
|
||||
if ( AccountObj !== null ) {
|
||||
setAccount(AccountObj);
|
||||
setFollows(account_id,'followers',[{name:'limit',data:18}]);
|
||||
setRecentImages(AccountObj.id);
|
||||
} else {
|
||||
location.href="/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
<?php elseif((isset($_GET['user']))): ?>
|
||||
|
||||
$(function(){
|
||||
|
||||
// find by url
|
||||
<?php
|
||||
$name = preg_split("/@/", $_GET['user'])[1];
|
||||
$domain = preg_split("/@/", $_GET['user'])[2];
|
||||
$url = "https://$domain/@$name";
|
||||
?>
|
||||
|
||||
const query = '<?= htmlspecialchars((string)filter_input(INPUT_GET, 'user'), ENT_QUOTES) ?>';
|
||||
|
||||
api.get('search', [{name:'q',data:query},{name:'resolve',data:'true'}], function(search) {
|
||||
|
||||
if ( !search.accounts.length ) {
|
||||
location.href="/404.php";
|
||||
} else if ( "@"+search.accounts[0].acct === query ) {
|
||||
setAccount(search.accounts[0]);
|
||||
setFollows(search.accounts[0].id,'followers',[{name:'limit',data:18}]);
|
||||
setRecentImages(search.accounts[0].id);
|
||||
} else {
|
||||
location.href="/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,115 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<div class="profile_icon_box">
|
||||
<img id="js_profile_image" src="/assets/images/missing.png" mediaaccess="true"/>
|
||||
</div>
|
||||
|
||||
<section class="profile_section_wrap">
|
||||
|
||||
<h1 class="profile_displayname">
|
||||
<a id="js_profile_displayname" class="emoji_poss" href="#"></a>
|
||||
</h1>
|
||||
|
||||
<h2 class="profile_username">
|
||||
@<a id="js_profile_username" href="#"></a>
|
||||
</h2>
|
||||
|
||||
<p id="js_profile_bio" class="profile_bio emoji_poss"></p>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_recent_images.php'); ?>
|
||||
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<div id="js-follows_profile">
|
||||
|
||||
</div>
|
||||
|
||||
<footer id="js-follows_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
$("#js-profile_nav_following").toggleClass("view");
|
||||
$("#js-profile_nav_toots > a").attr('href', './'+location.search);
|
||||
$("#js-profile_nav_following > a").attr('href', 'following'+location.search);
|
||||
$("#js-profile_nav_followers > a").attr('href', 'followers'+location.search);
|
||||
$("#js-profile_nav_favourites > a").attr('href','favourites'+location.search);
|
||||
|
||||
<?php if (isset($_GET['mid'])): ?>
|
||||
|
||||
$(function() {
|
||||
// find by mid
|
||||
const account_id = <?= htmlspecialchars((string)filter_input(INPUT_GET, 'mid'), ENT_QUOTES) ?>;
|
||||
|
||||
api.get('accounts/'+account_id, function(AccountObj) {
|
||||
|
||||
if ( AccountObj !== null ) {
|
||||
setAccount(AccountObj);
|
||||
setFollows(account_id,'following',[{name:'limit',data:18}]);
|
||||
setRecentImages(AccountObj.id);
|
||||
} else {
|
||||
location.href="/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
<?php elseif((isset($_GET['user']))): ?>
|
||||
|
||||
$(function(){
|
||||
|
||||
// find by url
|
||||
<?php
|
||||
$name = preg_split("/@/", $_GET['user'])[1];
|
||||
$domain = preg_split("/@/", $_GET['user'])[2];
|
||||
$url = "https://$domain/@$name";
|
||||
?>
|
||||
|
||||
const query = '<?= htmlspecialchars((string)filter_input(INPUT_GET, 'user'), ENT_QUOTES) ?>';
|
||||
|
||||
api.get('search', [{name:'q',data:query},{name:'resolve',data:'true'}], function(search) {
|
||||
|
||||
if ( !search.accounts.length ) {
|
||||
location.href="/404.php";
|
||||
} else if ( "@"+search.accounts[0].acct === query ) {
|
||||
setAccount(search.accounts[0]);
|
||||
setFollows(search.accounts[0].id,'following',[{name:'limit',data:18}]);
|
||||
setRecentImages(search.accounts[0].id);
|
||||
} else {
|
||||
location.href="/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,159 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<div class="profile_icon_box">
|
||||
<img id="js_profile_image" src="/assets/images/missing.png" mediaaccess="true"/>
|
||||
</div>
|
||||
|
||||
<section class="profile_section_wrap">
|
||||
|
||||
<h1 class="profile_displayname">
|
||||
<a id="js_profile_displayname" class="emoji_poss" href="#"></a>
|
||||
</h1>
|
||||
|
||||
<h2 class="profile_username">
|
||||
@<a id="js_profile_username" href="#"></a>
|
||||
</h2>
|
||||
|
||||
<p id="js_profile_bio" class="profile_bio emoji_poss"></p>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_recent_images.php'); ?>
|
||||
|
||||
</section>
|
||||
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
<ul class="header_items">
|
||||
|
||||
<li class="item toots">
|
||||
<a id="toots_link">
|
||||
Toots
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="item wreplies view">
|
||||
<a id="with_replies_link">
|
||||
Toots & replies
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="item media">
|
||||
<a id="media_link">
|
||||
Media
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
$("#toots_link").attr('href', './'+location.search);
|
||||
$("#with_replies_link").attr('href', './with_replies'+location.search);
|
||||
$("#media_link").attr('href', './media'+location.search);
|
||||
|
||||
$("#js-profile_nav_toots > a").toggleClass("view");
|
||||
$("#js-profile_nav_toots > a").attr('href', location.pathname+location.search);
|
||||
$("#js-profile_nav_following > a").attr('href', './following'+location.search);
|
||||
$("#js-profile_nav_followers > a").attr('href', './followers'+location.search);
|
||||
$("#js-profile_nav_favourites > a").attr('href', './favourites'+location.search);
|
||||
|
||||
<?php if (isset($_GET['mid'])): ?>
|
||||
|
||||
$(function() {
|
||||
|
||||
// find by mid
|
||||
const account_id = <?= htmlspecialchars((string)filter_input(INPUT_GET, 'mid'), ENT_QUOTES) ?>;
|
||||
api.get('accounts/'+account_id, function(AccountObj) {
|
||||
|
||||
if ( AccountObj !== null ) {
|
||||
setAccount(AccountObj);
|
||||
setTimeline("accounts/"+AccountObj.id+"/statuses");
|
||||
setRecentImages(AccountObj.id);
|
||||
} else {
|
||||
location.href = "/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
<?php elseif((isset($_GET['user']))): ?>
|
||||
|
||||
$(function(){
|
||||
|
||||
// find by url
|
||||
<?php
|
||||
$name = preg_split("/@/", $_GET['user'])[1];
|
||||
$domain = preg_split("/@/", $_GET['user'])[2];
|
||||
$url = "https://$domain/@$name";
|
||||
?>
|
||||
|
||||
const query = '<?= htmlspecialchars((string)filter_input(INPUT_GET, 'user'), ENT_QUOTES) ?>';
|
||||
|
||||
api.get('search', [{name:'q',data:query},{name:'resolve',data:'true'}], function(search) {
|
||||
|
||||
if ( !search.accounts.length ) {
|
||||
location.href = "/404.php";
|
||||
} else if ( "@"+search.accounts[0].acct === query ) {
|
||||
setAccount(search.accounts[0]);
|
||||
setTimeline("accounts/"+search.accounts[0].id+"/statuses");
|
||||
setRecentImages(search.accounts[0].id);
|
||||
} else {
|
||||
location.href = "/404.php";
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,160 @@
|
|||
<?php include ('header.php'); ?>
|
||||
|
||||
<!-- MAIN -->
|
||||
<main id="main">
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_header.php'); ?>
|
||||
|
||||
<div class="article_wrap">
|
||||
|
||||
<aside class="left_column">
|
||||
|
||||
<div class="profile_icon_box">
|
||||
<img id="js_profile_image" src="/assets/images/missing.png" mediaaccess="true"/>
|
||||
</div>
|
||||
|
||||
<section class="profile_section_wrap">
|
||||
|
||||
<h1 class="profile_displayname">
|
||||
<a id="js_profile_displayname" class="emoji_poss" href="#"></a>
|
||||
</h1>
|
||||
|
||||
<h2 class="profile_username">
|
||||
@<a id="js_profile_username" href="#"></a>
|
||||
</h2>
|
||||
|
||||
<p id="js_profile_bio" class="profile_bio emoji_poss"></p>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/user_recent_images.php'); ?>
|
||||
|
||||
</section>
|
||||
|
||||
<div class="right_column_clone">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<article class="center_column">
|
||||
|
||||
<header class="timeline_header">
|
||||
<ul class="header_items">
|
||||
|
||||
<li class="item toots">
|
||||
<a id="toots_link">
|
||||
Toots
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="item wreplies">
|
||||
<a id="with_replies_link">
|
||||
Toots & replies
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="item media view">
|
||||
<a id="media_link">
|
||||
Media
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</header>
|
||||
|
||||
<div id="js-stream_update">
|
||||
<button>
|
||||
View <span></span> new Toots
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul id="js-timeline" class="timeline">
|
||||
</ul>
|
||||
|
||||
<footer id="js-timeline_footer" class="timeline_footer">
|
||||
<i class="fa fa-spin fa-circle-o-notch" aria-hidden="true"></i>
|
||||
</footer>
|
||||
|
||||
</article>
|
||||
|
||||
<aside class="right_column">
|
||||
|
||||
<section class="side_widgets_wrap">
|
||||
<?php include dirname(__FILE__).('/widgets/side_who_to_follow.php'); ?>
|
||||
</section>
|
||||
|
||||
<?php include dirname(__FILE__).('/widgets/side_footer.php'); ?>
|
||||
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
|
||||
// namespace
|
||||
current_file = location.pathname;
|
||||
|
||||
$("#toots_link").attr('href', './'+location.search);
|
||||
$("#with_replies_link").attr('href', './with_replies'+location.search);
|
||||
$("#media_link").attr('href', './media'+location.search);
|
||||
$("#js-profile_nav_toots > a").toggleClass("view");
|
||||
$("#js-profile_nav_toots > a").attr('href', location.pathname+location.search);
|
||||
$("#js-profile_nav_following > a").attr('href', './following'+location.search);
|
||||
$("#js-profile_nav_followers > a").attr('href', './followers'+location.search);
|
||||
$("#js-profile_nav_favourites > a").attr('href', './favourites'+location.search);
|
||||
|
||||
<?php if (isset($_GET['mid'])): ?>
|
||||
|
||||
$(function() {
|
||||
|
||||
// find by mid
|
||||
const account_id = <?= htmlspecialchars((string)filter_input(INPUT_GET, 'mid'), ENT_QUOTES) ?>;
|
||||
|
||||
api.get('accounts/'+account_id, function(AccountObj) {
|
||||
|
||||
if ( AccountObj !== null ) {
|
||||
setAccount(AccountObj);
|
||||
setTimeline("accounts/"+AccountObj.id+"/statuses",[{name:'only_media',data:'true'}]);
|
||||
setRecentImages(AccountObj.id);
|
||||
} else {
|
||||
location.href = "/404.php";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
<?php elseif((isset($_GET['user']))): ?>
|
||||
|
||||
$(function(){
|
||||
|
||||
// find by url
|
||||
<?php
|
||||
$name = preg_split("/@/", $_GET['user'])[1];
|
||||
$domain = preg_split("/@/", $_GET['user'])[2];
|
||||
$url = "https://$domain/@$name";
|
||||
?>
|
||||
|
||||
const query = '<?= htmlspecialchars((string)filter_input(INPUT_GET, 'user'), ENT_QUOTES) ?>';
|
||||
|
||||
api.get('search', [{name:'q',data:query},{name:'resolve',data:'true'}], function(search) {
|
||||
|
||||
if ( !search.accounts.length ) {
|
||||
location.href="/404.php";
|
||||
} else if ( "@"+search.accounts[0].acct === query ) {
|
||||
setAccount(search.accounts[0]);
|
||||
setTimeline("accounts/"+search.accounts[0].id+"/statuses",[{name:'only_media',data:'true'}]);
|
||||
setRecentImages(search.accounts[0].id);
|
||||
} else {
|
||||
location.href="/404.php";
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</script>
|
||||
|
||||
<?php include ('footer.php'); ?>
|
|
@ -0,0 +1,101 @@
|
|||
<form id="header_status_form" name="header_status_form" class="status_form ready">
|
||||
|
||||
<div class="status_top">
|
||||
<input class="status_spoiler invisible" name="status_spoiler" placeholder="Content warning" type="text"/>
|
||||
</div>
|
||||
|
||||
<div class="status_main">
|
||||
|
||||
<!-- current avatar -->
|
||||
<div class="icon_box">
|
||||
<img class="js_current_profile_image" />
|
||||
</div>
|
||||
|
||||
<!-- text area -->
|
||||
<div class="status_textarea">
|
||||
|
||||
<textarea class="emoji_poss" name="status_textarea" placeholder="What's happening?"></textarea>
|
||||
|
||||
<div class="media_attachments_preview_area invisible"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="status_bottom invisible">
|
||||
|
||||
<!-- Media Attachment -->
|
||||
<label for="header_status_media_atta" class="status_media_attachment status_option_button">
|
||||
<i class="fa fa-camera" aria-hidden="true"></i>
|
||||
</label>
|
||||
|
||||
<!-- Content warning -->
|
||||
<label for="header_status_cw" class="status_CW status_option_button">
|
||||
<span class="disallow_select">CW</span>
|
||||
</label>
|
||||
|
||||
<!-- Not safe for work -->
|
||||
<label for="header_status_nsfw" class="status_NSFW status_option_button">
|
||||
<span class="disallow_select">NSFW</span>
|
||||
</label>
|
||||
|
||||
<!-- Privacy options -->
|
||||
<div class="status_privacy status_option_button expand_privacy_menu_button">
|
||||
|
||||
<!-- Expand menu -->
|
||||
<i class="fa fa-globe" aria-hidden="true"></i>
|
||||
|
||||
<!-- Privacy options -->
|
||||
<div class="expand_privacy_menu invisible">
|
||||
|
||||
<label for="header_status_public" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-globe">
|
||||
<i class="fa fa-globe" aria-hidden="true"></i>Public
|
||||
</label>
|
||||
|
||||
<label for="header_status_unlisted" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-unlock-alt">
|
||||
<i class="fa fa-unlock-alt" aria-hidden="true"></i>Unlisted
|
||||
</label>
|
||||
|
||||
<label for="header_status_fonly" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-lock">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>Followers-only
|
||||
</label>
|
||||
|
||||
<label for="header_status_direct" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-envelope">
|
||||
<i class="fa fa-envelope" aria-hidden="true"></i>Direct
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<input id="header_status_media_atta" name="files" type="file" multiple class="invisible"/>
|
||||
<input id="header_status_cw" name="status_cw" type="checkbox" class="invisible" />
|
||||
<input id="header_status_nsfw" name="status_nsfw" type="checkbox" class="invisible" />
|
||||
<input id="header_status_public" name='privacy_option' value="public" class="invisible" type="radio" />
|
||||
<input id="header_status_unlisted" name='privacy_option' value="unlisted" class="invisible" type="radio" />
|
||||
<input id="header_status_fonly" name='privacy_option' value="private" class="invisible" type="radio" />
|
||||
<input id="header_status_direct" name='privacy_option' value="direct" class="invisible" type="radio" />
|
||||
|
||||
<div class="submit_status_label_wrap">
|
||||
|
||||
<span class="character_count">
|
||||
512
|
||||
</span>
|
||||
|
||||
<!-- Submit -->
|
||||
<label for="header_status_form_submit" class="submit_status_label">
|
||||
|
||||
<div class="toot_button_label disallow_select" >
|
||||
<i class="fa fa-fw fa-pencil-square-o"></i>
|
||||
<span>Toot</span>
|
||||
</div>
|
||||
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<input id="header_status_form_submit" class="submit_status" type="button" class="invisible"/>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
|
@ -0,0 +1,11 @@
|
|||
<div class="overlay_copy_link invisible">
|
||||
|
||||
<header class="overlay_copy_link_header">
|
||||
<span class="emoji_poss">Copy link to Toot</span>
|
||||
</header>
|
||||
|
||||
<div class="overlay_copy_link_form">
|
||||
<input type="text" value="" readonly/>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,104 @@
|
|||
<div class="overlay_status invisible">
|
||||
|
||||
<header class="overlay_status_header">
|
||||
<span>Compose new Toot</span>
|
||||
</header>
|
||||
|
||||
<form id="overlay_status_form" name="overlay_status_form" class="status_form ready">
|
||||
|
||||
<div class="status_top">
|
||||
<input class="status_spoiler invisible" name="status_spoiler" placeholder="Content warning" type="text"/>
|
||||
</div>
|
||||
|
||||
<div class="status_main">
|
||||
|
||||
<!-- text area -->
|
||||
<div class="status_textarea">
|
||||
|
||||
<textarea class="emoji_poss" name="status_textarea" placeholder="What's happening?"></textarea>
|
||||
|
||||
<div class="media_attachments_preview_area invisible"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="status_bottom">
|
||||
|
||||
<!-- Media Attachment -->
|
||||
<label for="overlay_status_media_atta" class="status_media_attachment status_option_button">
|
||||
<i class="fa fa-camera" aria-hidden="true"></i>
|
||||
</label>
|
||||
|
||||
<!-- Content warning -->
|
||||
<label for="overlay_status_cw" class="status_CW status_option_button">
|
||||
<span class="disallow_select">CW</span>
|
||||
</label>
|
||||
|
||||
<!-- Not safe for work -->
|
||||
<label for="overlay_status_nsfw" class="status_NSFW status_option_button">
|
||||
<span class="disallow_select">NSFW</span>
|
||||
</label>
|
||||
|
||||
<!-- Privacy options -->
|
||||
<div class="status_privacy status_option_button expand_privacy_menu_button">
|
||||
|
||||
<!-- Expand menu -->
|
||||
<i class="fa fa-globe" aria-hidden="true"></i>
|
||||
|
||||
<!-- Privacy options -->
|
||||
<div class="expand_privacy_menu invisible">
|
||||
|
||||
<label for="overlay_status_public" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-globe">
|
||||
<i class="fa fa-globe" aria-hidden="true"></i>Public
|
||||
</label>
|
||||
|
||||
<label for="overlay_status_unlisted" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-unlock-alt">
|
||||
<i class="fa fa-unlock-alt" aria-hidden="true"></i>Unlisted
|
||||
</label>
|
||||
|
||||
<label for="overlay_status_fonly" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-lock">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>Followers-only
|
||||
</label>
|
||||
|
||||
<label for="overlay_status_direct" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-envelope">
|
||||
<i class="fa fa-envelope" aria-hidden="true"></i>Direct
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<input id="overlay_status_media_atta" name="files" type="file" multiple class="invisible"/>
|
||||
<input id="overlay_status_cw" name="status_cw" type="checkbox" class="invisible" />
|
||||
<input id="overlay_status_nsfw" name="status_nsfw" type="checkbox" class="invisible" />
|
||||
<input id="overlay_status_public" name='privacy_option' value="public" class="invisible" type="radio" />
|
||||
<input id="overlay_status_unlisted" name='privacy_option' value="unlisted" class="invisible" type="radio" />
|
||||
<input id="overlay_status_fonly" name='privacy_option' value="private" class="invisible" type="radio" />
|
||||
<input id="overlay_status_direct" name='privacy_option' value="direct" class="invisible" type="radio" />
|
||||
|
||||
<div class="submit_status_label_wrap">
|
||||
|
||||
<span class="character_count">
|
||||
500
|
||||
</span>
|
||||
|
||||
<!-- Submit -->
|
||||
<label for="overlay_status_form_submit" class="submit_status_label">
|
||||
|
||||
<div class="toot_button_label disallow_select">
|
||||
<i class="fa fa-fw fa-pencil-square-o"></i>
|
||||
<span>Toot</span>
|
||||
</div>
|
||||
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<input id="overlay_status_form_submit" class="submit_status" type="button" class="invisible"/>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,5 @@
|
|||
<div id="overlay_message">
|
||||
<section>
|
||||
<span></span>
|
||||
</section>
|
||||
</div>
|
|
@ -0,0 +1,105 @@
|
|||
<div class="single_reply_status invisible">
|
||||
<header class="single_reply_status_header">
|
||||
<span class="emoji_poss">Reply to </span>
|
||||
</header>
|
||||
|
||||
<div class="status_preview"></div>
|
||||
|
||||
<form id="single_reply_status_form" name="single_reply_status_form" class="status_form">
|
||||
|
||||
<div class="status_top">
|
||||
<input class="status_spoiler invisible" name="status_spoiler" placeholder="Content warning" type="text"/>
|
||||
</div>
|
||||
|
||||
<div class="status_main">
|
||||
|
||||
<!-- text area -->
|
||||
<div class="status_textarea">
|
||||
|
||||
<textarea class="emoji_poss" name="status_textarea" placeholder="What's happening?"></textarea>
|
||||
|
||||
<div class="media_attachments_preview_area invisible"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="status_bottom">
|
||||
|
||||
<!-- Media Attachment -->
|
||||
<label for="single_reply_status_media_atta" class="status_media_attachment status_option_button">
|
||||
<i class="fa fa-camera" aria-hidden="true"></i>
|
||||
</label>
|
||||
|
||||
<!-- Content warning -->
|
||||
<label for="single_reply_status_cw" class="status_CW status_option_button">
|
||||
<span class="disallow_select">CW</span>
|
||||
</label>
|
||||
|
||||
<!-- Not safe for work -->
|
||||
<label for="single_reply_status_nsfw" class="status_NSFW status_option_button">
|
||||
<span class="disallow_select">NSFW</span>
|
||||
</label>
|
||||
|
||||
<!-- Privacy options -->
|
||||
<div class="status_privacy status_option_button expand_privacy_menu_button">
|
||||
|
||||
<!-- Expand menu -->
|
||||
<i class="fa fa-globe" aria-hidden="true"></i>
|
||||
|
||||
<!-- Privacy options -->
|
||||
<div class="expand_privacy_menu invisible">
|
||||
|
||||
<label for="single_reply_status_public" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-globe">
|
||||
<i class="fa fa-globe" aria-hidden="true"></i>Public
|
||||
</label>
|
||||
|
||||
<label for="single_reply_status_unlisted" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-unlock-alt">
|
||||
<i class="fa fa-unlock-alt" aria-hidden="true"></i>Unlisted
|
||||
</label>
|
||||
|
||||
<label for="single_reply_status_fonly" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-lock">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>Followers-only
|
||||
</label>
|
||||
|
||||
<label for="single_reply_status_direct" class="status_privacy select_privacy disallow_select" privacyicon="fa fa-envelope">
|
||||
<i class="fa fa-envelope" aria-hidden="true"></i>Direct
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<input id="single_reply_status_media_atta" name="files" type="file" multiple class="invisible"/>
|
||||
<input id="single_reply_status_cw" name="status_cw" type="checkbox" class="invisible" />
|
||||
<input id="single_reply_status_nsfw" name="status_nsfw" type="checkbox" class="invisible" />
|
||||
<input id="single_reply_status_public" name='privacy_option' value="public" class="invisible" type="radio" />
|
||||
<input id="single_reply_status_unlisted" name='privacy_option' value="unlisted" class="invisible" type="radio" />
|
||||
<input id="single_reply_status_fonly" name='privacy_option' value="private" class="invisible" type="radio" />
|
||||
<input id="single_reply_status_direct" name='privacy_option' value="direct" class="invisible" type="radio" />
|
||||
|
||||
<div class="submit_status_label_wrap">
|
||||
|
||||
<span class="character_count">
|
||||
500
|
||||
</span>
|
||||
|
||||
<!-- Submit -->
|
||||
<label for="single_reply_status_form_submit" class="submit_status_label">
|
||||
|
||||
<div class="toot_button_label disallow_select">
|
||||
<i class="fa fa-reply" aria-hidden="true"></i>
|
||||
<span>Reply</span>
|
||||
</div>
|
||||
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<input id="single_reply_status_form_submit" class="submit_status" type="button" class="invisible"/>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,31 @@
|
|||
<div id="js-search_title_box">
|
||||
<h1></h1>
|
||||
</div>
|
||||
|
||||
<!-- PROFILE NAV -->
|
||||
<div class="search_nav_wrap">
|
||||
<div class="search_nav">
|
||||
|
||||
<!-- PROFILE NAV LEFT -->
|
||||
<div class="search_nav_left">
|
||||
<ul class="search_nav_list">
|
||||
|
||||
<!-- TOOTS -->
|
||||
<li id="js-search_nav_toots" class="search_nav_item search_toots">
|
||||
<a>
|
||||
<h2>TOOTS</h2>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- FOLLOWING -->
|
||||
<li id="js-search_nav_peoples" class="search_nav_item search_following">
|
||||
<a>
|
||||
<h2>PEOPLE</h2>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,15 @@
|
|||
<div class="side_widget stream_options">
|
||||
|
||||
<div class="form_title">
|
||||
<h2>Change instance</h2>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
|
||||
<div class="local_instance_wrap">
|
||||
<input name="local_instance" placeholder="Blank for default" type="text" class="disallow_enter"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,46 @@
|
|||
<div class="current_profile_box">
|
||||
|
||||
<div class="current_profile_header">
|
||||
<img class="js_current_header_image" />
|
||||
</div>
|
||||
|
||||
<div class="current_profile">
|
||||
|
||||
<div class="current_profile_icon">
|
||||
<img class="js_current_profile_image"/>
|
||||
</div>
|
||||
|
||||
<div class="current_profile_name_box">
|
||||
<a class="js_current_profile_link">
|
||||
<h2 class="js_current_profile_displayname emoji_poss"></h2>
|
||||
<span class="js_current_profile_username"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ul class="current_profile_counts">
|
||||
|
||||
<li class="current_profile_count current_profile_toots_count">
|
||||
<a class="current_toots_count_link">
|
||||
<span class="title">TOOTS</span>
|
||||
<span class="js_current_toots_count count"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="current_profile_count current_profile_follows_count">
|
||||
<a class="current_following_count_link">
|
||||
<span class="title">FOLLOWING</span>
|
||||
<span class="js_current_following_count count"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="current_profile_count current_profile_followers_count">
|
||||
<a class="current_followers_count_link">
|
||||
<span class="title">FOLLOWERS</span>
|
||||
<span class="js_current_followers_count count"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,61 @@
|
|||
<div class="side_widget what_to_follow">
|
||||
|
||||
<h2>Dev team</h2>
|
||||
|
||||
<ul class="account_list">
|
||||
<li class="account_box">
|
||||
<div class="icon_box">
|
||||
<img src="/assets/images/icon.jpeg"/>
|
||||
</div>
|
||||
<div class="label_box">
|
||||
<a href="/@neet@mastodon.cloud">
|
||||
<h3>
|
||||
<span class="dn">Neetshin</span>
|
||||
<span class="un">@neet@mastodon.cloud</span>
|
||||
</h3>
|
||||
</a>
|
||||
<button class="follow_button action_button" data="@neet@mastodon.cloud">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="account_box">
|
||||
<div class="icon_box">
|
||||
<img src="/assets/images/icon_pinfort.png"/>
|
||||
</div>
|
||||
<div class="label_box">
|
||||
<a href="/@pinfort@jp-mstdn.com">
|
||||
<h3>
|
||||
<span class="dn">pinfort</span>
|
||||
<span class="un">@pinfort@jp-mstdn.com</span>
|
||||
</h3>
|
||||
</a>
|
||||
<button class="follow_button" data="@pinfort@jp-mstdn.com">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="account_box">
|
||||
<div class="icon_box">
|
||||
<img src="/assets/images/icon_peijun.jpeg"/>
|
||||
</div>
|
||||
<div class="label_box">
|
||||
<a href="@peijun@mastodon.cloud">
|
||||
<h3>
|
||||
<span class="dn">Peijun</span>
|
||||
<span class="un">@peijun@mastodon.cloud</span>
|
||||
</h3>
|
||||
</a>
|
||||
<button class="follow_button" data="@peijun@mastodon.cloud">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,33 @@
|
|||
<footer class="side_widgets_footer side_widget">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
Halcyon for <a href="https://github.com/tootsuite/mastodon">Mastodon</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="footer_widget_about">About</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="footer_widget_terms">Terms</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">Apps</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/tootsuite/mastodon">Source code</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/List-of-Mastodon-instances.md">Other instances</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</footer>
|
||||
|
||||
<img style="display:block;margin:16px auto;width: 30%;opacity: .3;" src="/assets/images/halcyon.png" />
|
|
@ -0,0 +1,28 @@
|
|||
<div class="side_widget stream_options">
|
||||
|
||||
<div class="form_title">
|
||||
<h2>Preferences</h2>
|
||||
<button>SHOW</button>
|
||||
</div>
|
||||
|
||||
<form name="stream_options_form" class="pulldown_form">
|
||||
|
||||
<h3>New posts streaming</h3>
|
||||
<div class="post_steraming_wrap">
|
||||
</div>
|
||||
|
||||
<h3>Default post privacy</h3>
|
||||
<div class="post_privacy_wrap">
|
||||
</div>
|
||||
|
||||
<h3>Local instance</h3>
|
||||
<div class="local_instance_wrap">
|
||||
</div>
|
||||
|
||||
<h3>Hashtag search filter</h3>
|
||||
<div class="search_filter_wrap">
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
|
@ -0,0 +1,60 @@
|
|||
<div class="side_widget what_to_follow">
|
||||
|
||||
<h2>Who to follow</h2>
|
||||
|
||||
<ul class="account_list">
|
||||
<li class="account_box what_to_follow_0">
|
||||
<div class="icon_box">
|
||||
<img src=""/>
|
||||
</div>
|
||||
<div class="label_box">
|
||||
<a href="">
|
||||
<h3>
|
||||
<span class="dn emoji_poss"></span>
|
||||
<span class="un"></span>
|
||||
</h3>
|
||||
</a>
|
||||
<button class="follow_button" mid="" data="">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="account_box what_to_follow_1">
|
||||
<div class="icon_box">
|
||||
<img src=""/>
|
||||
</div>
|
||||
<div class="label_box">
|
||||
<a href="">
|
||||
<h3>
|
||||
<span class="dn emoji_poss"></span>
|
||||
<span class="un"></span>
|
||||
</h3>
|
||||
</a>
|
||||
<button class="follow_button" mid="" data="">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="account_box what_to_follow_2">
|
||||
<div class="icon_box">
|
||||
<img src=""/>
|
||||
</div>
|
||||
<div class="label_box">
|
||||
<a href="">
|
||||
<h3>
|
||||
<span class="dn emoji_poss"></span>
|
||||
<span class="un"></span>
|
||||
</h3>
|
||||
</a>
|
||||
<button class="follow_button" mid="" data="">
|
||||
<i class="fa fa-fw fa-user-plus"></i>
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,54 @@
|
|||
<!-- HEADER IMAGE -->
|
||||
<div class="header_image_box">
|
||||
<img id="js_header_image" src="/assets/images/missing_header.png" />
|
||||
</div>
|
||||
|
||||
<!-- PROFILE NAV -->
|
||||
<div class="profile_nav_wrap">
|
||||
<div class="profile_nav">
|
||||
|
||||
<!-- PROFILE NAV LEFT -->
|
||||
<div class="profile_nav_left">
|
||||
<!-- empty -->
|
||||
</div>
|
||||
|
||||
<!-- PROFILE NAV RIGHT -->
|
||||
<div class="profile_nav_right">
|
||||
<ul class="profile_nav_list">
|
||||
|
||||
<!-- TOOTS -->
|
||||
<li id="js-profile_nav_toots" class="profile_nav_item profile_toots">
|
||||
<a>
|
||||
<h2>TOOTS</h2>
|
||||
<span id="js_toots_count"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- FOLLOWING -->
|
||||
<li id="js-profile_nav_following" class="profile_nav_item profile_following">
|
||||
<a>
|
||||
<h2>FOLLOWING</h2>
|
||||
<span id="js_following_count"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- FOLLOWERS -->
|
||||
<li id="js-profile_nav_followers" class="profile_nav_item profile_followers">
|
||||
<a>
|
||||
<h2>FOLLOWERS</h2>
|
||||
<span id="js_followers_count"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- FAVOURITES -->
|
||||
<li id="js-profile_nav_favourites" class="profile_nav_item profile_favourites">
|
||||
</li>
|
||||
|
||||
<!-- ACTION BUTTON -->
|
||||
<li class="profile_button_box">
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,9 @@
|
|||
<div id="js_profile_recent_images">
|
||||
|
||||
<a><i class="fa fa-camera" aria-hidden="true"></i><span></span></a>
|
||||
|
||||
<div id="js_profile_recent_images_box">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|