Этот коммит содержится в:
Asaad Mahmood
2015-07-28 01:07:16 +05:00
родитель 5b7ae4f864 62db88ed45
Коммит 3dd541d3e0
8 изменённых файлов: 138 добавлений и 73 удалений

2
Godeps/Godeps.json сгенерированный
Просмотреть файл

@@ -100,7 +100,7 @@
},
{
"ImportPath": "github.com/nfnt/resize",
"Rev": "f2d1b73023c55bdfb4fa2ed385d2bec95bce3692"
"Rev": "dc93e1b98c579d90ee2fa15c1fd6dac34f6e7899"
},
{
"ImportPath": "github.com/stretchr/objx",

6
Godeps/_workspace/src/github.com/nfnt/resize/converter.go сгенерированный поставляемый
Просмотреть файл

@@ -131,11 +131,11 @@ func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16,
// reverse alpha-premultiplication.
if a != 0 {
r *= 0xffff
r *= 0xff
r /= a
g *= 0xffff
g *= 0xff
g /= a
b *= 0xffff
b *= 0xff
b /= a
}

4
Godeps/_workspace/src/github.com/nfnt/resize/resize.go сгенерированный поставляемый
Просмотреть файл

@@ -167,7 +167,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
// accessing the YCbCr arrays in a tight loop is slow.
// converting the image to ycc increases performance by 2x.
temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio)
result := newYCC(image.Rect(0, 0, int(width), int(height)), input.SubsampleRatio)
result := newYCC(image.Rect(0, 0, int(width), int(height)), image.YCbCrSubsampleRatio444)
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
in := imageYCbCrToYCC(input)
@@ -409,7 +409,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
// accessing the YCbCr arrays in a tight loop is slow.
// converting the image to ycc increases performance by 2x.
temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio)
result := newYCC(image.Rect(0, 0, int(width), int(height)), input.SubsampleRatio)
result := newYCC(image.Rect(0, 0, int(width), int(height)), image.YCbCrSubsampleRatio444)
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
in := imageYCbCrToYCC(input)

96
Godeps/_workspace/src/github.com/nfnt/resize/resize_test.go сгенерированный поставляемый
Просмотреть файл

@@ -46,7 +46,7 @@ func Test_CorrectResize(t *testing.T) {
}
}
func Test_SameColor(t *testing.T) {
func Test_SameColorWithRGBA(t *testing.T) {
img := image.NewRGBA(image.Rect(0, 0, 20, 20))
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
@@ -56,9 +56,99 @@ func Test_SameColor(t *testing.T) {
out := Resize(10, 10, img, Lanczos3)
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
color := img.At(x, y).(color.RGBA)
color := out.At(x, y).(color.NRGBA)
if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF {
t.Fail()
t.Errorf("%+v", color)
}
}
}
}
func Test_SameColorWithNRGBA(t *testing.T) {
img := image.NewNRGBA(image.Rect(0, 0, 20, 20))
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
img.SetNRGBA(x, y, color.NRGBA{0x80, 0x80, 0x80, 0xFF})
}
}
out := Resize(10, 10, img, Lanczos3)
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
color := out.At(x, y).(color.NRGBA)
if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF {
t.Errorf("%+v", color)
}
}
}
}
func Test_SameColorWithRGBA64(t *testing.T) {
img := image.NewRGBA64(image.Rect(0, 0, 20, 20))
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
img.SetRGBA64(x, y, color.RGBA64{0x8000, 0x8000, 0x8000, 0xFFFF})
}
}
out := Resize(10, 10, img, Lanczos3)
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
color := out.At(x, y).(color.NRGBA64)
if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF {
t.Errorf("%+v", color)
}
}
}
}
func Test_SameColorWithNRGBA64(t *testing.T) {
img := image.NewNRGBA64(image.Rect(0, 0, 20, 20))
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
img.SetNRGBA64(x, y, color.NRGBA64{0x8000, 0x8000, 0x8000, 0xFFFF})
}
}
out := Resize(10, 10, img, Lanczos3)
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
color := out.At(x, y).(color.NRGBA64)
if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF {
t.Errorf("%+v", color)
}
}
}
}
func Test_SameColorWithGray(t *testing.T) {
img := image.NewGray(image.Rect(0, 0, 20, 20))
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
img.SetGray(x, y, color.Gray{0x80})
}
}
out := Resize(10, 10, img, Lanczos3)
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
color := out.At(x, y).(color.Gray)
if color.Y != 0x80 {
t.Errorf("%+v", color)
}
}
}
}
func Test_SameColorWithGray16(t *testing.T) {
img := image.NewGray16(image.Rect(0, 0, 20, 20))
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
img.SetGray16(x, y, color.Gray16{0x8000})
}
}
out := Resize(10, 10, img, Lanczos3)
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
color := out.At(x, y).(color.Gray16)
if color.Y != 0x8000 {
t.Errorf("%+v", color)
}
}
}

Просмотреть файл

@@ -4,6 +4,8 @@ GOPATH ?= $(GOPATH:)
GOFLAGS ?= $(GOFLAGS:)
BUILD_NUMBER ?= $(BUILD_NUMBER:)
GO=$(GOPATH)/bin/godep go
ifeq ($(BUILD_NUMBER),)
BUILD_NUMBER := dev
endif
@@ -21,29 +23,27 @@ travis:
@echo building for travis
rm -Rf $(DIST_ROOT)
@go clean $(GOFLAGS) -i ./...
@$(GO) clean $(GOFLAGS) -i ./...
@cd web/react/ && npm install
@go build $(GOFLAGS) ./...
@$(GO) build $(GOFLAGS) ./...
@mkdir -p logs
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
build:
@go build $(GOFLAGS) ./...
@$(GO) build $(GOFLAGS) ./...
install:
@go get $(GOFLAGS) github.com/tools/godep
@if [ $(shell docker ps -a | grep -ci mattermost-mysql) -eq 0 ]; then \
echo restoring go libs using godep; \
$(GOPATH)/bin/godep restore; \
echo starting mattermost-mysql; \
docker run --name mattermost-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mostest \
-e MYSQL_USER=mmuser -e MYSQL_PASSWORD=mostest -e MYSQL_DATABASE=mattermost_test -d mysql > /dev/null; \
@@ -64,37 +64,37 @@ install:
test: install
@mkdir -p logs
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
@go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
benchmark: install
@mkdir -p logs
@go test $(GOFLAGS) -test.v -run=NO_TESTS -bench=$(BENCH) ./api || exit 1
@$(GO) test $(GOFLAGS) -test.v -run=NO_TESTS -bench=$(BENCH) ./api || exit 1
cover: install
rm -Rf $(DIST_RESULTS)
mkdir -p $(DIST_RESULTS)
@go test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/api.cover.out github.com/mattermost/platform/api
@go test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/model.cover.out github.com/mattermost/platform/model
@go test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/store.cover.out github.com/mattermost/platform/store
@go test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/utils.cover.out github.com/mattermost/platform/utils
@go test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/web.cover.out github.com/mattermost/platform/web
@$(GO) test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/api.cover.out github.com/mattermost/platform/api
@$(GO) test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/model.cover.out github.com/mattermost/platform/model
@$(GO) test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/store.cover.out github.com/mattermost/platform/store
@$(GO) test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/utils.cover.out github.com/mattermost/platform/utils
@$(GO) test $(GOFLAGS) -coverprofile=$(DIST_RESULTS)/web.cover.out github.com/mattermost/platform/web
cd $(DIST_RESULTS) && \
echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \
awk '{if($$1 != last) {print $$0;last=$$1}}' >> coverage.out
cd $(DIST_RESULTS) && go tool cover -html=coverage.out -o=coverage.html
cd $(DIST_RESULTS) && $(GO) tool cover -html=coverage.out -o=coverage.html
rm -f $(DIST_RESULTS)/*.cover.out
clean:
rm -Rf $(DIST_ROOT)
@go clean $(GOFLAGS) -i ./...
@$(GO) clean $(GOFLAGS) -i ./...
@if [ $(shell docker ps -a | grep -ci mattermost-mysql) -eq 1 ]; then \
echo stopping mattermost-mysql; \
@@ -124,7 +124,7 @@ run: install
@cd web/react && npm start &
@echo starting go web server
@go run $(GOFLAGS) mattermost.go -config=config.json &
@$(GO) run $(GOFLAGS) mattermost.go -config=config.json &
@echo starting compass watch
@cd web/sass-files && compass watch &
@@ -161,8 +161,8 @@ cleandb:
dist: install
@go build $(GOFLAGS) -i -a ./...
@go install $(GOFLAGS) -a ./...
@$(GO) build $(GOFLAGS) -i -a ./...
@$(GO) install $(GOFLAGS) -a ./...
mkdir -p $(DIST_PATH)/bin
cp $(GOPATH)/bin/platform $(DIST_PATH)/bin

Просмотреть файл

@@ -142,7 +142,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
go func() {
var thumbnail image.Image
if imgConfig.Width > int(utils.Cfg.ImageSettings.ThumbnailWidth) {
thumbnail = resize.Resize(utils.Cfg.ImageSettings.ThumbnailWidth, utils.Cfg.ImageSettings.ThumbnailHeight, img, resize.NearestNeighbor)
thumbnail = resize.Resize(utils.Cfg.ImageSettings.ThumbnailWidth, utils.Cfg.ImageSettings.ThumbnailHeight, img, resize.Lanczos3)
} else {
thumbnail = img
}
@@ -164,7 +164,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
go func() {
var preview image.Image
if imgConfig.Width > int(utils.Cfg.ImageSettings.PreviewWidth) {
preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.NearestNeighbor)
preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.Lanczos3)
} else {
preview = img
}

Просмотреть файл

@@ -36,7 +36,6 @@ module.exports = React.createClass({
this.resize();
this.processMentions();
this.updateTextdiv();
},
componentWillUnmount: function() {
PostStore.removeAddMentionListener(this._onChange);
@@ -87,7 +86,6 @@ module.exports = React.createClass({
this.processMentions();
this.doProcessMentions = false;
}
this.updateTextdiv();
this.resize();
},
componentWillReceiveProps: function(nextProps) {
@@ -117,17 +115,6 @@ module.exports = React.createClass({
});
}, 1);
},
updateTextdiv: function() {
var html = utils.insertHtmlEntities(this.refs.message.getDOMNode().value);
for (var k in this.mentions) {
var m = this.mentions[k];
var re = new RegExp('( |^)@' + m + '( |$|\n)', 'm');
html = html.replace(re, '$1<span class="mention">@'+m+'</span>$2');
}
var re2 = new RegExp('(^$)(?![.\n])', 'gm');
html = html.replace(re2, '<br/><br/>');
$(this.refs.textdiv.getDOMNode()).html(html);
},
handleChange: function() {
this.props.onUserInput(this.refs.message.getDOMNode().value);
this.resize();
@@ -181,7 +168,7 @@ module.exports = React.createClass({
}
},
processMentions: function() {
/* First, find all the possible mentions, highlight them in the HTML and add
/* First, find all the possible mentions and add
them all to a list of mentions */
var text = utils.insertHtmlEntities(this.refs.message.getDOMNode().value);
@@ -192,9 +179,7 @@ module.exports = React.createClass({
var matches = text.match(re1);
if (!matches) {
$(this.refs.textdiv.getDOMNode()).text(text);
this.updateMentionTab(null, []);
this.mentions = [];
return;
}
@@ -207,7 +192,7 @@ module.exports = React.createClass({
}
/* Figure out what the user is currently typing. If it's a mention then we don't
want to highlight it and add it to the mention list yet, so we remove it if
want to add it to the mention list yet, so we remove it if
there is only one occurence of that mention so far. */
var caret = utils.getCaretPosition(this.refs.message.getDOMNode());
@@ -225,14 +210,13 @@ module.exports = React.createClass({
typingMention = text.substring(atIndex+1, caret);
}
var re3 = new RegExp('@' + typingMention + '( |$|\n)', 'g');
var re2 = new RegExp('@' + typingMention + '( |$|\n)', 'g');
if ((text.match(re3) || []).length === 1 && mentions.indexOf(typingMention) !== -1) {
if ((text.match(re2) || []).length === 1 && mentions.indexOf(typingMention) !== -1) {
mentions.splice(mentions.indexOf(typingMention), 1);
}
this.updateMentionTab(null, mentions);
this.mentions = mentions;
},
checkForNewMention: function(text) {
var caret = utils.getCaretPosition(this.refs.message.getDOMNode());
@@ -287,15 +271,9 @@ module.exports = React.createClass({
elm.value = cmd;
this.handleChange();
},
scroll: function() {
var e = this.refs.message.getDOMNode();
var d = this.refs.textdiv.getDOMNode();
$(d).scrollTop($(e).scrollTop());
},
resize: function() {
var e = this.refs.message.getDOMNode();
var w = this.refs.wrapper.getDOMNode();
var d = this.refs.textdiv.getDOMNode();
var lht = parseInt($(e).css('lineHeight'),10);
var lines = e.scrollHeight / lht;
@@ -303,15 +281,11 @@ module.exports = React.createClass({
if (e.scrollHeight - mod < 167) {
$(e).css({'height':'auto','overflow-y':'hidden'}).height(e.scrollHeight - mod);
$(d).css({'height':'auto','overflow-y':'hidden'}).height(e.scrollHeight - mod);
$(w).css({'height':'auto'}).height(e.scrollHeight+2);
} else {
$(e).css({'height':'auto','overflow-y':'scroll'}).height(167);
$(d).css({'height':'auto','overflow-y':'scroll'}).height(167);
$(w).css({'height':'auto'}).height(167);
}
$(d).scrollTop($(e).scrollTop());
},
handleFocus: function() {
var elm = this.refs.message.getDOMNode();
@@ -332,8 +306,7 @@ module.exports = React.createClass({
return (
<div ref="wrapper" className="textarea-wrapper">
<CommandList ref='commands' addCommand={this.addCommand} channelId={this.props.channelId} />
<div className="form-control textarea-div" ref="textdiv"/>
<textarea id={this.props.id} ref="message" className={"form-control custom-textarea " + this.state.connection} spellCheck="true" autoComplete="off" autoCorrect="off" rows="1" placeholder={this.props.createMessage} value={this.props.messageText} onInput={this.handleChange} onChange={this.handleChange} onKeyPress={this.handleKeyPress} onKeyDown={this.handleKeyDown} onScroll={this.scroll} onFocus={this.handleFocus} onBlur={this.handleBlur} onPaste={this.handlePaste} />
<textarea id={this.props.id} ref="message" className={"form-control custom-textarea " + this.state.connection} spellCheck="true" autoComplete="off" autoCorrect="off" rows="1" placeholder={this.props.createMessage} value={this.props.messageText} onInput={this.handleChange} onChange={this.handleChange} onKeyPress={this.handleKeyPress} onKeyDown={this.handleKeyDown} onFocus={this.handleFocus} onBlur={this.handleBlur} onPaste={this.handlePaste} />
</div>
);
}

Просмотреть файл

@@ -721,13 +721,15 @@ var GeneralTab = React.createClass({
if(!this.submitActive) return;
if(this.state.picture.type !== "image/jpeg") {
this.setState({client_error: "Only JPG images may be used for profile pictures"});
var picture = this.state.picture;
if(picture.type !== "image/jpeg" && picture.type !== "image/png") {
this.setState({client_error: "Only JPG or PNG images may be used for profile pictures"});
return;
}
formData = new FormData();
formData.append('image', this.state.picture, this.state.picture.name);
formData.append('image', picture, picture.name);
client.uploadProfileImage(formData,
function(data) {