Статьи

Создание приложения чата с помощью node-webkit, Firebase и AngularJS

В этом посте мы собираемся создать настольное приложение для чата с именем vTak . Мы будем использовать node-webkit для поддержки основного настольного приложения и Firebase в качестве хранилища данных в реальном времени. Мы будем использовать генератор слякоти с именем slush-wean для создания базового приложения node-webkit / Express / Angular. Конечный продукт будет выглядеть примерно так:

Скриншот приложения

Prerequistes

Если вы новичок в node-webkit, пожалуйста, обратитесь к следующим ресурсам:

Node Webkit — Создание настольных приложений с использованием Node и веб-технологий
Приложение Dashboard для Node Webkit
Node webkit и Angularjs — Приложение MovieStub

Если вы новичок в Firebase, вы должны проверить следующие ресурсы:

Начало работы с Firebase

Я бы рекомендовал использовать Sublime text при работе с приложениями node-webkit. Обратитесь сюда для получения дополнительной информации.

Приложение

Как упоминалось ранее, мы собираемся создать приложение чата с именем vTak с помощью node-webkit, Firebase и Angular. vTak позволит пользователям войти в систему, зарегистрировавшись или используя провайдеров социальной аутентификации, таких как Twitter, Google и Facebook. Для этого мы будем использовать простой вход в Firebase. Как только пользователь войдет в систему, мы покажем список чатов, в которые нужно вступить. Как только пользователь выберет комнату, мы подключим его к этой комнате и получим все сообщения чата. Затем пользователь может начать общаться.

Начиная

Чтобы создать базу приложения, мы собираемся использовать генератор slush-wean именем slush-wean . Это создаст для нас базовое приложение node-webkit с интеграцией Express и Angular.

Создайте новую папку с именем vTak и откройте новый терминал / приглашение здесь. Сначала мы установим gulp , slush и slush-wean глобально, используя следующую команду:

 $ npm i -g gulp slush slush-wean 

Чтобы выложить приложение на отъём, запустите slush wean . Завершите строительные работы, указав название проекта как vTak . Slush потребуется время, чтобы настроить проект и загрузить необходимые зависимости. Чтобы запустить приложение, выполните gulp run .

gulp run будет запускать node-webkit-builder для извлечения библиотек, необходимых для запуска приложения node-webkit, поэтому вам не нужно об этом беспокоиться. Это однократный процесс, который займет до 5 минут. После завершения загрузки приложение dekstop запустится.

Когда приложение запустится, вы увидите заставку в течение примерно 3 секунд, а затем появится домашняя страница. Если вы извлекаете проект scaffolded, вы должны увидеть следующую структуру:

 . ├── app.js ├── gulpFile.js ├── index.html ├── package.json ├── public │ ├── css │ │ ├── app.css │ │ └── bootstrap.css │ ├── fonts │ │ ├── ... │ ├── js │ │ └── app.js │ ├── lib │ │ ├── angular-resource.min.js │ │ ├── angular-route.min.js │ │ ├── angular.min.js │ │ ├── bootstrap.min.js │ │ └── jquery.min.js │ └── partials │ └── head.html ├── routes │ └── index.js └── views └── index.ejs 

Краткий обзор:

  • app.js : экспресс-настройка сервера
  • gulpFile.js : исполнитель задач
  • index.html : главная страница приложения / заставка
  • общая папка: статические ресурсы (на стороне клиента — наше приложение будет разрабатываться здесь)
  • маршруты : экспресс-маршруты
  • view : начальный вид для нашего приложения Angularjs, обслуживаемого Express

Наш первый шаг — настроить аутентификацию. Чтобы этот пост был простым, я написал еще один пост под названием node-webkit и Firebase — Простая и социальная аутентификация . Вы можете следить за публикацией, чтобы интегрировать аутентификацию с нашим приложением node-webkit.

Я буду продолжать с вывода вышеупомянутого поста. Вы можете создать приложение из приведенного выше поста или клонировать папку ng-auth из этого репозитория . Как только вы клонируете / загрузите репозиторий, очистите содержимое папки vTak и скопируйте содержимое ng-auth в vTak .

Примечание: мы собираемся использовать версию Angular из вышеприведенного поста.

Как только вы скопируете содержимое, запустите npm i для установки зависимостей. Затем откройте gulpFile.js и прокомментируйте / раскомментируйте задачи в соответствии с вашей ОС. Наконец, откройте /public/js/controllers.js и обновите строку 5 следующим образом:

 var ref = new Firebase('https://nwkchatapp.firebaseio.com/'); 

При желании вы можете настроить собственную учетную запись Firebase. Какой бы подход вы ни использовали, ваша окончательная структура проекта должна быть:

Структура каталога проекта

И когда вы запустите приложение ( gulp run ), вы должны увидеть следующий экран входа в систему.

Экран входа

Продолжить развитие

Вы можете обновить имя приложения до vTak в index.html и package.json .

Далее мы загрузим необходимые файлы Firebase. Загрузите firebase.js , angularfire.min.js и firebase -simple-login.js и поместите их в папку public/lib .

Обновите views/index.ejs как показано ниже.

 <!DOCTYPE html> <html ng-app="ng-auth"> <head> <title>vTak</title> <link rel="stylesheet" href="css/bootstrap.css"> <link rel="stylesheet" href="css/app.css"> <script src="lib/angular.min.js"></script> <script src="lib/angular-route.min.js"></script> <script src="lib/angular-resource.min.js"></script> <script type="text/javascript" src="lib/firebase.js"></script> <script type="text/javascript" src="lib/firebase-simple-login.js"></script> <script type="text/javascript" src="lib/angularfire.min.js"></script> <script type="text/javascript" src="lib/jquery.min.js"></script> <script type="text/javascript" src="lib/bootstrap.min.js"></script> <script src="js/app.js"></script> <script src="js/factory.js"></script> <script src="js/controllers.js"></script> <script src="js/directives.js"></script> </head> </head> <body> <div class="container" ng-controller="AppCtrl"> <div ng-include src="'partials/head.html'"></div> <hr/> <ng-view></ng-view> </div> </body> </html> 

Теперь немного очистим домашнюю страницу приложения (страницу, на которую пользователь направляется после входа в систему). Откройте public/partials/head.html и обновите его, как показано ниже:

 <div class="header" ng-controller="Toolbar"> <div class="btn-group pull-right"> <a href="#" class="btn btn-xs btn-default" ng-show="user" ng-click="logoutUser()">Logout</a> <button ng-click="minimize()" type="button" class="btn btn-default btn-xs"> <span class="glyphicon glyphicon-minus"></span> </button> <button ng-click="toggleFullscreen()" type="button" class="btn btn-default btn-xs"> <span class="glyphicon glyphicon-fullscreen"></span> </button> <button ng-click="close()" type="button" class="btn btn-default btn-xs"> <span class="glyphicon glyphicon-remove"></span> </button> </div> <h1>vTak</h1> </div> 

Мы переместили кнопку выхода из тела страницы в верхний колонтитул рядом со значками действий окна.

Затем откройте public/js/controllers.js и обновите AppCtrl как показано ниже:

 ngAuth.controller('AppCtrl', function($rootScope, $scope, $window, $firebaseSimpleLogin) { $rootScope.URL = 'https://nwkchatapp.firebaseio.com/'; var ref = new Firebase($rootScope.URL); $rootScope.authClient = $firebaseSimpleLogin(ref); $rootScope.redirect = function(user) { if ($window.location.href.indexOf('home') < 0) $window.location.assign('http://localhost:3000/#home'); if (user.provider == 'password') { user.name = user.email; user.img = '/img/user.png' } else if (user.provider == 'facebook') { user.name = user.displayName; user.img = user.thirdPartyUserData.picture.data.url; } else if (user.provider == 'twitter') { user.name = user.displayName; user.img = user.thirdPartyUserData.profile_image_url; } else if (user.provider == 'google') { user.name = user.displayName; user.img = user.thirdPartyUserData.picture; } $rootScope.user = user; }; $rootScope.$on('$firebaseSimpleLogin:login', function(e, user) { if (user) { $rootScope.redirect(user); } }); } ) 

В этом коде есть два изменения. Сначала мы переместили URL-адрес Firebase в переменную. Во-вторых, мы объединили имя пользователя и изображение объекта пользователя для нескольких поставщиков услуг. Вы можете скачать изображение пользователя здесь .

Далее мы переместим функцию выхода из системы в контроллер Toolbar . Обновите контроллер Toolbar в public/js/controllers.js следующим образом:

 controller('Toolbar', ['$rootScope', '$scope', 'Window', function($rootScope, $scope, Window) { $scope.minimize = function() { Window.minimize(); }; $scope.toggleFullscreen = function() { Window.toggleKioskMode(); }; $scope.close = function() { Window.close(); }; $scope.logoutUser = function() { $rootScope.user = ''; $rootScope.authClient.$logout(); }; } ]) из controller('Toolbar', ['$rootScope', '$scope', 'Window', function($rootScope, $scope, Window) { $scope.minimize = function() { Window.minimize(); }; $scope.toggleFullscreen = function() { Window.toggleKioskMode(); }; $scope.close = function() { Window.close(); }; $scope.logoutUser = function() { $rootScope.user = ''; $rootScope.authClient.$logout(); }; } ]) 

Если вы перезапустите приложение сейчас, после входа в систему вы увидите, что выход logout перемещен вверх. В центре страницы вы также увидите выход из системы, с которым мы вскоре разберемся.

Теперь мы будем работать на домашней странице. Когда пользователь входит в vTak, мы показываем ему список комнат чата, и мы предоставляем возможность создать одну из своих комнат. Мы обновим разметку public/partials/home.html как показано ниже:

 <div class="container" ng-controller="HomeCtrl"> <label class="pull-right welcome-panel" ng-show="user"> Welcome, <u> <span id="email">{{user.name}}</span></u> <img class="prof-img" ng-src="{{user.img}}" width="39" /> </label> <br/> <h3 class="room-head">Chat Rooms <a href="javascript:" class="btn btn-xs btn-primary" ng-hide="isNew == true" ng-click="isNew = true; roomName = ''; ">New Room</a> <input ng-show="isNew == true" class="input-sm form-control cust-text" type="text" ng-model="roomName" placeholder="Room Name" /> <a href="javascript:" ng-disabled="!roomName" ng-show="isNew == true" class="btn btn-xs btn-info" ng-click="newRoom()">Create</a> </h3> <input type="text" class="form-control" placeholder="Search Rooms" ng-model="search"> <div class="rooms"> <div ng-repeat="item in rooms | filter:search" class="room"> <h3>{{item.roomname}}</h3>By : {{item.createdby}} <a class="btn btn-primary btn-xs pull-right join-room" href="javascript:" ng-click="joinChat($index)">Join</a> <a class="btn btn-danger btn-xs pull-right" ng-show="user.name == item.createdby" ng-click="deleteRoom($index)">Delete</a> </div> <div class="room" ng-show="rooms.length == 0"> <h3>No Rooms Available. Create your own!</h3> </div> </div> </div> 
  • В одной строке 2 мы показываем отображаемое имя пользователя и изображение профиля. Мы собрали эту информацию в AppCtrl только пользователь вошел в систему.
  • В строке 8 мы предоставляем кнопку для создания новой комнаты. Когда пользователь нажимает на нее, мы скрываем кнопку создания, отображаем текстовое поле и кнопку сохранения. Как только пользователь сохранит комнату, он появится в списке, заполненном в строке 16.
  • В строке 14 у нас есть панель поиска, где пользователь может искать доступные номера.
  • Также обратите внимание на строку 19. Если текущий зарегистрированный пользователь совпадает с пользователем, который создал комнату, мы показываем кнопку удаления.

HomeCtrl внимание, что весь связанный код JavaScript будет обрабатываться в HomeCtrl . Откройте public/js/controllers.js и перейдите в самый низ, чтобы найти HomeCtrl . Обновите его, как показано ниже:

 .controller('HomeCtrl', function($rootScope, $scope, $firebase, $location) { var ref = new Firebase($rootScope.URL + 'chatRooms'); var sync = $firebase(ref); $scope.rooms = sync.$asArray(); $scope.newRoom = function() { sync.$push({ createdby: $rootScope.user.name, roomname: $scope.roomName, createddate: Date.now() }); $scope.isNew = false; }; $scope.deleteRoom = function(room) { sync.$remove($scope.rooms[room].$id); }; $scope.joinChat = function(room) { $location.path('/chat/' + $scope.rooms[room].$id); }; }) 
  • Строка 2 — Мы создаем новую ссылку на chatRooms и синхронизируем ее в строке 3.
  • Строка 4 — Мы запрашиваем хранилище данных Firebase и заполняем все комнаты, перечисленные в chatRooms в виде массива.
  • Строка 8 — Когда пользователь создает новую комнату, мы используем метод push, чтобы сохранить необходимые данные.
  • Строка 15 — когда пользователь удаляет комнату
  • Строка 19 — Когда пользователь хочет присоединиться к комнате, мы перенаправляем его на новый путь. ( который мы скоро создадим )

Наконец, добавьте необходимые стили. Откройте public/css/app.css и добавьте следующие классы:

 body { overflow-x: hidden; } .room-head { margin-top: -35px; border-bottom: 2px solid #CCC; padding: 20px 20px 8px; } .prof-img { vertical-align: bottom; } .welcome-panel { padding-right: 20px; } .cust-text { width: 22%; display: initial; vertical-align: middle; margin-left: 11px; } .rooms,.messages { border: 1px solid #e8e7e8; margin: 20px; } .room { border: 1px solid #c7c7c7; margin-bottom: -1px; background: #fff; -webkit-transition: background .5s; padding: 10px; } .room:hover { background: #e6e6e6; } .join-room { margin-left: 5px; } .messages { height: 377px; overflow: auto; border: 1px solid #e8e7e8; } .message { border-bottom: 1px solid #c7c7c7; background: #fff; height: 75px; -webkit-transition: background .5s; padding: 3px 3px 3px 10px; } .message img { vertical-align: baseline; margin-right: 9px; } .chat-input { position: absolute; bottom: 0; width: 93%; text-align: center; margin-bottom: 14px; padding-left: 8px; } .back-btn { vertical-align: bottom; margin-left: 20px; } 

Сохраните все файлы и перезапустите приложение. Если вы не вышли из системы в последний раз, наша логика аутентификации позаботится о перенаправлении на домашнюю страницу. Вы можете нажать кнопку «Новая комната» button and create a new room . Недавно созданная комната автоматически появится в списке ниже.

Если вы хотите отладить приложение, вы можете установить для toolbar и frame значение true в package.json .

Теперь, когда мы создали новую комнату, давайте напишем логику, чтобы присоединиться к комнате и начать общаться со всеми пользователями в ней. Для этого мы создадим новый маршрут. Откройте public/js/app.js и добавьте следующий маршрут:

 $routeProvider.when('/chat/:roomid', { templateUrl: 'partials/chat.html', controller: 'ChatCtrl' }); 

Затем создайте новый файл с именем chat.html в папке public/partials . Этот файл имеет шаблон для просмотра чата. Обновите его, как показано ниже:

 <div class="container" ng-controller="ChatCtrl"> <label class="pull-right welcome-panel" ng-show="user"> <a href="/#/home" class="btn btn-info btn-xs back-btn">Back</a> Welcome, <u> <span id="email">{{user.name}}</span></u> <img class="prof-img" ng-src="{{user.img}}" width="39" /> </label> <br/> <h3 class="room-head">Welcome to {{roomInfo.roomname}}</h3> <div class="messages" scroll-glue> <div ng-repeat="msgs in chatMessages" class="message"> <h4> <img ng-src="{{msgs.userimg}}" width="20" />{{msgs.message}} </h4> <span>{{msgs.postedby}} <small class="text-muted">{{msgs.posteddate | date:'yyyy-MM-dd HH:mm:ss'}}</small> </span> </div> <div class="message" ng-show="chatMessages && chatMessages.length == 0"> <h4>No message yet!</h4> </div> </div> <div class="chat-input"> <input type="text" class="form-control" placeholder="Send Message" ng-model="message" ng-keypress="sendMessage($event)" autofocus> </div> </div> 

На что обратить внимание:
Строка 12 — будет содержать все сообщения. Обратите внимание на директиву scroll-glue , которая позаботится об автоматической прокрутке панели чата до последнего сообщения. ( Мы добавим и включим эту ссылку через мгновение )
Строка 26 — поле ввода для ввода сообщения.

Теперь загрузите скролл-склейк отсюда и поместите его в папку public/lib . Затем обновите зависимости модуля public/js/app.js как показано ниже.

 var ngAuth = angular.module('ng-auth', ['ngRoute', 'ngResource', 'firebase', 'luegg.directives']).config(['$routeProvider', function($routeProvider) { $routeProvider.when('/', { templateUrl: 'partials/auth.html', controller: 'AuthCtrl' }); $routeProvider.when('/home', { templateUrl: 'partials/home.html', controller: 'HomeCtrl' }); $routeProvider.when('/chat/:roomid', { templateUrl: 'partials/chat.html', controller: 'ChatCtrl' }); $routeProvider.otherwise({ redirectTo: '/' }); } ]); 

Обновите views/index.ejs для включения scrollglue.js :

 <script type="text/javascript" src="lib/scrollglue.js"></script> 

В public/js/controllers.js мы добавим логику для управления чатом. Добавьте следующий код в конец всех контроллеров:

 .controller('ChatCtrl', function($rootScope, $scope, $firebase, $routeParams) { // get room details var chatRoom = new Firebase($rootScope.URL + 'chatRooms/' + $routeParams.roomid); var roomSync = $firebase(chatRoom); $scope.roomInfo = roomSync.$asObject(); var msgsSync = $firebase(chatRoom.child('chatMessages')); $scope.chatMessages = msgsSync.$asArray(); $scope.sendMessage = function($event) { if (!($event.which == 13)) return; if ($scope.message.length == 0) return; msgsSync.$push({ postedby: $rootScope.user.name, message: $scope.message, posteddate: Date.now(), userimg: $rootScope.user.img }); $scope.message = ''; }; }); 

На что обратить внимание:
Строка 3 — мы создаем новую ссылку Firebase на чат
Строки 4 и 5 — мы создаем ссылку AngularFire и затем синхронизируем ее как объект
Строка 7 — мы создаем ссылку на объект чата внутри чата
Строка 8 — мы синхронизируем / выбираем все сообщения
Строка 14 — мы отправляем сообщение чата на сервер с некоторыми дополнительными данными.

Сохраните все файлы и запустите приложение. Теперь, когда вы нажмете на кнопку «Присоединиться», вы увидите новое созданное нами представление. Добавьте новое сообщение, и вы увидите обновление окна чата. Если вы хотите проверить чат, ( с запущенным приложением vTak ) откройте браузер и перейдите по http://localhost:3000 . Войдите с поставщиком услуг, таким же или отличным от того, который вы уже вошли, и вы можете общаться с самим собой.

Просто и легко!

Распространение приложения

Вы можете создавать собственные установщики и распространять приложение. Выполните следующую команду для сборки установщика OSX:

 $ gulp build-osx 

Или создайте установщик Windows с помощью следующей команды:

 $ gulp build-win 

Или создайте установщик Linux с помощью следующей команды:

 $ gulp build-linux 

Вывод

Надеюсь, у вас есть основная идея о том, как создать комплексное приложение, используя node-webkit и Firebase. Вы можете найти полный код этой статьи на GitHub .

Спасибо за прочтение. Комментарии приветствуются.