summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/admin.go2
-rw-r--r--api/api_test.go1
-rw-r--r--api/context.go3
-rw-r--r--api/post.go22
-rw-r--r--api/templates/password_change_body.html2
-rw-r--r--api/templates/password_change_subject.html2
-rw-r--r--doc/developer/tests/test-links.md1
-rw-r--r--doc/help/Markdown.md2
-rw-r--r--i18n/en.json4
-rw-r--r--i18n/es.json10
-rw-r--r--model/utils.go40
-rw-r--r--web/react/components/channel_info_modal.jsx12
-rw-r--r--web/react/components/rhs_thread.jsx12
-rw-r--r--web/react/components/user_settings/user_settings_general.jsx4
-rw-r--r--web/react/utils/utils.jsx4
-rw-r--r--web/sass-files/sass/partials/_post.scss1
-rw-r--r--web/sass-files/sass/partials/_sidebar--left.scss3
-rw-r--r--web/static/config/manifest.json49
-rw-r--r--web/static/images/favicon/android-chrome-144x144.pngbin0 -> 42510 bytes
-rw-r--r--web/static/images/favicon/android-chrome-192x192.pngbin0 -> 63268 bytes
-rw-r--r--web/static/images/favicon/android-chrome-256x256.pngbin0 -> 77443 bytes
-rw-r--r--web/static/images/favicon/android-chrome-36x36.pngbin0 -> 46037 bytes
-rw-r--r--web/static/images/favicon/android-chrome-384x384.pngbin0 -> 122679 bytes
-rw-r--r--web/static/images/favicon/android-chrome-48x48.pngbin0 -> 47013 bytes
-rw-r--r--web/static/images/favicon/android-chrome-512x512.pngbin0 -> 156688 bytes
-rw-r--r--web/static/images/favicon/android-chrome-72x72.pngbin0 -> 34794 bytes
-rw-r--r--web/static/images/favicon/android-chrome-96x96.pngbin0 -> 51380 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-114x114.pngbin0 -> 42510 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-120x120.pngbin0 -> 39527 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-144x144.pngbin0 -> 42510 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-152x152.pngbin0 -> 58512 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-57x57.pngbin0 -> 33180 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-60x60.pngbin0 -> 33245 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-72x72.pngbin0 -> 34794 bytes
-rw-r--r--web/static/images/favicon/apple-touch-icon-76x76.pngbin0 -> 35229 bytes
-rw-r--r--web/static/images/favicon/favicon-16x16.png (renamed from web/static/images/favicon.ico)bin15708 -> 18480 bytes
-rw-r--r--web/static/images/favicon/favicon-32x32.pngbin0 -> 18877 bytes
-rw-r--r--web/static/images/favicon/favicon-96x96.pngbin0 -> 20501 bytes
-rw-r--r--web/static/images/favicon/iTunesArtwork@2x.pngbin0 -> 529609 bytes
-rw-r--r--web/static/images/icon50x50.pngbin15502 -> 16591 bytes
-rw-r--r--web/static/images/logo-email.pngbin10380 -> 21529 bytes
-rw-r--r--web/static/images/logo.pngbin23393 -> 25177 bytes
-rw-r--r--web/static/images/logoWhite.pngbin5876 -> 20570 bytes
-rw-r--r--web/static/images/logo_compact.pngbin6258 -> 18160 bytes
-rw-r--r--web/templates/head.html16
-rw-r--r--web/web_test.go2
46 files changed, 154 insertions, 38 deletions
diff --git a/api/admin.go b/api/admin.go
index 61741b445..72a95ba6a 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -41,7 +41,7 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
file, err := os.Open(utils.GetLogFileLocation(utils.Cfg.LogSettings.FileLocation))
if err != nil {
- c.Err = model.NewAppError("getLogs", c.T("api.admin.file_read_error"), err.Error())
+ c.Err = model.NewLocAppError("getLogs", "api.admin.file_read_error", nil, err.Error())
}
defer file.Close()
diff --git a/api/api_test.go b/api/api_test.go
index 2ef4e196d..4d7192e4b 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -14,6 +14,7 @@ var Client *model.Client
func Setup() {
if Srv == nil {
utils.LoadConfig("config.json")
+ utils.InitTranslations()
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
NewServer()
StartServer()
diff --git a/api/context.go b/api/context.go
index b6ffb1a29..a3311a971 100644
--- a/api/context.go
+++ b/api/context.go
@@ -206,6 +206,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if c.Err != nil {
+ c.Err.Translate(c.T)
c.Err.RequestId = c.RequestId
c.LogError(c.Err)
c.Err.Where = r.URL.Path
@@ -373,7 +374,7 @@ func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) {
}
func (c *Context) SetInvalidParam(where string, name string) {
- c.Err = model.NewAppError(where, "Invalid "+name+" parameter", "")
+ c.Err = model.NewLocAppError(where, "api.context.invalid_param", map[string]interface{}{"Name": name}, "")
c.Err.StatusCode = http.StatusBadRequest
}
diff --git a/api/post.go b/api/post.go
index 7cd45d310..42c3c304d 100644
--- a/api/post.go
+++ b/api/post.go
@@ -185,6 +185,28 @@ func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIc
attachment["text"] = aText
list[i] = attachment
}
+ if _, ok := attachment["pretext"]; ok {
+ aText := attachment["pretext"].(string)
+ aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})")
+ attachment["pretext"] = aText
+ list[i] = attachment
+ }
+ if fVal, ok := attachment["fields"]; ok {
+ if fields, ok := fVal.([]interface{}); ok {
+ // parse attachment field links into Markdown format
+ for j, fInt := range fields {
+ field := fInt.(map[string]interface{})
+ if _, ok := field["text"]; ok {
+ fText := field["text"].(string)
+ fText = linkWithTextRegex.ReplaceAllString(fText, "[${2}](${1})")
+ field["text"] = fText
+ fields[j] = field
+ }
+ }
+ attachment["fields"] = fields
+ list[i] = attachment
+ }
+ }
}
post.AddProp(key, list)
}
diff --git a/api/templates/password_change_body.html b/api/templates/password_change_body.html
index 82f4d5429..6199a3423 100644
--- a/api/templates/password_change_body.html
+++ b/api/templates/password_change_body.html
@@ -18,7 +18,7 @@
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
<h2 style="font-weight: normal; margin-top: 10px;">You updated your password</h2>
- <p>You updated your password for {{.Props.TeamDisplayName}} on {{ .Props.TeamURL }} by {{.Props.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator.</p>
+ <p>Your password has been updated for {{.Props.TeamDisplayName}} on {{ .Props.TeamURL }} by {{.Props.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator.</p>
</td>
</tr>
<tr>
diff --git a/api/templates/password_change_subject.html b/api/templates/password_change_subject.html
index e7a794090..0cbf052c1 100644
--- a/api/templates/password_change_subject.html
+++ b/api/templates/password_change_subject.html
@@ -1 +1 @@
-{{define "password_change_subject"}}You updated your password for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}}
+{{define "password_change_subject"}}Your password has been updated for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}}
diff --git a/doc/developer/tests/test-links.md b/doc/developer/tests/test-links.md
index 91e3e9403..b4a04e439 100644
--- a/doc/developer/tests/test-links.md
+++ b/doc/developer/tests/test-links.md
@@ -40,7 +40,6 @@ http://
./make-compiled-client.sh
test.:test
https://<your-mattermost-url>/signup/gitlab
-https://your-mattermost-url>/signup/gitlab
#### Only the links within these sentences should auto-link:
diff --git a/doc/help/Markdown.md b/doc/help/Markdown.md
index d185a4160..9d3cb2a90 100644
--- a/doc/help/Markdown.md
+++ b/doc/help/Markdown.md
@@ -88,7 +88,7 @@ and
## Emojis
-Emoji provided free by [Emoji One](http://emojione.com/). Check out a full list of emojis [here](http://http://emoji.codes/).
+Emoji provided free by [Emoji One](http://emojione.com/). Check out a full list of emojis [here](http://emoji.codes/).
```
:smile: :+1: :sheep:
diff --git a/i18n/en.json b/i18n/en.json
index 67cf9c31e..d1035e89a 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -10,5 +10,9 @@
{
"id": "api.admin.file_read_error",
"translation": "Error reading log file"
+ },
+ {
+ "id": "api.context.invalid_param",
+ "translation": "Invalid {{.Name}} parameter"
}
] \ No newline at end of file
diff --git a/i18n/es.json b/i18n/es.json
index 67cf9c31e..efa5b857b 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -1,14 +1,18 @@
[
{
"id": "utils.i18n.loaded",
- "translation": "Loaded system translations for '%v' from '%v'"
+ "translation": "Loaded system translations for '%v' from '%v' spanish test!"
},
{
"id": "mattermost.current_version",
- "translation": "Current version is %v (%v/%v/%v)"
+ "translation": "Current version is %v (%v/%v/%v) spanish test!"
},
{
"id": "api.admin.file_read_error",
- "translation": "Error reading log file"
+ "translation": "Error reading log file spanish test!"
+ },
+ {
+ "id": "api.context.invalid_param",
+ "translation": "Invalid {{.Name}} parameter spanish test!"
}
] \ No newline at end of file
diff --git a/model/utils.go b/model/utils.go
index 617c95efd..a18ca760e 100644
--- a/model/utils.go
+++ b/model/utils.go
@@ -9,13 +9,15 @@ import (
"encoding/base32"
"encoding/json"
"fmt"
- "github.com/pborman/uuid"
"io"
"net/mail"
"net/url"
"regexp"
"strings"
"time"
+
+ goi18n "github.com/nicksnyder/go-i18n/i18n"
+ "github.com/pborman/uuid"
)
type StringInterface map[string]interface{}
@@ -23,20 +25,31 @@ type StringMap map[string]string
type StringArray []string
type EncryptStringMap map[string]string
-// AppError is returned for any http response that's not in the 200 range.
type AppError struct {
- Message string `json:"message"` // Message to be display to the end user without debugging information
- DetailedError string `json:"detailed_error"` // Internal error string to help the developer
- RequestId string `json:"request_id"` // The RequestId that's also set in the header
- StatusCode int `json:"status_code"` // The http status code
- Where string `json:"-"` // The function where it happened in the form of Struct.Func
- IsOAuth bool `json:"is_oauth"` // Whether the error is OAuth specific
+ Id string `json:"id"`
+ Message string `json:"message"` // Message to be display to the end user without debugging information
+ DetailedError string `json:"detailed_error"` // Internal error string to help the developer
+ RequestId string `json:"request_id"` // The RequestId that's also set in the header
+ StatusCode int `json:"status_code"` // The http status code
+ Where string `json:"-"` // The function where it happened in the form of Struct.Func
+ IsOAuth bool `json:"is_oauth"` // Whether the error is OAuth specific
+ params map[string]interface{} `json:"-"`
}
func (er *AppError) Error() string {
return er.Where + ": " + er.Message + ", " + er.DetailedError
}
+func (er *AppError) Translate(T goi18n.TranslateFunc) {
+ if len(er.Message) == 0 {
+ if er.params == nil {
+ er.Message = T(er.Id)
+ } else {
+ er.Message = T(er.Id, er.params)
+ }
+ }
+}
+
func (er *AppError) ToJson() string {
b, err := json.Marshal(er)
if err != nil {
@@ -68,6 +81,17 @@ func NewAppError(where string, message string, details string) *AppError {
return ap
}
+func NewLocAppError(where string, id string, params map[string]interface{}, details string) *AppError {
+ ap := &AppError{}
+ ap.Id = id
+ ap.params = params
+ ap.Where = where
+ ap.DetailedError = details
+ ap.StatusCode = 500
+ ap.IsOAuth = false
+ return ap
+}
+
var encoding = base32.NewEncoding("ybndrfg8ejkmcpqxot1uwisza345h769")
// NewId is a globally unique identifier. It is a [A-Z0-9] string 26
diff --git a/web/react/components/channel_info_modal.jsx b/web/react/components/channel_info_modal.jsx
index 18e125de3..72c7c3daa 100644
--- a/web/react/components/channel_info_modal.jsx
+++ b/web/react/components/channel_info_modal.jsx
@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import * as Utils from '../utils/utils.jsx';
const Modal = ReactBootstrap.Modal;
export default class ChannelInfoModal extends React.Component {
@@ -10,10 +11,13 @@ export default class ChannelInfoModal extends React.Component {
channel = {
display_name: 'No Channel Found',
name: 'No Channel Found',
+ purpose: 'No Channel Found',
id: 'No Channel Found'
};
}
+ const channelURL = Utils.getShortenedTeamURL() + channel.name;
+
return (
<Modal
show={this.props.show}
@@ -28,13 +32,17 @@ export default class ChannelInfoModal extends React.Component {
<div className='col-sm-9'>{channel.display_name}</div>
</div>
<div className='row form-group'>
- <div className='col-sm-3 info__label'>{'Channel Handle:'}</div>
- <div className='col-sm-9'>{channel.name}</div>
+ <div className='col-sm-3 info__label'>{'Channel URL:'}</div>
+ <div className='col-sm-9'>{channelURL}</div>
</div>
<div className='row'>
<div className='col-sm-3 info__label'>{'Channel ID:'}</div>
<div className='col-sm-9'>{channel.id}</div>
</div>
+ <div className='row'>
+ <div className='col-sm-3 info__label'>{'Channel Purpose:'}</div>
+ <div className='col-sm-9'>{channel.purpose}</div>
+ </div>
</Modal.Body>
<Modal.Footer>
<button
diff --git a/web/react/components/rhs_thread.jsx b/web/react/components/rhs_thread.jsx
index 2edcd8b37..945b09e37 100644
--- a/web/react/components/rhs_thread.jsx
+++ b/web/react/components/rhs_thread.jsx
@@ -17,6 +17,8 @@ export default class RhsThread extends React.Component {
constructor(props) {
super(props);
+ this.mounted = false;
+
this.onChange = this.onChange.bind(this);
this.onChangeAll = this.onChangeAll.bind(this);
this.forceUpdateInfo = this.forceUpdateInfo.bind(this);
@@ -50,8 +52,11 @@ export default class RhsThread extends React.Component {
PostStore.addSelectedPostChangeListener(this.onChange);
PostStore.addChangeListener(this.onChangeAll);
PreferenceStore.addChangeListener(this.forceUpdateInfo);
+
this.resize();
window.addEventListener('resize', this.handleResize);
+
+ this.mounted = true;
}
componentDidUpdate() {
if ($('.post-right__scroll')[0]) {
@@ -63,7 +68,10 @@ export default class RhsThread extends React.Component {
PostStore.removeSelectedPostChangeListener(this.onChange);
PostStore.removeChangeListener(this.onChangeAll);
PreferenceStore.removeChangeListener(this.forceUpdateInfo);
+
window.removeEventListener('resize', this.handleResize);
+
+ this.mounted = false;
}
forceUpdateInfo() {
if (this.state.postList) {
@@ -82,7 +90,7 @@ export default class RhsThread extends React.Component {
}
onChange() {
var newState = this.getStateFromStores();
- if (!Utils.areObjectsEqual(newState, this.state)) {
+ if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
@@ -120,7 +128,7 @@ export default class RhsThread extends React.Component {
}
var newState = this.getStateFromStores();
- if (!Utils.areObjectsEqual(newState, this.state)) {
+ if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/user_settings/user_settings_general.jsx b/web/react/components/user_settings/user_settings_general.jsx
index db8cd277d..df7ae4a25 100644
--- a/web/react/components/user_settings/user_settings_general.jsx
+++ b/web/react/components/user_settings/user_settings_general.jsx
@@ -493,7 +493,7 @@ export default class UserSettingsGeneralTab extends React.Component {
);
submit = this.submitEmail;
- } else {
+ } else if (this.props.user.auth_service === Constants.GITLAB_SERVICE) {
inputs.push(
<div
key='oauthEmailInfo'
@@ -531,7 +531,7 @@ export default class UserSettingsGeneralTab extends React.Component {
} else {
describe = UserStore.getCurrentUser().email;
}
- } else {
+ } else if (this.props.user.auth_service === Constants.GITLAB_SERVICE) {
describe = 'Log in done through GitLab';
}
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index c51ae1a21..32373b4a3 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -1309,6 +1309,10 @@ export function fillArray(value, length) {
// Checks if a data transfer contains files not text, folders, etc..
// Slightly modified from http://stackoverflow.com/questions/6848043/how-do-i-detect-a-file-is-being-dragged-rather-than-a-draggable-element-on-my-pa
export function isFileTransfer(files) {
+ if (isBrowserIE()) {
+ return files.types != null && files.types.contains('Files');
+ }
+
return files.types != null && (files.types.indexOf ? files.types.indexOf('Files') !== -1 : files.types.contains('application/x-moz-file'));
}
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 7b7c2d73a..c5cd10b20 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -183,6 +183,7 @@ body.ios {
position: absolute;
top: 50%;
left: 50%;
+ pointer-events: none;
}
.overlay__files {
diff --git a/web/sass-files/sass/partials/_sidebar--left.scss b/web/sass-files/sass/partials/_sidebar--left.scss
index 6f969ed47..5e7f04724 100644
--- a/web/sass-files/sass/partials/_sidebar--left.scss
+++ b/web/sass-files/sass/partials/_sidebar--left.scss
@@ -42,6 +42,9 @@
margin-right: 6px;
width: 12px;
display: inline-block;
+ svg {
+ max-height: 14px;
+ }
i, path, ellipse {
@include opacity(0.5);
&.online--icon, &.away--icon {
diff --git a/web/static/config/manifest.json b/web/static/config/manifest.json
index 8f29460b3..dd95d917e 100644
--- a/web/static/config/manifest.json
+++ b/web/static/config/manifest.json
@@ -1,13 +1,40 @@
{
- "name": "Mattermost",
- "icons": [
- {
- "src": "../static/iamges/icon50x50.png",
- "sizes": "50x50",
- "type": "image/png"
- }
- ],
- "start_url": "/",
- "display": "standalone",
- "orientation": "portrait"
+ "name": "Mattermost",
+ "icons": [{
+ "src": "/static/images/favicon/android-chrome-36x36.png",
+ "type": "image/png",
+ "sizes": "36x36"
+ }, {
+ "src": "/static/images/favicon/android-chrome-48x48.png",
+ "type": "image/png",
+ "sizes": "48x48"
+ }, {
+ "src": "/static/images/favicon/android-chrome-72x72.png",
+ "type": "image/png",
+ "sizes": "72x72"
+ }, {
+ "src": "/static/images/favicon/android-chrome-96x96.png",
+ "type": "image/png",
+ "sizes": "96x96"
+ }, {
+ "src": "/static/images/favicon/android-chrome-144x144.png",
+ "type": "image/png",
+ "sizes": "144x144"
+ }, {
+ "src": "/static/images/favicon/android-chrome-192x192.png",
+ "type": "image/png",
+ "sizes": "192x192"
+ }, {
+ "src": "/static/images/favicon/android-chrome-256x256.png",
+ "type": "image/png",
+ "sizes": "256x256"
+ }, {
+ "src": "/static/images/favicon/android-chrome-384x384.png",
+ "type": "image/png",
+ "sizes": "384x384"
+ }, {
+ "src": "/static/images/favicon/android-chrome-512x512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }]
} \ No newline at end of file
diff --git a/web/static/images/favicon/android-chrome-144x144.png b/web/static/images/favicon/android-chrome-144x144.png
new file mode 100644
index 000000000..b4cb16a20
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-144x144.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-192x192.png b/web/static/images/favicon/android-chrome-192x192.png
new file mode 100644
index 000000000..43b64dee2
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-192x192.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-256x256.png b/web/static/images/favicon/android-chrome-256x256.png
new file mode 100644
index 000000000..17d568314
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-256x256.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-36x36.png b/web/static/images/favicon/android-chrome-36x36.png
new file mode 100644
index 000000000..a46f34b26
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-36x36.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-384x384.png b/web/static/images/favicon/android-chrome-384x384.png
new file mode 100644
index 000000000..6a3fde9d3
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-384x384.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-48x48.png b/web/static/images/favicon/android-chrome-48x48.png
new file mode 100644
index 000000000..6beb5bb2a
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-48x48.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-512x512.png b/web/static/images/favicon/android-chrome-512x512.png
new file mode 100644
index 000000000..b9229a3b7
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-512x512.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-72x72.png b/web/static/images/favicon/android-chrome-72x72.png
new file mode 100644
index 000000000..9f6afec0d
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-72x72.png
Binary files differ
diff --git a/web/static/images/favicon/android-chrome-96x96.png b/web/static/images/favicon/android-chrome-96x96.png
new file mode 100644
index 000000000..b6ae0c7a7
--- /dev/null
+++ b/web/static/images/favicon/android-chrome-96x96.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-114x114.png b/web/static/images/favicon/apple-touch-icon-114x114.png
new file mode 100644
index 000000000..b4cb16a20
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-114x114.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-120x120.png b/web/static/images/favicon/apple-touch-icon-120x120.png
new file mode 100644
index 000000000..29a96291d
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-120x120.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-144x144.png b/web/static/images/favicon/apple-touch-icon-144x144.png
new file mode 100644
index 000000000..b4cb16a20
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-144x144.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-152x152.png b/web/static/images/favicon/apple-touch-icon-152x152.png
new file mode 100644
index 000000000..be3f49d99
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-152x152.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-57x57.png b/web/static/images/favicon/apple-touch-icon-57x57.png
new file mode 100644
index 000000000..5e7e3d366
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-57x57.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-60x60.png b/web/static/images/favicon/apple-touch-icon-60x60.png
new file mode 100644
index 000000000..6f6c5e6bf
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-60x60.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-72x72.png b/web/static/images/favicon/apple-touch-icon-72x72.png
new file mode 100644
index 000000000..9f6afec0d
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-72x72.png
Binary files differ
diff --git a/web/static/images/favicon/apple-touch-icon-76x76.png b/web/static/images/favicon/apple-touch-icon-76x76.png
new file mode 100644
index 000000000..adb504eab
--- /dev/null
+++ b/web/static/images/favicon/apple-touch-icon-76x76.png
Binary files differ
diff --git a/web/static/images/favicon.ico b/web/static/images/favicon/favicon-16x16.png
index af5505331..777a60546 100644
--- a/web/static/images/favicon.ico
+++ b/web/static/images/favicon/favicon-16x16.png
Binary files differ
diff --git a/web/static/images/favicon/favicon-32x32.png b/web/static/images/favicon/favicon-32x32.png
new file mode 100644
index 000000000..36c4a12e0
--- /dev/null
+++ b/web/static/images/favicon/favicon-32x32.png
Binary files differ
diff --git a/web/static/images/favicon/favicon-96x96.png b/web/static/images/favicon/favicon-96x96.png
new file mode 100644
index 000000000..4f6c6d1b2
--- /dev/null
+++ b/web/static/images/favicon/favicon-96x96.png
Binary files differ
diff --git a/web/static/images/favicon/iTunesArtwork@2x.png b/web/static/images/favicon/iTunesArtwork@2x.png
new file mode 100644
index 000000000..10321f3a1
--- /dev/null
+++ b/web/static/images/favicon/iTunesArtwork@2x.png
Binary files differ
diff --git a/web/static/images/icon50x50.png b/web/static/images/icon50x50.png
index 7ac6ce1c9..4791e755f 100644
--- a/web/static/images/icon50x50.png
+++ b/web/static/images/icon50x50.png
Binary files differ
diff --git a/web/static/images/logo-email.png b/web/static/images/logo-email.png
index c16978ba8..d0a38e21d 100644
--- a/web/static/images/logo-email.png
+++ b/web/static/images/logo-email.png
Binary files differ
diff --git a/web/static/images/logo.png b/web/static/images/logo.png
index 423d4d270..1a35cdf01 100644
--- a/web/static/images/logo.png
+++ b/web/static/images/logo.png
Binary files differ
diff --git a/web/static/images/logoWhite.png b/web/static/images/logoWhite.png
index 11bbd4632..3166c974c 100644
--- a/web/static/images/logoWhite.png
+++ b/web/static/images/logoWhite.png
Binary files differ
diff --git a/web/static/images/logo_compact.png b/web/static/images/logo_compact.png
index b861b7c6d..a4bce6281 100644
--- a/web/static/images/logo_compact.png
+++ b/web/static/images/logo_compact.png
Binary files differ
diff --git a/web/templates/head.html b/web/templates/head.html
index 689c69d3c..b5eb3a9b3 100644
--- a/web/templates/head.html
+++ b/web/templates/head.html
@@ -15,6 +15,19 @@
<!-- iOS add to homescreen -->
<!-- Android add to homescreen -->
+ <link rel="apple-touch-icon" sizes="57x57" href="/static/images/favicon/apple-touch-icon-57x57.png">
+ <link rel="apple-touch-icon" sizes="60x60" href="/static/images/favicon/apple-touch-icon-60x60.png">
+ <link rel="apple-touch-icon" sizes="72x72" href="/static/images/favicon/apple-touch-icon-72x72.png">
+ <link rel="apple-touch-icon" sizes="76x76" href="/static/images/favicon/apple-touch-icon-76x76.png">
+ <link rel="apple-touch-icon" sizes="114x114" href="/static/images/favicon/apple-touch-icon-114x114.png">
+ <link rel="apple-touch-icon" sizes="120x120" href="/static/images/favicon/apple-touch-icon-120x120.png">
+ <link rel="apple-touch-icon" sizes="144x144" href="/static/images/favicon/apple-touch-icon-144x144.png">
+ <link rel="apple-touch-icon" sizes="152x152" href="/static/images/favicon/apple-touch-icon-152x152.png">
+ <link rel="apple-touch-icon" sizes="180x180" href="/static/images/favicon/apple-touch-icon-180x180.png">
+ <link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon/favicon-32x32.png">
+ <link rel="icon" type="image/png" sizes="192x192" href="/static/images/favicon/android-chrome-192x192.png">
+ <link rel="icon" type="image/png" sizes="96x96" href="/static/images/favicon/favicon-96x96.png">
+ <link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon/favicon-16x16.png">
<link rel="manifest" href="/static/config/manifest.json">
<!-- Android add to homescreen -->
@@ -27,9 +40,6 @@
<link rel="stylesheet" href="/static/css/katex.min.css">
<link rel="stylesheet" class="code_theme" href="">
- <link id="favicon" rel="icon" href="/static/images/favicon.ico" type="image/x-icon">
- <link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon">
-
<script src="/static/js/react-0.14.3.js"></script>
<script src="/static/js/react-dom-0.14.3.js"></script>
<script src="/static/js/jquery-2.1.4.js"></script>
diff --git a/web/web_test.go b/web/web_test.go
index 8d40810b5..97e5ff154 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -45,7 +45,7 @@ func TestStatic(t *testing.T) {
// add a short delay to make sure the server is ready to receive requests
time.Sleep(1 * time.Second)
- resp, err := http.Get(URL + "/static/images/favicon.ico")
+ resp, err := http.Get(URL + "/static/images/favicon/favicon-16x16.png")
if err != nil {
t.Fatalf("got error while trying to get static files %v", err)