Browse Source

Merge commit '736096161798b48df74c497736e75a0b68fd805d' into theurere-sass-libs-branch

Conflicts:
	src/styles/components/_audiovideo.scss
	src/styles/global/_base.scss
	src/styles/global/_variables.scss
	src/styles/main.scss

Merge from 7360961617.
pull/29/head
Evan Theurer 12 years ago
parent
commit
7ddc562c4d
  1. 4
      .gitignore
  2. 9
      Makefile
  3. 18
      debian/changelog
  4. 4
      html/main.html
  5. 8
      server.conf.in
  6. 1
      src/app/spreed-speakfreely-server/api.go
  7. 1
      src/app/spreed-speakfreely-server/buffercache.go
  8. 1
      src/app/spreed-speakfreely-server/config.go
  9. 1
      src/app/spreed-speakfreely-server/connection.go
  10. 1
      src/app/spreed-speakfreely-server/context.go
  11. 7
      src/app/spreed-speakfreely-server/hub.go
  12. 23
      src/app/spreed-speakfreely-server/images.go
  13. 13
      src/app/spreed-speakfreely-server/main.go
  14. 1
      src/app/spreed-speakfreely-server/random.go
  15. 1
      src/app/spreed-speakfreely-server/rooms.go
  16. 1
      src/app/spreed-speakfreely-server/roomworker.go
  17. 1
      src/app/spreed-speakfreely-server/server.go
  18. 1
      src/app/spreed-speakfreely-server/stats.go
  19. 18
      src/app/spreed-speakfreely-server/tokenprovider.go
  20. 1
      src/app/spreed-speakfreely-server/tokens.go
  21. 1
      src/app/spreed-speakfreely-server/user.go
  22. 21
      src/app/spreed-speakfreely-server/ws.go
  23. 1
      src/app/spreed-speakfreely-server/wsdata.go
  24. 25
      src/i18n/messages-ja.po
  25. 100
      src/styles/color-pallete.html
  26. 327
      src/styles/components/_audiovideo.scss
  27. 319
      src/styles/components/_bar.scss
  28. 179
      src/styles/components/_webrtc.scss
  29. 1
      src/styles/global/_base.scss
  30. 23
      src/styles/global/_mixins.scss
  31. 66
      src/styles/global/_variables.scss
  32. 5
      src/styles/main.scss
  33. 7
      static/js/app.js
  34. 4
      static/js/controllers/mediastreamcontroller.js
  35. 2
      static/js/controllers/roomchangecontroller.js
  36. 93
      static/js/directives/audiovideo.js
  37. 4
      static/js/mediastream/peerconference.js
  38. 19
      static/js/mediastream/webrtc.js
  39. 2
      static/js/services/fileupload.js
  40. 74
      static/js/services/videolayout.js
  41. 22
      static/partials/audiovideo.html
  42. 6
      static/partials/audiovideopeer.html
  43. 2
      static/translation/messages-ja.json

4
.gitignore vendored

@ -24,3 +24,7 @@ vendor/* @@ -24,3 +24,7 @@ vendor/*
/.sass-cache
/extra
/src/i18n/*.mo
server.key
server.csr
server.crt
server.pem

9
Makefile

@ -20,8 +20,8 @@ @@ -20,8 +20,8 @@
PKG := app/spreed-speakfreely-server
EXENAME := spreed-speakfreely-server
CONFIG_FILE := spreed-speakfreely-server.conf
CONFIG_PATH := /etc
CONFIG_FILE ?= spreed-speakfreely-server.conf
CONFIG_PATH ?= /etc
VENDOR = "$(CURDIR)/vendor"
GOPATH = "$(VENDOR):$(CURDIR)"
@ -63,6 +63,9 @@ binary: @@ -63,6 +63,9 @@ binary:
binaryrace:
GOPATH=$(GOPATH) go build -race -o $(OUTPUT)/$(EXENAME) -ldflags '$(LDFLAGS)' $(PKG)
binaryall:
GOPATH=$(GOPATH) go build -a -o $(OUTPUT)/$(EXENAME) -ldflags '$(LDFLAGS)' $(PKG)
fmt:
GOPATH=$(GOPATH) go fmt app/...
@ -154,4 +157,4 @@ tarball: distclean release install @@ -154,4 +157,4 @@ tarball: distclean release install
echo -n $(VERSION) > $(TARPATH)/version.txt
tar czf $(DIST)/$(PACKAGE_NAME).tar.gz -C $(DIST) $(PACKAGE_NAME)
.PHONY: clean distclean pristine get build styles javascript release releasetest dist_gopath install gopath binary tarball assets
.PHONY: clean distclean pristine get build styles javascript release releasetest dist_gopath install gopath binary binaryrace binaryall tarball assets

18
debian/changelog vendored

@ -1,3 +1,21 @@ @@ -1,3 +1,21 @@
spreed-speakfreely-server (0.17.4) precise; urgency=low
* Updated Japanese translation.
* Allow Makefile variables CONFIG_FILE and CONFIG_PATH.
* Fixed a possible conference connection issue when all ICE connected were successfull.
* Videos are now properly aligned to window top.
* Top bar buttons no longer overlap.
* Use onepeople audio video renderer per default.
* Added support for native HTTPS server.
* Fixed a data channel not ready error.
* Use new video layout implementation to draw when there is a main view.
* Added UI controls to switch video layout.
* Made the conferencekiosk renderer mode working and enabled it in Ui.
* Use new websocket.Upgraded API.
* No longer hang up on reload when not confirmed.
-- Simon Eisenmann <simon@struktur.de> Thu, 24 Apr 2014 17:59:05 +0200
spreed-speakfreely-server (0.17.3) precise; urgency=low
* Buddy images are now loaded with seperate URL calls.

4
html/main.html

@ -27,9 +27,7 @@ @@ -27,9 +27,7 @@
<div class="audio-level" title="{{_('Your audio level')}}"></div>
</div>
<div id="audiovideo" class="ng-cloak" ng-show="peer">
<div id="container">
<audio-video/>
</div>
<audio-video/>
</div>
<div id="screenshare" class="ng-cloak mainview">
<screenshare/>

8
server.conf.in

@ -10,6 +10,14 @@ listen = 127.0.0.1:8080 @@ -10,6 +10,14 @@ listen = 127.0.0.1:8080
#stats = true # Provide stats API at /api/v1/stats (do not enable this in production or unprotected!).
#pprofListen = 127.0.0.1:6060 # See http://golang.org/pkg/net/http/pprof/ for details
[https]
#listen = 127.0.0.1:8443
#certificate = server.crt # Full path to certificate.
#key = server.key # Full path to key.
#minVersion = SSLv3 # Minimal supported encryption (SSLv3, TLSv1, TLSv1.1, TLSv1.2).
#readtimeout = 10
#writetimeout = 10
[app]
#title = Spreed Speak Freely
#ver = 1234 # version string to use for static resource

1
src/app/spreed-speakfreely-server/api.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import ()

1
src/app/spreed-speakfreely-server/buffercache.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/config.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/connection.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/context.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
type Context struct {

7
src/app/spreed-speakfreely-server/hub.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (
@ -113,7 +114,7 @@ func (h *Hub) Stat(details bool) *HubStat { @@ -113,7 +114,7 @@ func (h *Hub) Stat(details bool) *HubStat {
rooms := make(map[string][]string)
for roomid, room := range h.roomTable {
users := make([]string, 0, len(room.connections))
for id, _ := range room.connections {
for id := range room.connections {
users = append(users, id)
}
rooms[roomid] = users
@ -215,9 +216,9 @@ func (h *Hub) GetGlobalConnections() []*Connection { @@ -215,9 +216,9 @@ func (h *Hub) GetGlobalConnections() []*Connection {
if room, ok := h.roomTable[h.config.globalRoomid]; ok {
h.mutex.RUnlock()
return room.GetConnections()
} else {
h.mutex.RUnlock()
}
h.mutex.RUnlock()
return make([]*Connection, 0)
}

23
src/app/spreed-speakfreely-server/images.go

@ -1,3 +1,24 @@ @@ -1,3 +1,24 @@
/*
* Spreed Speak Freely.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed Speak Freely.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (
@ -51,7 +72,7 @@ func NewImageCache() ImageCache { @@ -51,7 +72,7 @@ func NewImageCache() ImageCache {
}
func (self *imageCache) Update(userId string, image string) string {
var mimetype string = "image/x-unknown"
mimetype := "image/x-unknown"
pos := strings.Index(image, ";")
if pos != -1 {
mimetype = image[:pos]

13
src/app/spreed-speakfreely-server/main.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (
@ -49,12 +50,12 @@ var templates *template.Template @@ -49,12 +50,12 @@ var templates *template.Template
var config *Config
// Helper to retrieve languages from request.
func getRequestLanguages(r *http.Request, supported_languages []string) []string {
func getRequestLanguages(r *http.Request, supportedLanguages []string) []string {
accept_language_header, ok := r.Header["Accept-Language"]
acceptLanguageHeader, ok := r.Header["Accept-Language"]
var langs []string
if ok {
langs = goacceptlanguageparser.ParseAcceptLanguage(accept_language_header[0], supported_languages)
langs = goacceptlanguageparser.ParseAcceptLanguage(acceptLanguageHeader[0], supportedLanguages)
}
return langs
@ -121,7 +122,7 @@ func handleRoomView(room string, w http.ResponseWriter, r *http.Request) { @@ -121,7 +122,7 @@ func handleRoomView(room string, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "private, max-age=0")
// Detect if the request was made with SSL.
ssl := false
ssl := r.TLS != nil
proto, ok := r.Header["X-Forwarded-Proto"]
if ok {
ssl = proto[0] == "https"
@ -290,9 +291,8 @@ func runner(runtime phoenix.Runtime) error { @@ -290,9 +291,8 @@ func runner(runtime phoenix.Runtime) error {
templates, err = templates.ParseGlob(path.Join(extraFolder, "*.html"))
if err != nil {
return fmt.Errorf("Failed to load extra templates: %s", err)
} else {
log.Printf("Loaded extra templates from: %s", extraFolder)
}
log.Printf("Loaded extra templates from: %s", extraFolder)
}
// Create our hub instance.
@ -358,6 +358,7 @@ func runner(runtime phoenix.Runtime) error { @@ -358,6 +358,7 @@ func runner(runtime phoenix.Runtime) error {
}
runtime.DefaultHTTPHandler(r)
runtime.DefaultHTTPSHandler(r)
return runtime.Start()
}

1
src/app/spreed-speakfreely-server/random.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/rooms.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/roomworker.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/server.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/stats.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

18
src/app/spreed-speakfreely-server/tokenprovider.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (
@ -49,19 +50,19 @@ func (tf *TokenFile) ReloadIfModified() error { @@ -49,19 +50,19 @@ func (tf *TokenFile) ReloadIfModified() error {
return nil
}
func reload_tokens(tf *TokenFile) {
func reloadRokens(tf *TokenFile) {
r, err := os.Open(tf.Path)
if err != nil {
panic(err)
}
csv_reader := csv.NewReader(r)
csv_reader.Comma = ':'
csv_reader.Comment = '#'
csv_reader.TrimLeadingSpace = true
csvReader := csv.NewReader(r)
csvReader.Comma = ':'
csvReader.Comment = '#'
csvReader.TrimLeadingSpace = true
records, err := csv_reader.ReadAll()
records, err := csvReader.ReadAll()
if err != nil {
panic(err)
}
@ -76,15 +77,14 @@ func reload_tokens(tf *TokenFile) { @@ -76,15 +77,14 @@ func reload_tokens(tf *TokenFile) {
func TokenFileProvider(filename string) TokenProvider {
tf := &TokenFile{Path: filename}
tf.Reload = func() { reload_tokens(tf) }
tf.Reload = func() { reloadRokens(tf) }
return func(token string) string {
tf.ReloadIfModified()
_, exists := tf.Tokens[token]
if !exists {
return ""
} else {
return token
}
return token
}
}

1
src/app/spreed-speakfreely-server/tokens.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

1
src/app/spreed-speakfreely-server/user.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (

21
src/app/spreed-speakfreely-server/ws.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import (
@ -31,6 +32,23 @@ const ( @@ -31,6 +32,23 @@ const (
wsWriteBufSize = 1024
)
var (
upgrader = websocket.Upgrader{
ReadBufferSize: wsReadBufSize,
WriteBufferSize: wsWriteBufSize,
CheckOrigin: func(r *http.Request) bool {
// Allow all connections by default to keep backwards
// compatibility, but we should really check the Origin
// header instead!
//
// NOTE: We can omit "CheckOrigin" if the host in Origin
// must be the same as the host of the request (which
// is probably always the case).
return true
},
}
)
func makeWsHubHandler(h *Hub) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@ -42,9 +60,8 @@ func makeWsHubHandler(h *Hub) http.HandlerFunc { @@ -42,9 +60,8 @@ func makeWsHubHandler(h *Hub) http.HandlerFunc {
}
// Upgrade to Websocket mode.
ws, err := websocket.Upgrade(w, r, nil, wsReadBufSize, wsWriteBufSize)
ws, err := upgrader.Upgrade(w, r, nil)
if _, ok := err.(websocket.HandshakeError); ok {
w.WriteHeader(http.StatusBadRequest)
return
} else if err != nil {
log.Println(err)

1
src/app/spreed-speakfreely-server/wsdata.go

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
type DataHello struct {

25
src/i18n/messages-ja.po

@ -9,7 +9,7 @@ msgstr "" @@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: Spreed Speak Freely 1.0\n"
"Report-Msgid-Bugs-To: simon@struktur.de\n"
"POT-Creation-Date: 2014-04-14 16:16+0200\n"
"PO-Revision-Date: 2014-04-09 14:43+0100\n"
"PO-Revision-Date: 2014-04-23 22:25+0100\n"
"Last-Translator: Curt Frisemo <curt.frisemo@spreed.com>\n"
"Language-Team: Curt Frisemo <curt.frisemo@spreed.com>\n"
"Plural-Forms: nplurals=1; plural=0\n"
@ -111,12 +111,11 @@ msgstr "ルームを出る" @@ -111,12 +111,11 @@ msgstr "ルームを出る"
msgid "Current room"
msgstr "現在のルーム"
#, fuzzy
msgid "Screen sharing options"
msgstr "メディアスクリーン共有"
msgstr "画面共有オプション"
msgid "Fit screen."
msgstr ""
msgstr "画面に合わせる"
msgid "Your picture"
msgstr "あなたの写真"
@ -152,7 +151,7 @@ msgid "High" @@ -152,7 +151,7 @@ msgid "High"
msgstr "高い"
msgid "HD"
msgstr ""
msgstr "HD"
msgid "Language"
msgstr "言語"
@ -289,7 +288,7 @@ msgid "Click here for help (Google Chrome)." @@ -289,7 +288,7 @@ msgid "Click here for help (Google Chrome)."
msgstr "ここをクリックしてヘルプ表示(Google Chrome)"
msgid "Please set your user details and settings."
msgstr "あなたのユーザー情報とセッティングを設定してください."
msgstr "あなたのプロフィールとアプリの動作を設定してください."
msgid ""
"Please note that some settings require you to reload or to make a new "
@ -369,7 +368,7 @@ msgid " does not pick up." @@ -369,7 +368,7 @@ msgid " does not pick up."
msgstr "は電話にでません."
msgid " tried to call you."
msgstr ""
msgstr "は電話しようとしました."
msgid " called you."
msgstr "から電話がありました."
@ -396,6 +395,9 @@ msgid "" @@ -396,6 +395,9 @@ msgid ""
"usermedia-screen-capture and open it with your browser and enable the "
"flag on top. Then restart the browser and you are ready to go."
msgstr ""
"画面共有は拒否されました.ブラウザの画面共有の設定を確認して下さい. Chromeのアドレスバーに chrome://flags/#enable-"
"usermedia-screen-capture "
"を入力して開き、スクリーンキャプチャのサポートを有効にしてください。その後ブラウザを再起動してください。"
msgid "Use browser language"
msgstr "ブラウザの言語を使用"
@ -437,19 +439,18 @@ msgstr "アクセスコードの確認に失敗しました.インターネッ @@ -437,19 +439,18 @@ msgstr "アクセスコードの確認に失敗しました.インターネッ
#, fuzzy, python-format
msgid "and %s"
msgstr ""
msgstr "と %2"
#, python-format
msgid "and %d others"
msgstr ""
msgid "User"
msgstr ""
msgstr "ユーザー"
msgid "Someone"
msgstr ""
msgstr "誰か"
#, fuzzy
msgid "Me"
msgstr "名前"
msgstr ""

100
src/styles/color-pallete.html

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
<!DOCTYPE html>
<title>CSS site color pallete</title>
<style>
td {
width: 20em;
padding: 0 2%;
}
.color-block {
height: 50px;
border: 10px solid white;
}
.color-desc {
height: 25px;
padding: 5% 0 0 0;
text-align: center;
}
</style>
<table>
<tr>
<td class="color-desc">
$background: #e5e5e5
</td>
<td class="color-desc">
$componentbg: #f5f5f5
</td>
<td class="color-desc">
$componentfg1: #262626
</td>
</tr>
<tr>
<td class="color-block" style="background-color: #e5e5e5;"></td>
<td class="color-block" style="background-color: #f5f5f5;"></td>
<td class="color-block" style="background-color: #262626;"></td>
</tr>
<tr>
<td class="color-desc">
$componentfg2: rgba(0,0,0,.5)
</td>
<td class="color-desc">
$componentfg3: rgba(0,0,0,.2)
</td>
<td class="color-desc">
$componentfg4: #737373
</td>
</tr>
<tr>
<td class="color-block" style="background-color: rgba(0,0,0,.5);"></td>
<td class="color-block" style="background-color: rgba(0,0,0,.2);"></td>
<td class="color-block" style="background-color: #737373;"></td>
</tr>
<tr>
<td class="color-desc">
$sidepanebg: white
</td>
<td class="color-desc">
$bordercolor: #ccc
</td>
<td class="color-desc">
$actioncolor1: rgb(132,184,25)
</td>
</tr>
<tr>
<td class="color-block" style="background-color: white;"></td>
<td class="color-block" style="background-color: #ccc;"></td>
<td class="color-block" style="background-color: rgb(132,184,25);"></td>
</tr>
<tr>
<td class="color-desc">
$actioncolor2: rgb(0,149,52)
</td>
<td class="color-desc">
none: #222
</td>
<td class="color-desc">
none: #db4f39
</td>
</tr>
<tr>
<td class="color-block" style="background-color: rgb(0,149,52);"></td>
<td class="color-block" style="background-color: #222;"></td>
<td class="color-block" style="background-color: #db4f39;"></td>
</tr>
<tr>
<td class="color-desc">
none: #84b819
</td>
<td class="color-desc">
none: rgba(0,0,0,.4)
</td>
<td class="color-desc">
none: rgba(0,0,0,.3)
</td>
</tr>
<tr>
<td class="color-block" style="background-color: #84b819;"></td>
<td class="color-block" style="background-color: rgba(0,0,0,.4);"></td>
<td class="color-block" style="background-color: rgba(0,0,0,.3);"></td>
</tr>
</table>

327
src/styles/components/_audiovideo.scss

@ -19,59 +19,264 @@ @@ -19,59 +19,264 @@
*
*/
#audiovideo {
position:absolute;
left:0px;
top:44px;
bottom:0px;
right:0px;
boder-top:1px solid $bordercolor;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
position:absolute;
left:0px;
top:44px;
bottom:0px;
right:0px;
border-top:1px solid $bordercolor;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
#audiovideo.fullscreen {
top:0px !important;
right:0px !important;
bottom:0px !important;
left:0px !important;
background:black !important;
top:0px !important;
right:0px !important;
bottom:0px !important;
left:0px !important;
background:black !important;
}
#audiovideo.fullscreen .remoteVideo .peeractions {
display:none;
#audiovideo.fullscreen .remoteVideo .peerActions {
display:none;
}
.withChat #audiovideo, .withBuddylist #audiovideo {
right:260px;
right:260px;
}
.withBuddylist.withChat #audiovideo {
right:520px;
right:520px;
}
.mainScreenshare {
#audiovideo {
width:150px;
.remoteVideo .peerlabel {
font-size:12px;
font-weight:bold;
}
.remoteVideo .peeractions i {
font-size:1em;
}
.audiovideo {
position:absolute;
top:0px;
left:0px;
bottom:0px;
right:0px;
}
.audiovideo.active {
perspective: 1000;
-webkit-perspective: 1000;
}
.audiovideo .audiovideoBase {
position:relative;
width:100%;
height:100%;
transition-property: transform;
-webkit-transition-property: -webkit-transform;
transition-duration: 2s;
-webkit-transition-duration: 2s;
transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
z-index:2;
}
.audiovideo.active .audiovideoBase {
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
.audiovideo .localContainer {
position: absolute;
left:0px;
right:0px;
top:0px;
bottom:0px;
transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
pointer-events:none;
z-index:2;
}
.audiovideo .remoteContainer {
position: absolute;
left:0px;
right:0px;
top:0px;
bottom:0px;
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
pointer-events:none;
z-index:2;
}
.audiovideo .miniContainer {
position: absolute;
max-height: 18%;
bottom: 2px;
right: 2px;
transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
opacity: 0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 0.5s;
-webkit-transition-duration: 0.5s;
}
.audiovideo .miniContainer.visible {
opacity: 1;
}
.audiovideo .miniVideo {
max-height: 100%;
max-width:100%;
display:block;
}
.audiovideo .localVideo {
width: 100%;
max-height: 100%;
opacity: 0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 2s;
-webkit-transition-duration: 2s;
background: rgba(0,0,0,0.4);
display:block;
}
.audiovideo .remoteVideos {
position:absolute;
left:0px;
right:0px;
bottom:0px;
top:0px;
opacity: 0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 2s;
-webkit-transition-duration: 2s;
video {
width:100%;
height:100%;
display:block;
}
}
.remoteVideo .peerlabel {
.audiovideo {
.remoteVideo {
display: inline-block;
width:100%;
max-width:100%;
max-height:100%;
vertical-align:bottom;
position:relative;
visibility:hidden;
background: rgba(0,0,0,0.4);
overflow:hidden;
}
.remoteVideo.withvideo {
visibility:visible;
}
.remoteVideo.onlyaudio {
visibility:visible;
background: #666;
}
.remoteVideo .onlyaudio {
display:none;
position:absolute;
left:0px;
top:45%;
right:0px;
color:rgba(255,255,255,0.3);
text-align:center;
font-size:80px;
margin-top:-40px;
pointer-events:auto;
}
.remoteVideo.onlyaudio video {
display:none;
}
.remoteVideo.onlyaudio .onlyaudio {
display:block;
}
.remoteVideo .peerActions {
position: absolute;
z-index: 10;
left:0px;
right:0px;
bottom:5%;
text-align:center;
opacity:.0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 0.2s;
-webkit-transition-duration: 0.2s;
pointer-events:auto;
}
.remoteVideo .peerActions i {
font-size:3vw;
}
.remoteVideo .peerActions:hover {
opacity:.5;
}
.remoteVideo .peerLabel {
position: absolute;
z-index:8;
left:4%;
bottom:4%;
font-size:2.5vw;
color:white;
opacity:.7;
text-shadow: 0px 0px 4px black;
max-width:30%;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
padding:4px;
}
}
.audiovideo .overlayActions {
position: absolute;
left:0px;
top:0px;
bottom:0px;
height:70px;
margin:auto 0;
width:40px;
padding:3px 0;
background: rgba(0,0,0,0.9);
z-index:5;
opacity:0;
button {
width:40px;
display: block;
color:#ccc;
cursor:pointer;
text-shadow: 0 0 5px black;
outline: 0;
}
}
.audiovideo.active:hover .overlayActions {
opacity: 0.3;
}
.audiovideo.active .overlayActions:hover {
opacity: 0.6;
}
.remoteVideo .peerLabel {
-webkit-transition: color 500ms ease-out;
-moz-transition: color 500ms ease-out;
-o-transition: color 500ms ease-out;
transition: color 500ms ease-out;
}
.remoteVideo.talking .peerlabel {
color: $audiovideolevel;
.remoteVideo.talking .peerLabel {
color: #9dd53a;
}
.remoteVideo .overlaylogo {
.remoteVideo .overlayLogo {
position:absolute;
right:4%;
top:4%;
@ -88,37 +293,63 @@ right:520px; @@ -88,37 +293,63 @@ right:520px;
pointer-events: none;
}
.localVideo video {
.miniContainer video {
border:1px solid transparent;
}
.localVideo.talking video {
border:1px solid $audiovideolevel;
.miniContainer.talking video {
border:1px solid #9dd53a;
}
.renderer-smally {
width:150px;
.remoteVideos {
padding-bottom: 85px;
}
.miniContainer {
bottom:0px;
left:0px;
right:0px;
max-height:none;
height:85px;
}
.remoteVideo .peerLabel {
font-size:.9em;
font-weight:bold;
}
.remoteVideo .peerActions i {
font-size:1em;
}
}
.renderer-onepeople {
}
.renderer-conferencekiosk {
#remoteVideos {
.remoteVideos {
top:auto;
bottom:2px;
text-align:center;
background:rgba(0,0,0,0.4);
padding-right:192px;
min-height:108px;
pointer-events:auto;
white-space:nowrap;
>div {
height:108px;
width:192px;
cursor:pointer;
}
.overlaylogo {
.overlayLogo {
display:none;
}
.peerlabel, .peeractions i {
.peerLabel, .peerActions i {
font-size:1.1em;
}
.peerlabel {
.peerLabel {
background: rgba(0,0,0,0.9);
}
}
#mini {
.miniContainer {
max-height: none;
height:108px;
width:192px;
@ -136,14 +367,13 @@ right:520px; @@ -136,14 +367,13 @@ right:520px;
transition-duration: 2s;
-webkit-transition-duration: 2s;
}
.bigVideo video {
width:100%;
height:100%;
}
}
.bigVideo video {
width:100%;
height:100%;
}
@media only screen and (max-width: 630px) {
.mainScreenshare #audiovideo {
display:none;
@ -152,6 +382,5 @@ right:520px; @@ -152,6 +382,5 @@ right:520px;
@media only screen and (max-width:590px) {
#audiovideo {
right:0px;
z-index:12;
}
}

319
src/styles/components/_bar.scss

@ -18,167 +18,178 @@ @@ -18,167 +18,178 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#bar {
-webkit-box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.2);
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.2);
position: absolute;
top: 0;
left: 0;
right: 0;
min-height: 44px;
background-color: $componentbg;
color: $componentfg1;
font-size: 1em;
font-weight: bold;
line-height: 40px;
text-align: center;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
z-index:5;
}
#bar > .left {
position: absolute;
left:0px;
top:0px;
bottom:0px;
padding-left:12px;
}
#bar .logo {
font-size:11px;
line-height:11px;
font-weight:normal;
color:black;
width:90px;
height:32px;
background-size:100%;
background-repeat:no-repeat;
background-image:url(../img/logo-small.png);
display:inline-block;
text-align:left;
}
#bar .logo > span {
position: relative;
left: 38px;
top: 26px;
font-style: italic;
}
#bar .logo > span a {
color:#222;
}
#bar > .right {
position: absolute;
right:0px;
top:1px;
bottom:1px;
padding-right:8px;
}
#bar > .left > *, #bar > .right > * {
vertical-align: middle;
}
#bar > .right .btn {
border-color:transparent;
background:transparent;
color:rgba(0,0,0,0.3);
height:42px;
width:42px;
display: inline-block;
font-size:24px;
padding:0px;
line-height:40px;
text-align:center;
margin-left:-8px;
}
#bar > .right .btn:focus {
border: none;
box-shadow: 0;
outline: none;
}
#bar > .right .btn:hover {
border-color: #ccc;
background-color:none;
color:rgba(0,0,0,0.4);
}
#bar > .right .btn.active {
border-color: #ccc;
background-color:none;
color:rgba(0,0,0,0.4);
}
#bar > .right .btn.active.amutebtn {
background-color: #db4f39;
border-color: #db4f39;
color: white;
}
#bar > .right .btn.active.aenablebtn {
background-color: #84b819;
border-color: #84b819;
color: white;
}
#bar .btn {
position:relative;
}
#bar .badge {
background-color: #84b819;
font-size:.4em;
position:absolute;
right:0px;
top:2px;
border:1px solid white;
}
#bar .userpicture {
margin:-5px 0.5em 0px 0.5em;
width:46px;
height:46px;
border-radius:2px;
display:inline-block;
}
#bar > .middle {
z-index:5;
background-color: $componentbg;
display:inline-block;
padding:0 1em;
position:relative;
min-height: 44px;
vertical-align:middle;
margin-left:-70px;
background-color: $componentbg;
color: $componentfg1;
font: bold 1em/40px $font-sans-serif;
left: 0;
min-height: 44px;
position: absolute;
right: 0;
top: 0;
text-align: center;
z-index: 5;
@include box-shadow(0 2px 10px 0 $componentfg3);
@include touch-callout(none);
@include user-select(none);
> .left {
bottom: 0;
left: 0;
top: 0;
padding-left: 12px;
position: absolute;
// TODO(theurere): cleanup
> *, #bar > .right > * {
vertical-align: middle;
}
}
.logo {
background: url(../img/logo-small.png) no-repeat;
background-size: 100%;
display: inline-block;
color: black;
font: normal 11px/11px $font-sans-serif;
height: 32px;
text-align: left;
width: 90px;
> span {
font-style: italic;
left: 38px;
position: relative;
top: 26px;
}
> span a {
color: $dgrey;
}
}
}
@media all and (max-width: 700px) {
#bar {
z-index:40;
-webkit-box-shadow: none;
box-shadow: none;
#bar {
> .right {
bottom: 1px;
padding-right: 8px;
position: absolute;
right: 0;
top: 1px;
.btn {
background: transparent;
border-color: transparent;
color: $grey3;
display: inline-block;
font: 24px/40px $font-sans-serif;
height: 42px;
margin-left: -4px;
padding: 0;
text-align: center;
width: 42px;
}
#bar > .middle.status-connecting, #bar > .middle.status-closed, #bar > .middle.status-reconnecting, #bar > .middle.status-error, #bar > .middle.status-ringing {
max-width:100%;
border-bottom:1px solid $bordercolor;
.actions {
display: block;
padding:.2em 0 .8em 0;
}
min-height: 45px;
.btn:focus {
border: none;
@include box-shadow(0);
outline: none;
}
#bar > .middle.status-connected, #bar > .middle.status-conference {
position:absolute;
left:0px;
right:0px;
max-width:100%;
.btn:hover {
background-color: none;
border-color: #ccc;
color: $grey4;
}
#bar > .middle {
display:block;
max-width:40%;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
margin-left:0px;
img {
display:none;
}
.btn.active {
background-color: none;
border-color: #ccc;
color: $grey4;
}
.btn.active.amutebtn {
background-color: $red;
border-color: $red;
color: white;
}
.btn.active.aenablebtn {
background-color: $actioncolor1;
border-color: $actioncolor1;
color: white;
}
}
}
#bar {
.btn {
position: relative;
}
.badge {
background-color: $actioncolor1;
border: 1px solid white;
font-size: .4em;
position: absolute;
right: 0;
top: 2px;
}
.userpicture {
border-radius: 2px;
display: inline-block;
height: 46px;
margin: -5px .5em 0 .5em;
width: 46px;
}
> .middle {
background-color: $componentbg;
display: inline-block;
min-height: 44px;
padding: 0 1em;
position: relative;
margin-left: -70px;
vertical-align: middle;
z-index: 5;
@include breakpt($breakpoint-medium) {
display: block;
margin-left: 0px;
max-width: 40%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
#bar {
@include breakpt($breakpoint-medium) {
z-index: 40;
@include box-shadow(none);
}
> .middle img {
@include breakpt($breakpoint-medium) {
display: none;
}
}
> .middle.status-connected,
> .middle.status-conference {
@include breakpt($breakpoint-medium) {
max-width: 100%;
left: 0;
position: absolute;
right: 0;
}
}
> .middle.status-connecting,
> .middle.status-closed,
> .middle.status-reconnecting,
> .middle.status-error,
> .middle.status-ringing {
@include breakpt($breakpoint-medium) {
border-bottom: 1px solid $bordercolor;
max-width: 100%;
min-height: 45px;
}
}
// TODO(theurere): cleanup
> .middle.status-connecting .actions,
> .middle.status-closed .actions,
> .middle.status-reconnecting .actions,
> .middle.status-error .actions,
> .middle.status-ringing .actions {
@include breakpt($breakpoint-medium) {
display: block;
padding: .2em 0 .8em 0;
}
}
}

179
src/styles/components/_webrtc.scss

@ -1,179 +0,0 @@ @@ -1,179 +0,0 @@
/*
* Spreed Speak Freely.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed Speak Freely.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#container {
position: absolute;
/*margin: 0px auto;*/
perspective: 1000;
-webkit-perspective: 1000;
top:0px;
left:0px;
bottom:0px;
right:0px;
}
#container .visible {
opacity:1 !important;
}
#card {
position:relative;
width:100%;
height:100%;
transition-property: transform;
-webkit-transition-property: -webkit-transform;
transition-duration: 2s;
-webkit-transition-duration: 2s;
transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
}
#card.active {
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
#local {
position: absolute;
left:0px;
right:0px;
top:0px;
bottom:0px;
transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
pointer-events:none;
}
#remote {
position: absolute;
left:0px;
right:0px;
top:0px;
bottom:0px;
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
#mini {
position: absolute;
max-height: 18%;
bottom: 2px;
right: 2px;
transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
opacity: 0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 0.5s;
-webkit-transition-duration: 0.5s;
}
#localVideo {
width: 100%;
height: 100%;
opacity: 0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 2s;
-webkit-transition-duration: 2s;
background: rgba(0,0,0,0.4);
/*background: red;*/
}
#remoteVideos {
position:absolute;
left:0px;
right:0px;
bottom:0px;
top:0px;
opacity: 0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 2s;
-webkit-transition-duration: 2s;
/*background: blue;*/
}
#remoteVideos video {
width:100%;
height:100%;
}
#miniVideo {
max-height: 100%;
max-width:100%;
}
.remoteVideo {
display: inline-block;
width:100%;
height:100%;
vertical-align:bottom;
position:relative;
visibility:hidden;
background: rgba(0,0,0,0.4);
}
.remoteVideo.withvideo {
visibility:visible;
}
.remoteVideo.onlyaudio {
visibility:visible;
background: #666;
}
.remoteVideo .onlyaudio {
display:none;
position:absolute;
left:0px;
top:45%;
right:0px;
color:rgba(255,255,255,0.3);
text-align:center;
font-size:80px;
margin-top:-40px;
}
.remoteVideo.onlyaudio video {
display:none;
}
.remoteVideo.onlyaudio .onlyaudio {
display:block;
}
.remoteVideo .peeractions {
position: absolute;
z-index: 10;
left:0px;
right:0px;
bottom:5%;
text-align:center;
opacity:.0;
transition-property: opacity;
-webkit-transition-property: opacity;
transition-duration: 0.2s;
-webkit-transition-duration: 0.2s;
}
.remoteVideo .peeractions i {
font-size:3vw;
}
.remoteVideo:hover .peeractions {
opacity:.5;
}
.remoteVideo .peerlabel {
position: absolute;
z-index:8;
left:4%;
bottom:4%;
font-size:2.5vw;
color:white;
opacity:.7;
text-shadow: 0px 0px 4px black;
max-width:30%;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
padding:4px;
}

1
src/styles/global/_base.scss

@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
html, body {
background-clip: padding-box;
height: 100%;
font: normal $base-font-size $font-sans-serif;
}
body {
margin: 0;

23
src/styles/global/_mixins.scss

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
@mixin breakpt($pt) {
@media (max-width: $pt) {
@content;
}
}
@mixin user-select($select) {
-khtml-user-select: $select;
-moz-user-select: $select;
-ms-user-select: $select;
-webkit-user-select: $select;
user-select: $select;
}
@mixin touch-callout($callout) {
-webkit-touch-callout: $callout;
}
@mixin box-shadow($shadow) {
-webkit-box-shadow: $shadow;
box-shadow: $shadow;
}

66
src/styles/global/_variables.scss

@ -1,48 +1,42 @@ @@ -1,48 +1,42 @@
// ** Custom Variables **
// --------------------------------------------------
// Colors
/*
* Spreed Speak Freely.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed Speak Freely.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
$background: #e5e5e5;
$componentbg: #f5f5f5;
$componentfg1: #262626;
$componentfg2: rgba(0,0,0,.5);
$componentfg3: rgba(0,0,0,.2);
$componentfg3: rgba(0,0,0,.2); //#ccc
$componentfg4: #737373;
$sidepanebg: white;
$bordercolor: #ccc;
$actioncolor1: rgb(132,184,25);
$actioncolor2: rgb(0,149,52);
$audiovideolevel: #9dd53a;
// ** Fontawsome changed variables **
// original at libs/fontawesome/_variables.scss
// --------------------------
// ** Bootstrap changed variables **
// original at libs/bootstrap/_variables.scss
// --------------------------------------------------
//== Scaffolding
//
// ## Settings for some of the most global styles.
//** Background color for `<body>`.
$body-bg: $background;
//== Typography
//
//## Font, line-height, and color for body text, headings, and more.
$grey3: rgba(0,0,0,.3);
$grey4: rgba(0,0,0,.4);
$dgrey: rgb(34,34,34);
$red: rgb(219,79,57);
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-family-base: $font-family-sans-serif;
$breakpoint-small: 480px;
$breakpoint-medium: 700px;
$breakpoint-large: 1280px;
$font-size-base: 13px;
$font-sans-serif: "Helvetica Neue",Helvetica,Arial,sans-serif;
$base-font-size: 13px;

5
src/styles/main.scss

@ -19,11 +19,11 @@ @@ -19,11 +19,11 @@
*
*/
@import "global/variables";
@import "compass";
@import "libs/libs";
@import "global/variables";
@import "global/mixins";
@import "global/base";
@import "global/angular";
@ -33,7 +33,6 @@ @@ -33,7 +33,6 @@
@import "components/rightslide";
@import "components/bar";
@import "components/webrtc";
@import "components/buddylist";
@import "components/settings";
@import "components/chat";

7
static/js/app.js

@ -119,12 +119,7 @@ define([ @@ -119,12 +119,7 @@ define([
var domain = "messages";
var catalog = domain + "-" + lang;
var bootstrap = function(translationData) {
if (translationData) {
// Set loaded translation data.
translationData.missing_key_callback = function(key) {
console.warn("Missing key " + key + " for " + lang);
};
} else {
if (!translationData) {
// Fallback catalog in case translation could not be loaded.
lang = "en";
translationData = {};

4
static/js/controllers/mediastreamcontroller.js

@ -589,7 +589,7 @@ define(['underscore', 'bigscreen', 'moment', 'webrtc.adapter'], function(_, BigS @@ -589,7 +589,7 @@ define(['underscore', 'bigscreen', 'moment', 'webrtc.adapter'], function(_, BigS
changed = true;
}
if (changed) {
$scope.$broadcast("mainresize");
$scope.$broadcast("mainresize", layout.main);
}
});
@ -618,7 +618,7 @@ define(['underscore', 'bigscreen', 'moment', 'webrtc.adapter'], function(_, BigS @@ -618,7 +618,7 @@ define(['underscore', 'bigscreen', 'moment', 'webrtc.adapter'], function(_, BigS
$element.addClass(makeName("main", layout.main));
}
}
$scope.$broadcast("mainresize");
$scope.$broadcast("mainresize", layout.main);
}}()
), true);

2
static/js/controllers/roomchangecontroller.js

@ -23,7 +23,7 @@ define([], function() { @@ -23,7 +23,7 @@ define([], function() {
// RoomchangeController
return ["$scope", "$element", "$window", "$location", "mediaStream", "$http", "$timeout", function($scope, $element, $window, $location, mediaStream, $http, $timeout) {
console.log("Room change controller", $element, $scope.roomdata);
//console.log("Room change controller", $element, $scope.roomdata);
var url = mediaStream.url.api("rooms");

93
static/js/directives/audiovideo.js

@ -30,17 +30,19 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -30,17 +30,19 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
var peers = {};
var events = $({});
$scope.card = $element;
$scope.container = $element.parent().get(0);
$scope.layoutparent = $element.parent().parent();
$scope.container = $element.get(0);
$scope.layoutparent = $element.parent();
$scope.remoteVideos = $element.find("#remoteVideos").get(0);
$scope.localVideo = $element.find("#localVideo").get(0);
$scope.miniVideo = $element.find("#miniVideo").get(0);
$scope.mini = $element.find("#mini");
$scope.remoteVideos = $element.find(".remoteVideos").get(0);
$scope.localVideo = $element.find(".localVideo").get(0);
$scope.miniVideo = $element.find(".miniVideo").get(0);
$scope.mini = $element.find(".miniContainer").get(0);
$scope.hasUsermedia = false;
$scope.isActive = false;
$scope.rendererName = $scope.defaultRendererName = "onepeople";
//console.log("audiovideo", localVideo, miniVideo);
$scope.addRemoteStream = function(stream, currentcall) {
@ -82,12 +84,12 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -82,12 +84,12 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
});
}
scope.$emit("active", currentcall);
$scope.resize();
$scope.redraw();
}, function() {
peers[peerid] = scope;
console.warn("We did not receive video data for remote stream", currentcall, stream, video);
scope.$emit("active", currentcall);
$scope.resize();
$scope.redraw();
});
scope.doChat = function() {
$scope.$emit("startchat", currentcall.id, {autofocus: true, restore: true});
@ -107,7 +109,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -107,7 +109,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
subscope.element.remove();
}
subscope.$destroy();
$scope.resize();
$scope.redraw();
}
};
@ -133,7 +135,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -133,7 +135,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
if (!$scope.isActive) {
$scope.isActive = true;
$scope.remoteVideos.style.opacity = 1;
$scope.card.addClass("active");
$element.addClass("active");
//console.log("active 3");
_.delay(function() {
$scope.localVideo.style.opacity = 0;
@ -141,7 +143,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -141,7 +143,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
}, 500);
_.delay(function() {
//console.log("active 4", $scope.mini);
$scope.mini.addClass("visible"); //.style.opacity = 1;
$($scope.mini).addClass("visible");
}, 1000);
}
@ -167,7 +169,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -167,7 +169,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
}
if ($scope.localVideo.videoWidth > 0) {
$scope.localVideo.style.opacity = 1;
$scope.resize();
$scope.redraw();
} else {
count++;
if (count < 100) {
@ -196,14 +198,15 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -196,14 +198,15 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
$scope.miniVideo.src = '';
$($scope.remoteVideos).empty();
}, 1500);
$scope.mini.removeClass("visible");
$($scope.mini).removeClass("visible");
$scope.localVideo.style.opacity = 0;
$scope.remoteVideos.style.opacity = 0;
$scope.card.removeClass('active');
$element.removeClass('active');
_.each(peers, function(scope, k) {
scope.$destroy();
delete peers[k];
});
$scope.rendererName = $scope.defaultRendererName;
});
@ -237,38 +240,66 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ @@ -237,38 +240,66 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
//console.log("compile", arguments)
$(scope.card).on("doubletap dblclick", _.debounce(scope.toggleFullscreen, 100, true));
iElement.on("doubletap dblclick", _.debounce(scope.toggleFullscreen, 100, true));
//scope.rendererName = "conferencekiosk";
scope.rendererName = "onepeople";
var rendererName = null;
var getRendererName = function() {
// Return name of current renderer.
if (rendererName !== null) {
return rendererName;
} else {
return scope.rendererName;
}
};
var needsResize = false;
scope.resize = function() {
needsResize = true;
scope.setRenderer = function(name) {
scope.rendererName = name;
};
var resize = function() {
var needsRedraw = false;
scope.redraw = function() {
needsRedraw = true;
};
var redraw = function() {
var size = {
width: scope.layoutparent.width(),
height: scope.layoutparent.height()
}
videoLayout.update(scope.rendererName, size, scope, controller);
var again = videoLayout.update(getRendererName(), size, scope, controller);
if (again) {
// Layout needs a redraw.
needsRedraw = true;
}
};
$($window).on("resize", scope.resize);
scope.$on("mainresize", function() {
_.defer(scope.resize);
// Make sure we draw on resize.
$($window).on("resize", scope.redraw);
scope.$on("mainresize", function(event, main) {
if (main) {
// Force smally renderer when we have a main view.
rendererName = "smally"
} else if (rendererName) {
rendererName = null;
}
_.defer(scope.redraw);
});
scope.redraw();
// Make sure we draw when the renderer was changed.
scope.$watch("rendererName", function() {
_.defer(scope.redraw);
});
scope.resize();
// Update function run in rendering thread.
var update = function() {
if (needsResize) {
needsResize =false;
resize();
if (needsRedraw) {
needsRedraw =false;
redraw();
}
requestAnimationFrame(update);
}
update();
_.defer(update);
}

4
static/js/mediastream/peerconference.js

@ -183,12 +183,16 @@ define(['underscore', 'mediastream/peercall'], function(_, PeerCall) { @@ -183,12 +183,16 @@ define(['underscore', 'mediastream/peercall'], function(_, PeerCall) {
console.log("Conference peer connection state changed", iceConnectionState, currentcall);
switch (iceConnectionState) {
case "completed":
case "connected":
if (!this.callsIn.hasOwnProperty(currentcall.id)) {
this.callsIn[currentcall.id] = true;
this.pushUpdate();
}
break;
case "failed":
console.warn("Conference peer connection state failed", currentcall);
break;
}
this.webrtc.onConnectionStateChange(iceConnectionState, currentcall);

19
static/js/mediastream/webrtc.js

@ -90,18 +90,12 @@ define([ @@ -90,18 +90,12 @@ define([
this.api.e.bind("received.offer received.candidate received.answer received.bye received.conference", _.bind(this.processReceived, this));
window.onbeforeunload = _.bind(function() {
if (this.currentcall) {
this.currentcall.close();
this.api.sendBye(this.currentcall.id);
}
if (this.currentconference) {
this.currentconference.close();
}
$(window).on("unload", _.bind(function() {
this.doHangup("unload");
if (this.api.connector) {
this.api.connector.disabled = true;
}
}, this);
}, this));
// Create default media (audio/video).
this.usermedia = new UserMedia();
@ -443,6 +437,7 @@ define([ @@ -443,6 +437,7 @@ define([
xfer.e.on("connectionStateChange", _.bind(function(event, iceConnectionState, currentxfer) {
console.log("Xfer state changed", iceConnectionState);
switch (iceConnectionState) {
case "completed":
case "connected":
// Do nothing here, we wait for dataReady.
break
@ -516,6 +511,7 @@ define([ @@ -516,6 +511,7 @@ define([
peerscreenshare.e.on("connectionStateChange", _.bind(function(event, iceConnectionState, currentscreenshare) {
console.log("Screen share state changed", iceConnectionState);
switch (iceConnectionState) {
case "completed":
case "connected":
opts.connected(currentscreenshare);
break
@ -645,7 +641,10 @@ define([ @@ -645,7 +641,10 @@ define([
};
WebRTC.prototype.onConnectionStateChange = function(iceConnectionState, currentcall) {
this.e.triggerHandler('statechange', [iceConnectionState, currentcall]);
// Defer this to allow native event handlers to complete before running more stuff.
_.defer(_.bind(function() {
this.e.triggerHandler('statechange', [iceConnectionState, currentcall]);
}, this));
};
WebRTC.prototype.onRemoteStreamAdded = function(stream, currentcall) {

2
static/js/services/fileupload.js

@ -129,7 +129,7 @@ define(["jquery", "underscore", "webrtc.adapter"], function($, _) { @@ -129,7 +129,7 @@ define(["jquery", "underscore", "webrtc.adapter"], function($, _) {
};
FileUpload.prototype.bindDrop = function(namespace, element, cb) {
console.log("Binding file upload drop to", namespace, element);
//console.log("Binding file upload drop to", namespace, element);
// Helper to allow later modifications.
var binder = {

74
static/js/services/videolayout.js

@ -42,7 +42,7 @@ define(["jquery", "underscore"], function($, _) { @@ -42,7 +42,7 @@ define(["jquery", "underscore"], function($, _) {
// videoLayout
return ["$window", function($window) {
// Video layout with all persons rendered the same size.
// Video layout with all videos rendered the same size.
var OnePeople = function(container, scope, controller) {
};
@ -59,15 +59,6 @@ define(["jquery", "underscore"], function($, _) { @@ -59,15 +59,6 @@ define(["jquery", "underscore"], function($, _) {
if (videos.length) {
var remoteSize = getRemoteVideoSize(videos, peers);
/*if (videos.length === 1) {
var remoteVideo = peers[videos[0]].element.find("video").get(0);
videoWidth = remoteVideo.videoWidth;
videoHeight = remoteVideo.videoHeight;
console.log("Remote video size: ", videoWidth, videoHeight);
} else {
videoWidth = 1920;
videoHeight = 1080;
}*/
videoWidth = remoteSize.width;
videoHeight = remoteSize.height;
}
@ -94,18 +85,18 @@ define(["jquery", "underscore"], function($, _) { @@ -94,18 +85,18 @@ define(["jquery", "underscore"], function($, _) {
}
var aspectRatio = videoWidth/videoHeight;
var innerHeight = size.height; //scope.layoutparent.height();
var innerWidth = size.width; //scope.layoutparent.width();
var innerHeight = size.height;
var innerWidth = size.width;
//console.log("resize", innerHeight, innerWidth);
//console.log("resize", container, videos.length, aspectRatio, innerHeight, innerWidth);
var extraCSS = {};
if (videos.length === 1) {
var newVideoWidth = innerWidth < aspectRatio * innerHeight ? innerWidth : aspectRatio * innerHeight;
var newVideoHeight = innerHeight < innerWidth / aspectRatio ? innerHeight : innerWidth / aspectRatio;
container.style.width = newVideoWidth + 'px';
container.style.left = ((innerWidth - newVideoWidth) / 2) + 'px';
var extraCSS = {};
} else {
var space = innerHeight*innerWidth; // square pixels
var videoSpace = space/videos.length;
@ -134,7 +125,7 @@ define(["jquery", "underscore"], function($, _) { @@ -134,7 +125,7 @@ define(["jquery", "underscore"], function($, _) {
container.style.width = newContainerWidth + "px";
container.style.left = ((innerWidth - newContainerWidth) / 2) + 'px';
extraCSS = {
"#remoteVideos": {
".renderer-onepeople .remoteVideos": {
">div": {
width: singleVideoWidth+"px",
height: singleVideoHeight+"px"
@ -155,15 +146,27 @@ define(["jquery", "underscore"], function($, _) { @@ -155,15 +146,27 @@ define(["jquery", "underscore"], function($, _) {
};
// Smally inherits from OnePeople
var Smally = function(container, scope, controller) {
// Call super.
OnePeople.call(this, container, scope, controller);
}
Smally.prototype = Object.create(OnePeople.prototype);
Smally.prototype.constructor = Smally;
Smally.prototype.name = "smally";
// A view with one selectable large video. The others are small.
var ConferenceKiosk = function(container, scope, controller) {
this.remoteVideos = $(container).find("#remoteVideos");
this.remoteVideos = $(container).find(".remoteVideos");
this.bigVideo = $("<div>").addClass("bigVideo").get(0);
this.remoteVideos.before(this.bigVideo);
this.big = null;
this.remoteVideos.on("click", ".remoteVideo", _.bind(function(event) {
if ($(event.currentTarget).hasClass("remoteVideo")) {
event.stopPropagation();
this.makeBig($(event.currentTarget));
}
}, this));
@ -212,6 +215,7 @@ define(["jquery", "underscore"], function($, _) { @@ -212,6 +215,7 @@ define(["jquery", "underscore"], function($, _) {
var aspectRatio = remoteSize.width/remoteSize.height;
var innerHeight = size.height - 110;
var innerWidth = size.width;
var extraCSS = {};
var bigVideoWidth = innerWidth < aspectRatio * innerHeight ? innerWidth : aspectRatio * innerHeight;
var bigVideoHeight = innerHeight < innerWidth / aspectRatio ? innerHeight : innerWidth / aspectRatio;
@ -219,19 +223,43 @@ define(["jquery", "underscore"], function($, _) { @@ -219,19 +223,43 @@ define(["jquery", "underscore"], function($, _) {
this.bigVideo.style.width = bigVideoWidth + 'px';
this.bigVideo.style.height = bigVideoHeight + 'px';
// Make space for own video on the right if width goes low.
if (((size.width - (videos.length-1) * 192) / 2) < 192) {
extraCSS = {
".renderer-conferencekiosk .remoteVideos": {
"margin-right": "192px",
"overflow-x": "auto",
"overflow-y": "hidden"
}
};
}
$.injectCSS(extraCSS, {
truncateFirst: true,
containerName: dynamicCSSContainer
});
};
ConferenceKiosk.prototype.close = function(container, scope, controller) {
this.closed = true;
if (this.big) {
this.remoteVideos.append(this.big);
this.big.find("video").get(0).play();
}
this.big = null;
this.bigVideo.remove()
this.bigVideo = null;
this.remoteVideos = null;
};
// Register renderers.
renderers[OnePeople.prototype.name] = OnePeople;
renderers[Smally.prototype.name] = Smally;
renderers[ConferenceKiosk.prototype.name] = ConferenceKiosk;
// Public api.
var current = null;
return {
@ -240,27 +268,33 @@ define(["jquery", "underscore"], function($, _) { @@ -240,27 +268,33 @@ define(["jquery", "underscore"], function($, _) {
var videos = _.keys(controller.peers);
var peers = controller.peers;
var container = scope.container;
var layoutparent = scope.layoutparent;
if (!current) {
current = new renderers[name](container, scope, controller)
console.log("Created new video layout renderer", name, current);
$(container).addClass("renderer-"+name);
$(layoutparent).addClass("renderer-"+name);
return true;
} else {
if (current.name !== name) {
current.close(container, scope, controller);
$(container).removeAttr("style");
$(container).removeClass("renderer-"+current.name);
current = new renderers[name](container, scope, conroller)
$(container).addClass("renderer-"+name);
$(layoutparent).removeClass("renderer-"+current.name);
current = new renderers[name](container, scope, controller)
$(layoutparent).addClass("renderer-"+name);
console.log("Switched to new video layout renderer", name, current);
return true;
}
}
current.render(container, size, scope, videos, peers);
return current.render(container, size, scope, videos, peers);
},
register: function(name, impl) {
renderers[name] = impl;
},
layouts: function() {
return _.keys(renderers);
}
}

22
static/partials/audiovideo.html

@ -1,12 +1,18 @@ @@ -1,12 +1,18 @@
<div id="card">
<div id="local">
<video id="localVideo" autoplay="autoplay" muted="true"></video>
<div class="overlaylogo"></div>
<div class="audiovideo">
<div class="audiovideoBase">
<div class="localContainer">
<video class="localVideo" autoplay="autoplay" muted="true"></video>
<div class="overlayLogo"></div>
</div>
<div id="remote">
<div id="remoteVideos"></div>
<div id="mini" class="localVideo" ng-class="{talking: talking}">
<video id="miniVideo" autoplay="autoplay" muted="true"></video>
<div class="remoteContainer">
<div class="remoteVideos nicescroll"></div>
<div class="miniContainer" ng-class="{talking: talking}">
<video class="miniVideo" autoplay="autoplay" muted="true"></video>
</div>
</div>
</div>
<div class="overlayActions">
<button class="btn btn-link" title="{{_('Standard view')}}" ng-click="setRenderer('onepeople')"><i class="fa fa-table" ></i></button>
<button class="btn btn-link" title="{{_('Kiosk view')}}" ng-click="setRenderer('conferencekiosk')"><i class="fa fa-user"></i></button>
</div>
</div>

6
static/partials/audiovideopeer.html

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
<div class="remoteVideo" ng-class="{'withvideo': withvideo, 'onlyaudio': onlyaudio, 'talking': talking}">
<video autoplay="autoplay"></video>
<div class="peerlabel">{{peerid|displayName}}</div>
<div class="peeractions">
<div class="peerLabel">{{peerid|displayName}}</div>
<div class="peerActions">
<a title="{{_('Start chat')}}" ng-click="doChat()" class="btn btn-default"><i class="fa fa-comments-o"></i></a>
</div>
<div class="onlyaudio"><i class="fa fa-eye-close"></i></div>
<div class="overlaylogo"></div>
<div class="overlayLogo"></div>
</div>

2
static/translation/messages-ja.json

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save