среда, 21 октября 2009 г.

Google Wave на iPhone. Краткий обзор

Пользователь shifttstas сделал отличный обзор как Google Wave выглядит на мобильных устройствах и в частности на iPhone.

Как вы знаете Google Wave поддерживает только новые браузеры, у этого есть логичное объяснение, так как wave основан на очень мощной платформе из Java script то не каждый браузер может её запустить, но сегодня Google сделала поддержку Wave на iPhone


А так же в месте с версией для iPhone они добавили наконец поддержку показа кто онлайн.
При нахождении кого либо онлайн отображается зеленая точка
image


И так что бы попасть набирает в iPhone известный нам всем адрес wave.google.com, нас естественно перекидывает на https версию, после того как увидим окно
image

Нажимаем Go Ahead

И попадаем в
image

Одна из самых интересных вещей, что гаджеты работают!

image

А так же можно посмотреть на свой контакт список


image

Функция прокрутки времени Playback тоже работает


image

А вот и меню управления волной


image

Ну что же можно написать? Спасибо, Стас, что ты сделал такой обзор и будем как всегда ждать, когда всех пустят в Google Wave. Самое главное, что бы это ожидание не превратилось в привычку.

Написание базового wave-робота на python'e

По лету мне достался инвайт в Google Wave Sandbox. Но в этой самой песочнице было очень много народу, все волны были публичными, и мой бедный нетбук только с большим скрипом переваривал всю эту активность, так что, немного поигравшись, на сендбокс я забил :)
И вот недавно мой аккаунт в sandbox превратился в аккаунт в лайвпревью, и я, разослав инвайты тем, до кого добрался, и ожидая, пока хоть кто-то из знакомых их получит, сел разбираться с роботским апи.

Результатом разбирательств стал такой вот базовый робот: bakarobo@appsot.com, который умеет пока всего-ничего:
по команде !br:bor! достать случайную цитату с баша
по команде !br:rb! достать фото дня с rosbest
по команде !br:BakaRobo! откликнуться :)
и ругаться в ответ на все незнакомые команды.


И в процессе создания я понял забавную вещь: для Wave-роботов разработана большая, клевая API … Практически не документированная на текущий момент :) По крайней мере, референс по питоновской апи — это просто генеренный перечень классов и функций, из которого не понятно практически ничего.
И вот, потратив некоторое время на чтение разных доков и семплов, я, как мне кажется, выделил некоторый базовый набор информации, необходимой для того, чтобы сделать уже какого-то полезного робота. О всех этих нужных штуках я и хочу рассказать, может быть, не слишком хорошо структурировано :)
Начнем с того, что роботов размещать следует на Google App Engine. Как создать там приложение и скачать инструментарий для коммитов кода я рассказывать не буду — там все очень понятно объяснено.
Итак, мы скачали инструменты, и в некоей папке на диске у нас возникла примерно такая картинка:


.
..
google_appengine
our_robot


Где our_robot — папка, в которой будет наш робот. И вот в эту-то папку мы и скачиваем и распаковываем вот этот архивчик с code.google.com — это, собственно, питоновская апишка.
Теперь мы готовы к собственно разработке.
На всякий случай: коммит кода в аппенджин делается так:
python ./google_appengine/appcfg.py update ./our_robot/ — потом нас спрашивают о мыле и пароле и дают залить файло.

В базовом случае главных файлов в проекте будет три:

our_robot.py - собственно, код робота
app.yaml - нечто вроде манифеста
_wave/capabilities.xml - файлик, объявляющий эвенты, которые хочет слушать робот.

Питоновый API xml-ку кастати сам генерирует, на базе аргументов к robot.Robot, а вот для Java API надо писать ручками.

Так что, видимо, от некоторого количества телодвижений в процессе разработки можно отказаться.
Список эвентов можно посмотреть тут, но самые важные для робота, на мой взгляд, это:

WAVELET_SELF_ADDED — срабатывает, когда робота добавляют в волну, в этот момент неплохо показать маленькое инфо по использованию;
BLIP_SUBMITTED — срабатывает, когда создается/редактируется блип волны, причем не в момент написания текста, а когда уже жмякнута кнопка «Done».

Поехали дальше.

Манифест app.yaml выглядит, судя по туториалу на code.google.com, примерно так:

application: our_robot
version: 1
runtime: python
api_version: 1
handlers:
- url: /_wave/.*
script: our_robot.py
- url: /assets
static_dir: assets
- url: /icon.png
static_files: icon.png
upload: icon.png


Тут, вроде, все понятно. Название робота, версии, чем запускаем, версия апи и хендлеры для разных урлов.

Единственное, на что следует обратить внимание — это "-url: /icon.png" в разделе хендлеров. Этого, кажется, нету в туториале, конструкция позволяет задать способ обращения с иконкой робота. Рисуем ее в пнгшку, сохраняем в папку робота, объявляем внутри питоновского файла :)

capabilities.xml, опять же, по тутору, выглядит тоже незамысловато:

<?xml version="1.0" encoding="utf-8"?>
<w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0">
<w:capabilities>
<w:capability name="WAVELET_SELF_ADDED" content="true" />
<w:capability name="BLIP_SUBMITTED" content="true" />
</w:capabilities>
<w:version>1</w:version>
</w:robot>

Собственно, в этом файле и менять-то особо нечего: только номер версии да эвенты, которые мы хотим слушать.

А вот после того, как вся эта предварительная суматоха закончилась и начинается, собственно, довольно приятная возня с написанием питоновского кода робота.

Для начала я опишу общую структуру кода, как он приводится в примерах и туториале, а потом накидаю всяких минорных полезностей, которых в туториале нет, в референсе до них еще надо докопаться :), так что мне пришлось добывать их из примеров.

Итак, в общем и целом код болванки для робота выглядит примерно так:

from waveapi import events
from waveapi import model
from waveapi import robot
def OnRobotAdded(properties, context):
pass
def OnBlipSubmitted(properties, context):
pass
if __name__ == '__main__':
myRobot = robot.Robot('our_robot',
image_url='http://our_robot.appspot.com/icon.png', #иконка контакта для робота
version='2.3', #версия
profile_url='http://our_robot.appspot.com/') #адрес профиля контакта

# Назначаем события:
myRobot.RegisterHandler(events.WAVELET_SELF_ADDED, OnRobotAdded)
myRobot.RegisterHandler(events.BLIP_SUBMITTED, OnBlipSubmitted)
# Запуск
myRobot.Run()

И как бы вроде бы все замечательно и понятно. Но когда начинаешь писать собственно функции событий, понимаешь, что совершенно неясно, как, к примеру, заменить кусок текста на другой кусок текста, не говоря уже о том, чтобы что-нибудь покрасить или подчеркнуть.

В результате не слишком долгого, но довольно упорного ресерча я нарыл вот такой вот список полезных методов, которого мне хватило для написания робота:

Во-первых, чтобы в функциях обработки событий достать блип, с которым событие произошло (если, конечно, это событие произошло с блипом), используем

blip = context.GetBlipById(properties['blipId'])

Во-вторых, чтобы получить текст блипа и с ним оперировать, делаем

doc = blip.GetDocument()
contents = doc.GetText()


Соответственно, чтобы заменить некоторый кусок текста на другой, используем на полученный doc

doc.SetTextInRange(model.document.Range(НАЧАЛО, КОНЕЦ), НОВЫЙ_ТЕКСТ)

Чтобы вставить кусок текста в любое место:

doc.InsertText(НАЧАЛО, ТЕКСТ)

Чтобы добавить кусок текста в конец:

doc.AppendText(ТЕКСТ)

Чтобы вставить картинку:

В конец — doc.AppendElement(model.document.Image(АДРЕС_КАРТИНКИ, ШИРИНА, ВЫСОТА, ATTACHMENT_ID, АЛЬТ))

В определенное место — doc.InsertElement(НАЧАЛО, model.document.Image(АДРЕС_КАРТИНКИ, ШИРИНА, ВЫСОТА, ATTACHMENT_ID, АЛЬТ))

В общем, полезно посмотреть вот этот референс для того, чтобы узнать, что можно делать с документом. Для того, чтобы узнать виды элементов, которые можно создавать, смотрим референсы по waveapi.document.* — там есть и Image, и Link и даже Gadget.

Дальше. Все оформление и разные другие полезности блипа хранятся в так называемой аннотации. С ней все просто:
doc.SetAnnotation(model.document.Range(НАЧАЛО, КОНЕЦ), ТИП, ЗНАЧЕНИЕ)

Причем ТИП — это штука, которая описывает, что за аннотацию мы добавляем. Самый важный, имхо, это 'style/STYLE_PROP', где STYLE_PROP — это запись css атрибута в js виде.

Вдруг кто не знает — это трансформированная запись свойств css, используемая в js-скриптах, показать ее суть проще на примерах :) Например, color — это просто color, а вот font-size — это fontSize. В смысле, там, где в css дефис, в этой записи дефиса нет, но каждое слово кроме первого начинается с большой буквы. backgroundColor, backgroundImage, marginTop, и так далее.

Убираются они так же незамысловато, можно тупо убить все аннотации одного типа, например, про цвет шрифта, или цвет фона, вот такой функой:

doc.DeleteAnnotationsByName(ТИП)

А можно почистить от аннотаций определенного типа только некоторый диапозон текста:

doc.DeleteAnnotationsInRange(model.document.Range(НАЧАЛО, КОНЕЦ), ТИП)

Аннотации полезны еще тем, что в них можно хранить любую инфу, которая относится к этому блипу.

Чтобы аннотировать блип целиком, используем:

doc.AnnotateDocument(ТИП, ЗНАЧЕНИЕ)

Чтобы узнать, есть ли в блипе какой-то тип аннотации, вызывается

doc.HasAnnotation(ТИП)

Вот где-то такой набор, как мне кажется, уже позоляет создавать роботов, которые могут делать нечто полезное. Конечно, за рамками текста осталось, например, применение GAE системы баз данных и прочие приятные вещи, но, надеюсь, текст не будет полностью бесполезен.

Оригинал: Хабрахабр
Автор: Алексей Ничипоренко

четверг, 15 октября 2009 г.

Расширение Firefox для работы с Google Wave

Неофициальное расширение Firefox позволяющее следить за активностью в Google Wave. Может быть полезно для тех кто уже пользуется Wave и хочет получать уведомления о новых сообщениях.

Оно создано на основе Google Voice Add-on for Firefox и хоть функционала пока мало, но уже хорошо, что люди всё больше и больше разрабатывают для Google Wave.

Использование простое. Скачиваем само расширение Google Wave Add-on for Firefox (всего 9 кб) и у вас в правом нижнем углу появится иконка Wave. Там будет отображаться количество новых сообщений.

google-wave-notifier

Автор обещает работоспособность только для пользователей wave.google.com

Взято с http://thatsmith.com/2009/10/google-wave-add-on-for-firefox

вторник, 13 октября 2009 г.

Клиент для Google Wave в виде Java Web Application

Итак, я написал небольшой проект на Java, который представляет собой клиент к Google Wave, который, в свою очередь, вы можете расширить необходимыми вам возможностями. Визуально выглядит он не очень презентабельно (впрочем, а-ля Windows 3.11, почему бы и нет), поскольку веб-дизайнер из меня не очень хороший, однако абсолютно за весь исходный код я отвечаю головой :). Так, например, требующиеся для отображения CSS-стили при этом выглядят максимально понятно, а XHTML-структура максимально упрощена (не в ущерб стандартам) для того, чтобы настоящий дизайнер мог развернуться и сделать действительно красиво :).
sametimed в работе
Сайт, исходные коды, и war-пакет с текущим состоянием проекта находятся по адресу http://code.google.com/p/sametimed
Сейчас у меня нет под рукой общедоступного хостинга, чтобы я мог прямо вот так запустить проект и дать поиграться с ним не отходя от хабра, однако, я могу предложить вам видео (на vimeo), демонстирующее его основные возможности, что, думаю, тоже вполне ничего, а запустить проект вы сможете сами, благо подробные инструкции есть на сайте проекта, а развёрнутые пояснения и подробное описание работы (и руководство к расширению возможностей) — внутри…

Sametimed b0.1 Work Demonstration (HD) from Ulric Wilfred on Vimeo.

Установка
Для того, чтобы запустить этот клиент, нужно, по идее, четыре вещи:

Чуть более подробные инструкции как его запустить сам по себе или в виде рабочего проекта для Eclipse представлены на странице проекта. Здесь же я рассмотрю структуру кода и опишу как он действует (пока без что UML-диаграмм, извините, по мере возможности я их добавлю).
Общая концепция

Здесь под сочетанием «серверная сторона/часть» подразумевается не сервер wave-protocol, а серверная строна веб-приложения.
Поскольку в wave-protocol сейчас существует только консольный клиент, релизованный в виде jar-приложения, основной вопрос состоит в своевременной передаче информации с клиента на серверную часть и наоборот.
Посему стало необходимо ввести два понятия:
  • Команда: отправляется с клиента на сервер, требует «открыть волну», «добавить участника», «отменить действие», «сказать привет» и т.п., отправляется по действию пользователя.
  • Сообщение: отправляется с сервера на клиент, сообщает о том, что «кто-то пригласил в волну», «sonya ответила привет», «добавился участник», «произошла ошибка», отправляется при любом обновлении.

При этом, команду с клиента можно отправить сразу, сильно не задумываясь о нагрузке на сервер, а вот сообщения об обновлениях требуется отсылать только по факту происшествия. Однако, на клиенте находится javascript, который без сложных приспоcоблений не может осуществлять такие вещи. Здесь потребовался Reverse Ajax, вернее его реализация для Java — библиотека DWR (Direct Web Remoting), она позволяет вызывать функцию на клинете с сервера в тот момент, когда решит сервер, а не клиент. Их сайт рассказывает о всех возможностях, которые вовсе не ограничены данным применением, но для проекта, как я уже сказал, из всех возможностей я использовал только эту.
Команды и сообщения передаются в виде XML, а содержимое сообщений об обновлениях в виде JSON, засчёт чего в построении интерфейса участвует только Javascript (я использовал JQuery), а серверная сторона даже не задумывается о существовании UI.
(для серверной стороны в проекте есть интерфейс Renderer, реализация которого вызывается при необходимых обновлениях, но он предназначен как раз для случаев вроде консольного клиента)
Описание процесса, происходящего в текущей версии

При запуске клиента, вы видите страницу с полем для ввода юзернейма и единственной кнопкой. Wave-protocol сервер при этом должен быть запущен. При нажатии на кнопку введённый вами юзернейм передаётся в сервлет (GetClientViewServlet), который подключает вас «к волне», и возвращает всю структуру (модель) клиента в виде JSON. JQuery на клиентской стороне строит весь интерфейс вейвлета. Если вы нажмёте кнопку ещё раз, вы запросите ещё один вейвлет, при этом между собой они будут различаться по внутреннему ID (сгенерированному автоматически), указанному на синей полоске в скобках. По этому ID и сервер и клиент определяют, к какому клиенту относится команда и/или сообщение.
Одновременно с этим DWR начинает ожидать вестей об обновлениях, а вы в это время можете ввести любую из доступных команд в поле консоли и нажать «send». Например, создать волну командой «\new», открыть её командой «\open <id>» и что-нибудь сказать, набрав просто текст (как в скайпе). При нажатии на кнопку «send» отправляется POST-запрос к другому сервлету (CommandsReceiverServlet), который получает сгенерированную в виде XML команду и тут же её выполняет, передавая данные серверу wave-protocol.
Обновления в данный момент приходят с серверной стороны (и от сервера wave-protocol) в виде XML-сообщения (на клиентской стороне есть обработчик, который вызывается при получении новых сообщений), в котором содержится алиас изменившейся модели (например, «chat», «inbox», «userslist», «errors» или «editor») и её содержимое в виде JSON, которое тут же обрабатывается и обновляет соответствующую часть вейвлета.
Как видите, всё до невозможности просто.
Структура проекта и возможности для расширения
Java:
  • name.shamansir.sametimed.wave Все классы, лежащие «снаружи» и относящиеся к клиенту непосредственно; здесь находятся абстрактные классы AUpdatingWavelet и ADocumentsWavelet — определяющие структуру соответствующего типа вейвлетов (обновляющийся вейвлет и его расширение, вейвлет содержащий документы). Класс SimpleWavelet служит примером такой реализации. Класс WavesClient занимается обработкой команд и именно он возвращает модель содержащегося в нём вейвлета в GetClientViewServlet.
  • name.shamansir.sametimed.wave.messaging Все, что относится к командам и сообщениям. Идентификаторы команд/сообщений в CommandID/MessageTypeID, сами классы Command и UpdateMessage, сервлет-обработчик CommandsReceiverServlet.
  • name.shamansir.sametimed.wave.model Классы, описывающие модель вейвлета. Они содержат описание каждой суб-модели, вроде списка участников, чата или текстового документа. И ModelID, описывающий возможные модели с абстрактным классом AModel, конечно. Плюс, ModelFactory, фабрика моделей.
  • name.shamansir.sametimed.wave.model.base Значения моделей, вроде «набора строк чата», «набора блоков текста в документе», «списка доступных волн» и т.д. Именно в этих классах описывается преобразование в JSON.
  • name.shamansir.sametimed.wave.model.base.atom То, из чего состоят значения, если это необходимо для их структуры — «строка чата», «блок текста», «идентификатор волны»
  • name.shamansir.sametimed.wave.model.base.chat Вейвлет с функцией чата и клиент для него
  • name.shamansir.sametimed.wave.model.base.editor Вейвлет с поддержкой редактируемого документа, на данный момент не имплементирован, поэтому отключен
  • name.shamansir.sametimed.wave.render Классы, относящиеся к рендерингу Здесь находится тот самый класс JSUpdatesListener, который средствами DWR вызывает функцию обновления на клиенте.

Самый логичный способ расширения — имплементация класса ADocumentsWavelet или расширение класса WaveletWithChat. Поскольку, в наиболее вероятном случае, вы будете оперировать понятием «документ» (А чат или что-либо другое, как раз являются документами), то именно такой способ должен подойти вам лучше всего. Также вам понадобится задуматься о модели данного документа (создав соответсвующий тип, реализующий AModel, добавить id модели в тип ModelID и генерацию модели в ModelFactory).
Если документ не будет обрабатывать какие-либо новые команды, то этого достаточно — можно заменить в GetClientViewServlet возвращаемый вейвлет на ваш собственный и вуаля!.. Ах, да, ещё генерация UI на клиенте, но об этом ниже.
Если же необходимы свои собственные, предназначенные сугубо для него команды, то необходимо добавить соответствующие команды в тип CommandID. После этого нужно расширить класс WavesClient для поддержки вашего вейвлета и для того, чтобы он обрабатывал и передавал новые команды вейвлету независимо от предка. И, в этом случае, заменить в GetClientViewServlet реализацию WavesClient на вашу собственную. И снова вуаля! (снова, не учитывая UI)
Вам понадобится, конечно же, учесть пару тонкостей при написании обработки команд, но в общих чертах это весь необходимый процесс для расширения функциональности клиента.
Javascript
  • ui.js занимается генерацией интерфейса, для каждого блока модели есть собственный метод
  • command.js отправляет и генерирует команды, принимает сообщения об обновлениях, а также содержит обработчики для кнопок
  • ajax.js скрипт, который давно пора заменить на соответствующий метод jquery, но никак не доходят руки :). используется в command.js

Для того, чтобы добавить генерацию вашей модели, достаточно добавить строку, вызывающую ваш метод обработки в методы CreateClient и renderUpdate объекта ClientRenderer в ui.js и собственно написать этот метод. Всё остальное будет (должно) работать самостоятельно.
CSS
  • sametimed-plain.css ещё чуть более ужасный интерфейс чем цветной :)
  • sametimed-colored.css цветной, Windows 3.11-подобный интерфейс :).

Пока что стили, определяющие позиционирование и внешний вид (цветность) не разделены, хотя они разделяются комментариями в самих файлах. Думаю, я не буду этого менять.
Эпилог

Вышло много текста про один небольшой аппликейшн, но зато пост описывает все его возможности. Надеюсь найдётся не один человек, которому эта разработка будет интересна и если найдётся, планирую усовершенствовать его дальше. Пока это небольшая поделка «из интереса», но немного стараний — и её можно превратить в полноценный проект.
Тех, кто это будет тестировать, прошу постить баги в соответствующее место, в разумных пределах и не относящиеся к дизайну :).
Участие в разработке приветствуется но поощрить нечем, только лицензией :).

 

Взято: http://habrahabr.ru/blogs/google/72235/ by zokotuhaFly

Раздача инвайтов?

Сегодня целый день в твиттере стоит шум! И шум этот связан с раздачей инвайтов в Google Wave.

fake

Я тоже обратил внимание и что могу вам сказать – ИМХО это фейк. Во-первых смутил домен http://www.google.com-wave.info/ Google никогда бы не зарегистрировали такой домен. Во-вторых сам сайт – просто одна страничка, на которой нам предлогают ввести свой твиттер аккаунт и электронную почту.

Думаю, что это не просто фейк, а именно сайт, созданный для сбора адресов и тветтеров, что бы потом их спамить.

Будьте внимательны к сайтам такого рода!
Для подтверждения информации всегда обращайтесь к оффициальным источникам.

А инвайт на Google Wave скоро получат многие из вас! Не будем торопить события.

вторник, 6 октября 2009 г.

Google Wave на Android

Решил показать, как же выглядят волны на устройстве Android.

Google Wave на Android

Во-первых мы видим, что отображается корректно и понятно.

Google Wave на Android - Waves

После того, как мы перешли на сайт, то видим список волн.

Google Wave на Android - Contacts

Контакты в принципе тоже не отличются от PC\Mac версии

Google Wave на Android - In Wave

Внутри самой волны.

Google Wave на Android - in Wave 2

Навигация по волне.

Так как это тестировал не я, то немного не понятно – а где же у нас список папок, сохранёные поиски?

Так же минус – нет индикторов колличества новых сообщений. Когда мы внутри волны, мы ведь не можем скакать то к списку волн, то внутрь волны. Ноя думаю всё это подправят. Плюс к тому же ходят слухи, что начали разработку специализированного клиента под Android устройства.

Осталось совсем немного и он выйдет в свет… Эх-эх-эх….