Authored by 盖剑秋

Image upload. reviewed by Redding.

@@ -53,6 +53,11 @@ import { @@ -53,6 +53,11 @@ import {
53 syncUser, 53 syncUser,
54 } from './reducers/home/homeActions'; 54 } from './reducers/home/homeActions';
55 55
  56 +import Immutable, {List, Record} from 'immutable';
  57 +
  58 +import {
  59 + startPosting,
  60 +} from './reducers/posting/postingActions';
56 61
57 /** 62 /**
58 * 63 *
@@ -164,6 +169,9 @@ export default function community(platform) { @@ -164,6 +169,9 @@ export default function community(platform) {
164 console.log(store.getState().posting); 169 console.log(store.getState().posting);
165 if (store.getState().posting.dataValid) { 170 if (store.getState().posting.dataValid) {
166 console.log('发送中。。。。。'); 171 console.log('发送中。。。。。');
  172 + Actions.pop();
  173 + console.log(store.getState().posting.assets.toJS());
  174 + store.dispatch(startPosting(store.getState().posting.assets.toJS()));
167 } else { 175 } else {
168 // 发布按钮: 176 // 发布按钮:
169 // 1.用户编辑内容时,“正文或标题”和“图片”其一必须有内容,否则右上角发布icon置灰,点击文本弹窗提示请输入内容。 177 // 1.用户编辑内容时,“正文或标题”和“图片”其一必须有内容,否则右上角发布icon置灰,点击文本弹窗提示请输入内容。
@@ -58,7 +58,12 @@ export default keyMirror({ @@ -58,7 +58,12 @@ export default keyMirror({
58 POSTING_BOARD_SUCCESS: null, 58 POSTING_BOARD_SUCCESS: null,
59 POSTING_BOARD_FAILURE: null, 59 POSTING_BOARD_FAILURE: null,
60 POSTING_BOARD_SELECTED: null, 60 POSTING_BOARD_SELECTED: null,
61 - POSTING_ASSETS_SELECTED:null,  
62 - POSTING_TITLE_EDITED:null,  
63 - POSTING_CONTENT_EDITED:null, 61 + POSTING_ASSETS_SELECTED: null,
  62 + POSTING_TITLE_EDITED: null,
  63 + POSTING_CONTENT_EDITED: null,
  64 + POSTING_POST_START: null,
  65 + POSTING_POST_FAILURE: null,
  66 + POSTING_UPLOAD_UPDATE: null,
  67 + POSTING_POST_FINISHED: null,
  68 + POSTING_STATE_RESET: null,
64 }); 69 });
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 8
9 import {Actions} from 'react-native-router-flux'; 9 import {Actions} from 'react-native-router-flux';
10 import PostingService from '../../services/PostingService'; 10 import PostingService from '../../services/PostingService';
  11 +import Immutable, {List, Record} from 'immutable';
11 12
12 const { 13 const {
13 POSTING_BOARD_REQUEST, 14 POSTING_BOARD_REQUEST,
@@ -17,6 +18,11 @@ const { @@ -17,6 +18,11 @@ const {
17 POSTING_ASSETS_SELECTED, 18 POSTING_ASSETS_SELECTED,
18 POSTING_TITLE_EDITED, 19 POSTING_TITLE_EDITED,
19 POSTING_CONTENT_EDITED, 20 POSTING_CONTENT_EDITED,
  21 + POSTING_POST_START,
  22 + POSTING_POST_FAILURE,
  23 + POSTING_UPLOAD_UPDATE,
  24 + POSTING_POST_FINISHED,
  25 + POSTING_STATE_RESET,
20 } = require('../../constants/actionTypes').default; 26 } = require('../../constants/actionTypes').default;
21 27
22 export function titleEdited(title) { 28 export function titleEdited(title) {
@@ -60,6 +66,109 @@ export function getBoardFailure(error) { @@ -60,6 +66,109 @@ export function getBoardFailure(error) {
60 } 66 }
61 } 67 }
62 68
  69 +export function postStart() {
  70 + return {
  71 + type: POSTING_POST_START,
  72 + }
  73 +}
  74 +
  75 +export function uploadImageStateChanged(payloadData) {
  76 + return {
  77 + type: POSTING_UPLOAD_UPDATE,
  78 + payload:payloadData,
  79 + }
  80 +}
  81 +
  82 +export function postFinished(success) {
  83 + return {
  84 + type:POSTING_POST_FINISHED,
  85 + payload:success,
  86 + }
  87 +}
  88 +
  89 +export function updateUploadState(url,fileName) {
  90 +
  91 + return (dispatch, getState) => {
  92 +
  93 + let {posting} = getState();
  94 +
  95 + let assets = posting.assets.toJS();
  96 + for (var i = 0; i < assets.length; i++) {
  97 + if (assets[i].name == fileName) {
  98 + assets[i].webURL = url;
  99 + assets[i].finished = true;
  100 + }
  101 + }
  102 + let finishCount = posting.finishedCount;
  103 + finishCount++;
  104 + let percent = parseFloat(finishCount)/assets.length;
  105 + console.log(percent);
  106 + let payloadData = {assets,finishCount,percent};
  107 + dispatch(uploadImageStateChanged(payloadData));
  108 +
  109 + dispatch(() => {
  110 + let {posting} = getState();
  111 + if (posting.postPercent == 1) {
  112 + let assets = posting.assets.toJS();
  113 + let imageStr = '';
  114 + for (let i = 0; i < assets.length; i++) {
  115 + imageStr += assets[i].webURL+',';
  116 + }
  117 + let param = {
  118 + postTitle: posting.title,
  119 + uid: '111213',
  120 + forumCode: posting.currentBoardId,
  121 + contentData: posting.content,
  122 + images: imageStr,
  123 + }
  124 +
  125 + return new PostingService().commitPost(param).then(json => {
  126 + console.log(json);
  127 + dispatch(postFinished(true));
  128 + dispatch(resetState());
  129 + }).catch(error => {
  130 + dispatch(postFinished(false));
  131 + })
  132 + }
  133 + });
  134 + }
  135 +}
  136 +
  137 +export function resetState() {
  138 + return {
  139 + type: POSTING_STATE_RESET,
  140 + }
  141 +}
  142 +
  143 +export function postFail() {
  144 + return {
  145 + type: POSTING_POST_FAILURE,
  146 + }
  147 +}
  148 +
  149 +export function startPosting(assets) {
  150 +
  151 + return dispatch => {
  152 + dispatch(postStart());
  153 + for (let i = 0; i < assets.length; i++) {
  154 + let asset = assets[i]
  155 + if (asset.finished) {
  156 + continue;
  157 + }
  158 + new PostingService().uploadImageAsset(asset)
  159 + .then(response => {
  160 + console.log(response);
  161 + dispatch(updateUploadState(response,asset.name));
  162 + }).catch(error => {
  163 +
  164 + console.log(error);
  165 + dispatch(postFail());
  166 + });
  167 + }
  168 + }
  169 +
  170 +}
  171 +
63 export function getBoardList() { 172 export function getBoardList() {
64 return dispatch => { 173 return dispatch => {
65 dispatch(getBoardRequest()); 174 dispatch(getBoardRequest());
@@ -25,6 +25,10 @@ let InitialState = Record({ @@ -25,6 +25,10 @@ let InitialState = Record({
25 boards: List(), 25 boards: List(),
26 assets: List(), 26 assets: List(),
27 dataValid:false, //是否可以点击发送 27 dataValid:false, //是否可以点击发送
  28 + inPosting:false,//正在上传
  29 + postFail: false,
  30 + finishedCount:0,
  31 + postPercent:0,
28 }); 32 });
29 33
30 export default InitialState; 34 export default InitialState;
@@ -20,6 +20,11 @@ const { @@ -20,6 +20,11 @@ const {
20 POSTING_ASSETS_SELECTED, 20 POSTING_ASSETS_SELECTED,
21 POSTING_TITLE_EDITED, 21 POSTING_TITLE_EDITED,
22 POSTING_CONTENT_EDITED, 22 POSTING_CONTENT_EDITED,
  23 + POSTING_POST_START,
  24 + POSTING_POST_FAILURE,
  25 + POSTING_UPLOAD_UPDATE,
  26 + POSTING_POST_FINISHED,
  27 + POSTING_STATE_RESET,
23 } = require('../../constants/actionTypes').default; 28 } = require('../../constants/actionTypes').default;
24 29
25 const initialState = new InitialState; 30 const initialState = new InitialState;
@@ -34,6 +39,11 @@ export default function postingReducer(state = initialState, action) { @@ -34,6 +39,11 @@ export default function postingReducer(state = initialState, action) {
34 39
35 switch (action.type) { 40 switch (action.type) {
36 41
  42 + case POSTING_STATE_RESET: {
  43 + return initialState;
  44 + }
  45 +
  46 + break;
37 case POSTING_TITLE_EDITED: { 47 case POSTING_TITLE_EDITED: {
38 let dataValid=false; 48 let dataValid=false;
39 if (action.payload.length) { 49 if (action.payload.length) {
@@ -92,6 +102,38 @@ export default function postingReducer(state = initialState, action) { @@ -92,6 +102,38 @@ export default function postingReducer(state = initialState, action) {
92 } 102 }
93 103
94 break; 104 break;
  105 +
  106 + case POSTING_POST_START: {
  107 +
  108 + let nextState = state.set('inPosting',true).set('postFail',false);
  109 + return nextState;
  110 + }
  111 +
  112 + break;
  113 +
  114 + case POSTING_UPLOAD_UPDATE: {
  115 +
  116 + let {assets,finishCount,percent} = action.payload;
  117 + let nextState = state.set('assets',Immutable.fromJS(assets))
  118 + .set('finishedCount',finishCount)
  119 + .set('postPercent',percent);
  120 + return nextState;
  121 + }
  122 +
  123 + break;
  124 + case POSTING_POST_FAILURE: {
  125 + let nextState = state.set('inPosting',false).set('postFail',true);
  126 + return nextState;
  127 + }
  128 +
  129 + break;
  130 + case POSTING_POST_FINISHED: {
  131 + let success = action.payload;
  132 + let nextState = state.set('inPosting',!success).set('postFail',!success);
  133 + return nextState;
  134 + }
  135 +
  136 + break;
95 default: 137 default:
96 138
97 break; 139 break;
1 'use strict' 1 'use strict'
2 2
  3 +
  4 +import {Platform, Dimensions, NativeModules, CameraRoll,} from 'react-native';
  5 +import DeviceInfo from 'react-native-device-info';
  6 +import queryString from 'query-string';
  7 +import RNNativeConfig from '../../common/services/RNNativeConfig';
  8 +
  9 +
3 import Request from '../../common/services/Request'; 10 import Request from '../../common/services/Request';
4 11
5 export default class PostingService { 12 export default class PostingService {
@@ -20,4 +27,67 @@ export default class PostingService { @@ -20,4 +27,67 @@ export default class PostingService {
20 throw(error); 27 throw(error);
21 }); 28 });
22 } 29 }
  30 +
  31 + async commitPost(param) {
  32 +
  33 + return await this.api.get({
  34 +
  35 + url: '',
  36 + body: {
  37 + method: 'app.social.addPost',
  38 + ...param,
  39 + }
  40 +
  41 + }).then((json) => {
  42 + return json;
  43 + }).catch((error) => {
  44 + throw(error);
  45 + })
  46 + }
  47 +
  48 + async uploadImageAsset(asset) {
  49 +
  50 + let formData = new FormData();
  51 + formData.append('project','social');//for community ....
  52 + formData.append('fileData',{name:asset.node.image.name,type: 'image/jpeg','uri':asset.node.image.url});
  53 +
  54 +
  55 + let app_version = DeviceInfo.getBuildNumber();
  56 + let os_version = DeviceInfo.getSystemVersion();
  57 + let client_type = Platform.OS === 'ios' ? 'iphone' : 'android';
  58 + let {height, width} = Dimensions.get('window');
  59 + let screen_size = width + 'x' + height;
  60 + let privateKey = RNNativeConfig.getPrivateKey();
  61 +
  62 + formData.append('app_version',app_version);
  63 + formData.append('os_version',os_version);
  64 + formData.append('client_type',client_type);
  65 + formData.append('screen_size',width + 'x' + height);
  66 + formData.append('privateKey',privateKey);
  67 +
  68 +
  69 + let options = {};
  70 + options.body = formData;
  71 + options.method = 'post';
  72 + options.headers = {'project':'social',HTTP_REFERER:'admin.yohobuy.com'};
  73 +
  74 + return await fetch('http://upload.static.yohobuy.com', options)
  75 + .then((response) => {
  76 +
  77 + return response.json().then(
  78 + (json) => {
  79 + console.log(json);
  80 + if (json.code == 200) {
  81 + return json.data.imagesList[0];
  82 + }else {
  83 + throw(json);
  84 + }
  85 + }
  86 + )
  87 +
  88 +
  89 + }).catch((error) => {
  90 + throw(error);
  91 + });
  92 + }
23 } 93 }