Простий Twitter клієнт на ExtJS та Zend Framework

Насправді це не повноцінний клієнт, а написаний в демонстраційних цілях. Виконує лише прості функції - переглядає стрічку повідомлень, свої повідомлення, людей які зафоловили вас, і тих, кого зафоловили ви. Ну і, звісно, публікує твіти. twitter logo

Для початку напишемо інтерфейс для клієнта. Виглядати він буде так:

Клієнтська частина


var inputField = new  Ext.form.TextArea({
    id: 'input-area',
    name: 'inputArea',
    width: '100%',
    height: 60,
    padding: '5px'
});
var inputPanel = new Ext.Panel({
    region:'north',
    border: false,
    height: 85,
    items: inputField,
    bbar: [
        '->', {
	    text: 'clear',
	    listeners: {
	        'click': function() {
		    inputField.setValue("");
		}
	    }
	},{
	    text: 'send',
	    listeners: {
	    'click': function() {
	        ....
                /* Публікація повідомлення */
                ....
	    }
	}
	}
    ]
});
inputPanel - панель для створення і публікації повідомлення.

var itemFriends = new Ext.Panel({
	id: 'item-friends',
        title: 'Friends',
        autoScroll: 'auto',
        items: viewFeed,
        cls:'empty',
        listeners: {
	    'beforeexpand': function(){

	    }
        }
});

var itemMy = new Ext.Panel({
	id: 'item-my',
        title: 'My',
        autoScroll: 'auto',
        items: viewMy,
        cls:'empty',
        listeners: {
            'beforeexpand': function(){

	    }
        }
});

 var itemFollowing = new Ext.Panel({
    	id: 'item-following',
        title: 'Following',
        autoScroll: 'auto',
        cls:'empty',
        items: viewFollowing,
        listeners: {
	    'beforeexpand': function(){

	    }
        }
});

var itemFollowers = new Ext.Panel({
    	id: 'item-followers',
        title: 'Followers',
        autoScroll: 'auto',
        items: viewFollowers,
        cls:'empty',
        listeners: {
            'beforeexpand': function(){

	    }
        }
});

var accordion = new Ext.Panel({
        region:'center',
        border: false,
        split:true,
        layout:'accordion',
        items: [itemFriends, itemMy, itemFollowing, itemFollowers]
});
Панель accordion - для відображення змісту я вибрав тип розміщення компонентів 'accordion'. В панелях itemFriends, itemMy, itemFollowing, itemFollowers відповідно буде знаходитися: стрічка друзів, свої твіти, ваші друзі і ті, у кого ви у друзях.

var window = new Ext.Window({
    title: 'Ext-Twitter',
    width:300,
    border: false,
    height:600,
    disable: true,
    shim:false,
    maximizable: false,
    tools:[{
        id:'refresh',
	qtip: 'Refresh messages',
	handler: function(event, toolEl, panel){
	    /* refresh panels */
	 }
    },{
        id:'gear',
	qtip: 'Options',
	handler: function(event, toolEl, panel){
	    options();
	}
    }],
    layout: 'border',
        listeners: {
	    'close': function(){
	        Ext.Ajax.request({
        	   url: '/twitter/logout/'
		 });
	    }
	},
    items: [ inputPanel, accordion ]
});
window.show();
Створюється вікно, у якому будуть відображатися ці панелі. У властивість tools компоненту Window додано кнопки оновлення стрічки та вікна налаштувань аккаунту. Поставимо обробник, що спрацьовує на закриття вікна - він закриватиме сесію роботи з клієнтом.

var tplFeed = new Ext.XTemplate(
    '<div id="list-view"><tpl for=".">',
    '<div class="thumb-wrap" id="item-{id}">',
    '<img width="48" align="left" src="{awatar}" alt="{name}"><div class="x-view"><b>{name}</b> {message}</div><div class="createdate">{createdate}</div></div>',
    '</tpl></div>'
);

var tplUsers = new Ext.XTemplate(
    '<div id="list-view"><tpl for=".">',
    '<div class="thumb-wrap" id="item-{id}">',
    '<img width="48" align="left" src="{awatar}" alt="{name}"><div class="x-view"><b>{name}</b><div>{description}</div></div></div>',
    '</tpl></div>'
);
tplFeed та tplUsers - шаблони для відображення стрічки повідомлень та користувачів відповідно. Тут не забуваємо про стилі, які необхідно додати для коректного відображення інформації.

/* Friends */
 var storeFeed = new Ext.data.JsonStore({
    url: '/twitter/feed/',
    root: 'data',
    baseParams: { 'type': 'friends' },
    fields: [
        'name', 'id', 'login', 'createdate', 'message', 'awatar'
    ]
});

var viewFeed = new Ext.DataView({
    tpl: tplFeed,
    singleSelect: true,
    itemSelector: 'div.thumb-wrap',
    emptyText : '<div style="padding:10px;">Empty</div>',
    store: storeFeed,
    overClass:'x-view-over'
});

/* My */
var storeMy = new Ext.data.JsonStore({
    url: '/twitter/feed/',
    root: 'data',
    baseParams: { 'type': 'my' },
    fields: [
        'name', 'id', 'login', 'createdate', 'message', 'awatar'
    ]
});

var viewMy = new Ext.DataView({
    tpl: tplFeed,
    singleSelect: true,
    itemSelector: 'div.thumb-wrap',
    emptyText : '<div style="padding:10px;">Empty</div>',
    store: storeMy,
    overClass:'x-view-over'
});

/* Following  */
var storeFollowing = new Ext.data.JsonStore({
    url: '/twitter/users/',
    root: 'data',
    baseParams: { 'type': 'following' },
    fields: [
        'name', 'id', 'login', 'awatar', 'description'
    ]
});

var viewFollowing = new Ext.DataView({
    tpl: tplUsers,
    singleSelect: true,
    itemSelector: 'div.thumb-wrap',
    emptyText : '<div style="padding:10px;">Empty</div>',
    store: storeFollowing,
    overClass:'x-view-over'
});

/* Followers  */
var storeFollowers = new Ext.data.JsonStore({
    url: '/twitter/users/',
    root: 'data',
    baseParams: { 'type': 'followers' },
    fields: [
        'name', 'id', 'login', 'awatar', 'description'
    ]
});

var viewFollowers = new Ext.DataView({
    tpl: tplUsers,
    singleSelect: true,
    itemSelector: 'div.thumb-wrap',
    emptyText : '<div style="padding:10px;">Empty</div>',
    store: storeFollowers,
    overClass:'x-view-over'
});
Тут додаються компоненти Ext.data.JsonStore та Ext.DataView, які будуть завантажувати та відображати інформацію через шаблони. Я сильно не заморочувався і створив для кожної панелі по одній парі таких компонентів.

function options(){
    var optionsForm = new Ext.FormPanel({
        labelWidth: 75,
        url:'save-form.php',
        bodyStyle:'padding:5px 5px 0',
        width: 320,
        defaults: {width: 200},
        defaultType: 'textfield',
        items: [{
                fieldLabel: 'Login',
                name: 'login',
                allowBlank:false
            },{
                fieldLabel: 'Password',
                name: 'password',
                inputType: "password",
                allowBlank:false
            }
        ],
        reader : new Ext.data.JsonReader({
    	   	root: "data",
			id: "id"
       	},[
        	'login', 'password'
        ]),
        buttons: [{
            text: 'Cancel',
            listeners: {
                'click': function(){
        	    optionsWindow.close();
        	 }
            }
        }, {
            text: 'Connect',
            listeners: {
		'click': function(){
        	    optionsWindow.disable();
        	    optionsForm.getForm().submit({
            		url:'/twitter/login/',
            		params: {
			    'data': Ext.encode(optionsForm.getForm().getValues())
            		},
            		success: function() {
            		    optionsWindow.enable();
            		    window.enable();
            		    logged = true;
            		    loadFeed();
                	}
                    });
        	optionsWindow.close();
        	}
            }
        }]
    });

    var optionsWindow = new Ext.Window({
        title: 'Ext-Twitter options',
        width:320,
        border: false,
        height:150,
        shim:false,
        modal: true,
        maximizable: false,
        layout: 'fit',
        items: optionsForm
    });
    optionsWindow.show();
}
Створення діалогового вікна з налаштуваннями аккаунта. В поля достатньо ввести ваш twitter-логін та пароль і при натисненні "Connect" спрацює обробник "/twitter/login/". При успішному залогування змінну logged встановимо в true. Виглядає воно так:

function loadFeed() {
    if (logged != true) return;
     	switch(accordion.layout.activeItem.id) {
            case 'item-friends':
     	        storeFeed.load();
         	break;
     	    case 'item-my':
     		storeMy.load();
        	break;
     	    case 'item-following':
     		storeFollowing.load();
        	break;
     	    case 'item-followers':
     		storeFollowers.load();
        	break;
     	    default:
         	break;
        }
}
Функція завантаження інформації (стрічки з повідомленнями чи список користувачів) в залежності від активної панелі.

Серверна частина

Опишу контроллер, що буде обробляти клієнтські запити.

public function loginAction() {
    $this->_helper->viewRenderer->setNoRender();
    $data = $this->getRequest()->getParam('data', 0);
    if ($data) {
        $data = json_decode(stripslashes($data), 1);
        $login = $data['login'];
        $password = $data['password'];
        $twitter = new Zend_Service_Twitter($login, $password);
        $response = $twitter->account->verifyCredentials();
        if ($response) {
            $twitterNamespace = new Zend_Session_Namespace('Twitter_Auth');
            $twitterNamespace->login = $login;
            $twitterNamespace->password = $password;
            echo '{"success": true}';
        }
    }
}
Протягом всього часу буде використовуватися компонент Zend Framework - Zend_Service_Twitter. В даному методі приймаються від користувача логін та пароль, в разі успішної аутентифікації данні зберігаються у сессії.

public function logoutAction() {
    $this->_helper->viewRenderer->setNoRender();
    $twitterNamespace = new Zend_Session_Namespace('Twitter_Auth');
    $twitter = new Zend_Service_Twitter($twitterNamespace->login, $twitterNamespace->password);
    $response = $twitter->account->endSession();
    Zend_Session::namespaceUnset('Twitter_Auth');
    echo "{'success': true}";
}
При закритті вікна клієнта спрацьовує цей обробник. Він закриває сесію з даними аутентифікації.

public function feedAction() {
    $this->_helper->viewRenderer->setNoRender();
    $type = $this->getRequest()->getParam('type', 'friends');
    $twitterNamespace = new Zend_Session_Namespace('Twitter_Auth');
    $twitter = new Zend_Service_Twitter($twitterNamespace->login, $twitterNamespace->password);
    switch ($type) {
        case 'friends':
	    $response = $twitter->status->friendsTimeline();
	    break;
	case 'my':
	    $response = $twitter->status->userTimeline();
	    break;
	default:
	    echo "{'success': false}";
	    return;
    }
    $data = array();
    foreach ($response as $item) {
        $id = (string)$item->id;
	$awatar = (string)$item->user->profile_image_url;
	$login =  (string)$item->user->screen_name;
	$user =  (string)$item->user->name;
	$createdate =  (string)$item->created_at;
	$message =  (string)$item->text;
	$data[] = array(
	    'id'	=>	$id,
	    'awatar'	=>	$awatar,
	    'login'	=>	$login,
	    'name'	=>	$user,
	    'createdate'	=>	$createdate,
	    'message'	=>	$message
	);
    }
    $res = array(
        'data'	=>	$data
    );
    echo json_encode($res);
}
Отримання стрічки з повідомленнями. Метод status->friendsTimeline() повертає стрічку друзів, а метод status->userTimeline() - власні твіти.
Аналогічно виводяться користувачі. Метод user->friends() повертає список ваших друзів, а user->followers() - у кого ви у друзях.

І нарешті, метод, що публікує повідомлення.

public function updateAction()
{
	$this->_helper->viewRenderer->setNoRender();
	$text = $this->getRequest()->getParam('text', 0);
	if ($text) {
		$twitterNamespace = new Zend_Session_Namespace('Twitter_Auth');
		$twitter = new Zend_Service_Twitter($twitterNamespace->login, $twitterNamespace->password);
		$response = $twitter->status->update($text);
		if ($response) echo "{'success': true}";
	}
}
Подивитися клієнт в дії можна за адресою http://labs.vlasuk.org.ua/twitter.

І цікаво було б почути думку, чи є доцільність у використанні такого типу клієнтів.

коментарі:

sky 16.12.2009 11:47
Upd. Більш зручніше повний js-код можна переглянути теж тут - http://labs.vlasuk.org.ua/twitter
+1Влад 16.12.2009 12:02
ще би повний код у вигляді архівчика ;)
sky 17.12.2009 07:15
блін. js - подивіться джерело сторінки тут - http://labs.vlasuk.org.ua/twitter.
php - весь код у статті

додати коментар: