package adonai.diary_browser; import android.annotation.SuppressLint; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Pair; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.MultiAutoCompleteTextView; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; import com.afollestad.materialdialogs.AlertDialogWrapper; import com.afollestad.materialdialogs.MaterialDialog; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.j256.ormlite.dao.RuntimeExceptionDao; import com.j256.ormlite.stmt.SelectArg; import com.squareup.okhttp.Headers; import com.squareup.okhttp.MultipartBuilder; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.regex.Matcher; import java.util.regex.Pattern; import adonai.diary_browser.database.DbProvider; import adonai.diary_browser.entities.AutocompleteItem; import adonai.diary_browser.pages.Comment; import adonai.diary_browser.adapters.DraftListArrayAdapter; import adonai.diary_browser.dto.ImgurImageResponse; import adonai.diary_browser.dto.PleerEmbedAnswer; import adonai.diary_browser.dto.PleerUploadAnswer; import adonai.diary_browser.pages.Post; import adonai.diary_browser.pages.Umail; import adonai.diary_browser.misc.FileUtils; import adonai.diary_browser.misc.SemicolonTokenizer; import pl.droidsonroids.gif.GifDrawable; import pl.droidsonroids.gif.GifImageButton; /** * Основной фрагмент посылки сообщения. Такой фрагмент присутствует в каждой {@link DiaryActivity}. * Отвечает за посылку и редактирование постов/комментариев/U-Mail с произвольными параметрами, * а также вставку смайлов и других объектов. * <p/> * <i>Замечание: содержит в себе асинхронный обработчик для посылки/приёма сообщений с сайта и отслеживания статуса</i> * * @see DiaryListActivity * @see UmailListActivity * * @author Адонай * * @// TODO: Добавить возможность отмены посылки поста/комментария */ public class MessageSenderFragment extends Fragment implements OnClickListener, OnCheckedChangeListener, android.widget.RadioGroup.OnCheckedChangeListener { // команды внутренним хэндлерам private static final int HANDLE_DO_POST = 0; private static final int HANDLE_DO_COMMENT = 1; private static final int HANDLE_DO_UMAIL = 2; private static final int HANDLE_UMAIL_ACK = 3; private static final int HANDLE_UMAIL_REJ = 4; private static final int HANDLE_REQUEST_AVATARS = 5; private static final int HANDLE_SET_AVATAR = 6; private static final int HANDLE_PROGRESS = 8; private static final int HANDLE_GET_SMILIES = 9; private static final int HANDLE_GET_DRAFTS = 10; private static final int HANDLE_CONN_ERROR = -1; static Pattern EMAIL_ANSWER_REGEX = Pattern.compile("Re\\[(\\d+)\\]: (.*)"); BroadcastReceiver mPaneStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case Utils.CLOSING_PANE_BROADCAST: // выключаем смайлики setSmiliesState(false); break; case Utils.OPENING_PANE_BROADCAST: // включаем смайлики setSmiliesState(true); break; } } }; Handler.Callback UiCallback = new Handler.Callback() { @SuppressWarnings("unchecked") public boolean handleMessage(Message message) { switch (message.what) { case HANDLE_DO_POST: case HANDLE_DO_COMMENT: { // Пост опубликован, возвращаемся pd.dismiss(); closeMe(true); break; } case HANDLE_GET_DRAFTS: { pd.dismiss(); final List<Post> drafts = (List<Post>) message.obj; if(drafts == null) { Toast.makeText(getActivity(), getString(R.string.connection_error), Toast.LENGTH_SHORT).show(); break; } if(drafts.isEmpty()) { Toast.makeText(getActivity(), getString(R.string.no_drafts), Toast.LENGTH_SHORT).show(); break; } AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); ListAdapter adapter = new DraftListArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, drafts); builder.setAdapter(adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final Post clicked = drafts.get(which); // выбираем действие - удалить или редактировать AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); builder.setPositiveButton(R.string.edit, new DialogInterface.OnClickListener() { // редактировать @Override public void onClick(DialogInterface dialog, int which) { // http://xxxx.diary.ru/?editpost&postid=#######&draft String editUrl = clicked.url.substring(0, clicked.url.lastIndexOf('/') + 1) + "?editpost&postid=" + clicked.postID + "&draft"; ((DiaryActivity) getActivity()).handleBackground(Utils.HANDLE_EDIT_POST, editUrl); } }).setNegativeButton(R.string.delete, new DialogInterface.OnClickListener() { // удалить @Override public void onClick(DialogInterface dialog, int which) { // диалог подтверждения AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); builder.setTitle(android.R.string.dialog_alert_title).setCancelable(false).setMessage(R.string.really_delete); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ((DiaryActivity) getActivity()).handleBackground(Utils.HANDLE_DELETE_POST_DRAFT, clicked.postID); } }).setNegativeButton(android.R.string.no, null).create().show(); } }).setTitle(R.string.select_action).create().show(); } }).setTitle(R.string.select_draft).create().show(); break; } case HANDLE_UMAIL_ACK: { pd.dismiss(); AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); builder.setTitle(android.R.string.ok).setCancelable(false).setMessage(R.string.message_send_ok); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { closeMe(false); } }); builder.create().show(); break; } case HANDLE_UMAIL_REJ: { pd.dismiss(); AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); builder.setTitle(android.R.string.no).setCancelable(false).setMessage(R.string.message_send_error); builder.setPositiveButton(android.R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { closeMe(false); } }); builder.create().show(); break; } case HANDLE_REQUEST_AVATARS: { for (int i = 0; i < avatarMap.size(); i++) { ImageButton current = new ImageButton(getActivity()); current.setImageDrawable((Drawable) avatarMap.valueAt(i)); current.setTag(R.integer.avatar_id, avatarMap.keyAt(i)); current.setOnClickListener(MessageSenderFragment.this); mAvatars.addView(current); } pd.dismiss(); break; } case Utils.HANDLE_UPLOAD_FILE: case Utils.HANDLE_UPLOAD_MUSIC: case Utils.HANDLE_UPLOAD_GIF: { int cursorPos = contentText.getSelectionStart(); contentText.setText(contentText.getText().toString().substring(0, cursorPos) + message.obj + contentText.getText().toString().substring(cursorPos, contentText.getText().length())); contentText.setSelection(contentText.getText().toString().indexOf("/>", cursorPos)); break; } case HANDLE_PROGRESS: pd.setProgress((int) message.obj); break; case HANDLE_GET_SMILIES: Elements smileLinks = (Elements) message.obj; DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); mSmilies.removeAllViews(); for (Map.Entry<String, Object> smile : smileMap.entrySet()) { GifDrawable gif = (GifDrawable) smile.getValue(); gif.start(); GifImageButton current = new GifImageButton(getActivity()); current.setTag(R.integer.smile_key, smile.getKey()); int maxImageHeight = (int) (gif.getIntrinsicHeight() * dm.density); int maxImageWidth = (int) (gif.getIntrinsicWidth() * dm.density); current.setScaleType(ImageView.ScaleType.MATRIX); Matrix matrix = new Matrix(); matrix.setScale(dm.density, dm.density); // увеличим размеры смайликов current.setImageMatrix(matrix); current.setImageDrawable(gif); current.setMinimumHeight(maxImageHeight + current.getPaddingTop() + current.getPaddingBottom()); current.setMinimumWidth(maxImageWidth + current.getPaddingLeft() + current.getPaddingRight()); current.setOnClickListener(MessageSenderFragment.this); mSmilies.addView(current); } mSmilieButtons.removeAllViews(); for (Element link : smileLinks) { if (link.text().isEmpty()) continue; Button current = new Button(getActivity()); current.setTag(R.integer.smile_page, link.attr("href")); current.setText(link.text()); current.setOnClickListener(MessageSenderFragment.this); mSmilieButtons.addView(current); } pd.dismiss(); break; case HANDLE_CONN_ERROR: Toast.makeText(getActivity(), getString(R.string.connection_error), Toast.LENGTH_SHORT).show(); pd.dismiss(); break; default: break; } return true; } }; private Button mPublish, mSaveDraft, mLoadDraft; private Button mShowSmilies; private EditText toText; private EditText titleText; private EditText contentText; private EditText requoteText; private MultiAutoCompleteTextView themesText; private MultiAutoCompleteTextView musicText; private MultiAutoCompleteTextView moodText; private CheckBox mShowOptionals; private CheckBox mShowPoll; private CheckBox mSubscribe; private CheckBox mShowCloseOptions; private CheckBox mGetReceipt; private CheckBox mRequote; private CheckBox mCopyMessage; private CheckBox mCustomAvatar; private CheckBox mNoComments; private RadioGroup mSecureOptions; private TextView mTitle; private TextView mCurrentPage; private EditText mUserLogin; private EditText mUserPassword; private EditText mPollTitle; private EditText mPollChoice1; private EditText mPollChoice2; private EditText mPollChoice3; private EditText mPollChoice4; private EditText mPollChoice5; private EditText mPollChoice6; private EditText mPollChoice7; private EditText mPollChoice8; private EditText mPollChoice9; private EditText mPollChoice10; private EditText mCloseAllowList; private EditText mCloseDenyList; private EditText mCloseText; private RadioGroup mCloseOpts; private Handler mHandler, mUiHandler; private Looper mLooper; private MaterialDialog pd; private LinearLayout mAvatars, mOptionals, mPoll, mSmilies, mSmilieButtons, mPredefinedThemes, mMainLayout, mAsUserLayout; private List<View> postElements = new ArrayList<>(); private List<View> commentElements = new ArrayList<>(); private List<View> umailElements = new ArrayList<>(); private List<Pair<String, String>> postParams; private String mSignature; private NetworkService mService; private SparseArray<Object> avatarMap; private Map<String, Object> smileMap; private DiaryHttpClient mHttpClient; private SharedPreferences mSharedPrefs; Handler.Callback HttpCallback = new Handler.Callback() { @SuppressWarnings("unchecked") public boolean handleMessage(Message message) { try { switch (message.what) { case HANDLE_DO_POST: case HANDLE_DO_COMMENT: { mHttpClient.postPageToString(postParams); mUiHandler.sendEmptyMessage(message.what); return true; } case HANDLE_DO_UMAIL: { String result = mHttpClient.postPageToString(postParams); if (result.contains("Письмо отправлено")) mUiHandler.sendEmptyMessage(HANDLE_UMAIL_ACK); else mUiHandler.sendEmptyMessage(HANDLE_UMAIL_REJ); return true; } case HANDLE_GET_SMILIES: { String url = message.obj != null ? (String) message.obj : "http://www.diary.ru/smile.php"; String urlValid = url.replaceAll("[:/]", "_"); // не содержащее недопустимых символов для ФС имя String result; if (mCache.hasData(getActivity(), urlValid)) result = new String(mCache.retrieveData(getActivity(), urlValid)); else { result = mHttpClient.getPageAsString(url); if(result == null) { mUiHandler.sendEmptyMessage(HANDLE_CONN_ERROR); return true; } mCache.cacheData(getActivity(), result.getBytes(), urlValid); } Document rootNode = Jsoup.parse(result); Elements smilies = rootNode.select("tr img"); Elements smileLinks = rootNode.select("ul a"); smileMap = new HashMap<>(); for (Element smilie : smilies) smileMap.put(smilie.attr("alt"), smilie.attr("src")); // распараллеливаем получение смайликов // в массиве теперь будет храниться строка вызова смайлика - задача загрузки аватара ExecutorService executor = Executors.newFixedThreadPool(smileMap.size()); for (String id : smileMap.keySet()) { final String smileUrl = (String) smileMap.get(id); FutureTask<Drawable> future = new FutureTask<>(new Callable<Drawable>() { @Override public Drawable call() throws Exception { String name = smileUrl.substring(smileUrl.lastIndexOf('/') + 1); byte[] outputBytes; if (mCache.hasData(getActivity(), name)) outputBytes = mCache.retrieveData(getActivity(), name); else { outputBytes = mHttpClient.getPageAsByteArray(smileUrl); // caching image mCache.cacheData(getActivity(), outputBytes, name); } return new GifDrawable(outputBytes); } }); smileMap.put(id, future); executor.execute(future); } // по мере выполнения задач переписываем массив по кусочкам на результат задачи // хак для того, чтобы всё работало в одном потоке while (true) { int remaining = 0; for (String id : smileMap.keySet()) if (smileMap.get(id) instanceof FutureTask) { FutureTask<Drawable> future = (FutureTask<Drawable>) smileMap.get(id); if (future.isDone()) smileMap.put(id, future.get()); else remaining++; } if (remaining == 0) break; } mUiHandler.sendMessage(mUiHandler.obtainMessage(HANDLE_GET_SMILIES, smileLinks)); return true; } case HANDLE_REQUEST_AVATARS: { String url = "http://www.diary.ru/options/member/?avatar"; String dataPage = mHttpClient.getPageAsString(url); if (dataPage == null) return false; // собираем пары ID аватара - url аватара Elements avatardivs = Jsoup.parse(dataPage).select("div#avatarbit"); avatarMap = new SparseArray<>(); for (Element avatarbit : avatardivs) { Integer avId = Integer.valueOf(avatarbit.select("input[name=use_avatar_id]").val()); String imageUrl = avatarbit.child(0).attr("style"); imageUrl = imageUrl.substring(imageUrl.lastIndexOf('(') + 1, imageUrl.lastIndexOf(')')); avatarMap.put(avId, imageUrl); } // распараллеливаем получение аватарок // в массиве теперь будет храниться ID аватара - задача загрузки аватара ExecutorService executor = Executors.newFixedThreadPool(avatarMap.size()); for (int i = 0; i < avatarMap.size(); i++) { final String imageUrl = (String) avatarMap.valueAt(i); FutureTask<Drawable> future = new FutureTask<>(new Callable<Drawable>() { @Override public Drawable call() throws Exception { final byte[] imageBytes = mHttpClient.getPageAsByteArray(imageUrl); Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); return new BitmapDrawable(getResources(), image); } }); avatarMap.setValueAt(i, future); executor.execute(future); } // по мере выполнения задач переписываем массив по кусочкам на результат задачи // хак для того, чтобы всё работало в одном потоке while (true) { int remaining = 0; for (int i = 0; i < avatarMap.size(); i++) if (avatarMap.valueAt(i) instanceof FutureTask) { FutureTask<Drawable> future = (FutureTask<Drawable>) avatarMap.valueAt(i); if (future.isDone()) avatarMap.setValueAt(i, future.get()); else remaining++; } if (remaining == 0) break; } mUiHandler.sendEmptyMessage(HANDLE_REQUEST_AVATARS); return true; } case HANDLE_GET_DRAFTS: { String url = mHttpClient.getCurrentUrl() + "?draft"; String dataPage = mHttpClient.getPageAsString(url); if (dataPage == null) { // ошибка соединения mUiHandler.sendMessage(mUiHandler.obtainMessage(message.what, null)); return false; } Elements posts = Jsoup.parse(dataPage).select("#postsArea > [id~=post\\d+]"); List<Post> drafts = new ArrayList<>(posts.size()); if(posts.isEmpty()) { // нет черновиков? mUiHandler.sendMessage(mUiHandler.obtainMessage(message.what, drafts)); return false; } for(Element post : posts) { Post draft = new Post(); draft.date = post.select(".postTitle > span").attr("title"); draft.title = post.select(".postTitle h2").text(); String fullContent = post.select(".postContent .postInner .paragraph").text(); draft.content = fullContent.substring(0, fullContent.length() > 100 ? 100 : fullContent.length()); draft.postID = post.id().substring(4); // после post##### draft.url = post.select(".postLinksBackg .urlLink a").attr("href"); drafts.add(draft); } mUiHandler.sendMessage(mUiHandler.obtainMessage(message.what, drafts)); return true; } case HANDLE_SET_AVATAR: { String URL = "http://www.diary.ru/options/member/?avatar"; mHttpClient.postPageToString(URL, postParams); Toast.makeText(getActivity(), R.string.avatar_selected, Toast.LENGTH_SHORT).show(); return true; } case Utils.HANDLE_UPLOAD_MUSIC: { File file = new File((String) message.obj); mHttpClient.getPage(URI.create("http://pleer.com/upload")); long length = file.length(); final DiaryHttpClient.ProgressListener listener = new SendProgressListener(length); MultipartBuilder mpEntityBuilder = new MultipartBuilder(); mpEntityBuilder.type(MultipartBuilder.FORM) .addFormDataPart("module", "photolib") .addFormDataPart("signature", mSignature) .addFormDataPart("resulttype1", String.valueOf(message.arg1)) .addFormDataPart("file", file.getName(), new DiaryHttpClient.CountingFileRequestBody(file, listener)); String progressId = ""; for (int i = 0; i < 8; ++i) { progressId += (int) Math.ceil(Math.random() * 100000); } String str = mHttpClient.postPageToString("http://pleer.com/upload/send?X-Progress-ID=" + progressId, mpEntityBuilder.build()); if(str == null) { Toast.makeText(getActivity(), getString(R.string.message_send_error), Toast.LENGTH_LONG).show(); pd.dismiss(); break; } Gson pleerGson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .create(); // check if upload was success PleerUploadAnswer uploadAnswer = pleerGson.fromJson(str, PleerUploadAnswer.class); if(!uploadAnswer.isCorrectFile()) { Toast.makeText(getActivity(), getString(R.string.pp_wrong_file), Toast.LENGTH_LONG).show(); pd.dismiss(); break; } if(!uploadAnswer.isCorrectName()) { Toast.makeText(getActivity(), getString(R.string.pp_wrong_name), Toast.LENGTH_LONG).show(); pd.dismiss(); break; } MultipartBuilder embedBody = new MultipartBuilder() .type(MultipartBuilder.FORM) .addFormDataPart("id", uploadAnswer.getLink()); String embedStr = mHttpClient.postPageToString("http://pleer.com/site_api/embed/track", embedBody.build()); if(embedStr == null) { Toast.makeText(getActivity(), getString(R.string.message_send_error), Toast.LENGTH_LONG).show(); pd.dismiss(); break; } PleerEmbedAnswer embedAnswer = pleerGson.fromJson(embedStr, PleerEmbedAnswer.class); if(!embedAnswer.isSuccess()) { Toast.makeText(getActivity(), getString(R.string.embed_error), Toast.LENGTH_LONG).show(); pd.dismiss(); break; } InputStream is = getResources().getAssets().open("plaintext/prostopleer_embed.html"); String htmlToEmbed = String.format(Utils.getStringFromInputStream(is), embedAnswer.getEmbedId(), message.arg1 == 2 ? "grey" : "black", embedAnswer.getEmbedId(), message.arg1 == 2 ? "grey" : "black", uploadAnswer.getLink(), embedAnswer.getName()); mUiHandler.sendMessage(mUiHandler.obtainMessage(Utils.HANDLE_UPLOAD_MUSIC, htmlToEmbed)); pd.dismiss(); break; } case Utils.HANDLE_UPLOAD_GIF: { File gifImage = new File((String) message.obj); long length = gifImage.length(); final DiaryHttpClient.ProgressListener listener = new SendProgressListener(length); Headers authHeaders = new Headers.Builder() .add("Authorization", Utils.IMGUR_CLIENT_AUTH) .build(); MultipartBuilder mpEntityBuilder = new MultipartBuilder(); mpEntityBuilder.type(MultipartBuilder.FORM) .addFormDataPart("title", gifImage.getName()) .addFormDataPart("type", "file") .addFormDataPart("image", gifImage.getName(), new DiaryHttpClient.CountingFileRequestBody(gifImage, listener)); String result = mHttpClient.postPageToString(Utils.IMGUR_API_ENDPOINT + "image", mpEntityBuilder.build(), authHeaders); ImgurImageResponse response = new Gson().fromJson(result, ImgurImageResponse.class); if(!response.success) { Toast.makeText(getActivity(), getString(R.string.message_send_error), Toast.LENGTH_LONG).show(); pd.dismiss(); break; } int width = message.arg1 * 100; // 100 / 200 / 300 double rate = width / (float) response.data.width; int height = (int) (response.data.height * rate); String toPaste = String.format("<img width='%d' height='%d' src='%s' />", width, height, response.data.link); mUiHandler.sendMessage(mUiHandler.obtainMessage(Utils.HANDLE_UPLOAD_GIF, toPaste)); pd.dismiss(); break; } case Utils.HANDLE_UPLOAD_FILE: { try { File file = new File((String) message.obj); long length = file.length(); final DiaryHttpClient.ProgressListener listener = new SendProgressListener(length); MultipartBuilder mpEntityBuilder = new MultipartBuilder(); mpEntityBuilder.type(MultipartBuilder.FORM) .addFormDataPart("module", "photolib") .addFormDataPart("signature", mSignature) .addFormDataPart("resulttype1", String.valueOf(message.arg1)) .addFormDataPart("attachment1", URLEncoder.encode(file.getName(), "windows-1251"), new DiaryHttpClient.CountingFileRequestBody(file, listener)); String result = mHttpClient.postPageToString("http://www.diary.ru/diary.php?upload=1&js", mpEntityBuilder.build()); if (result != null) { if (result.contains("допустимые:")) // ошибка отправки, слишком большая картинка Toast.makeText(getActivity(), getString(R.string.too_big_picture), Toast.LENGTH_LONG).show(); else { result = result.substring(result.indexOf("'") + 1, result.indexOf("';")); if (result.length() > 0) mUiHandler.sendMessage(mUiHandler.obtainMessage(Utils.HANDLE_UPLOAD_FILE, result)); else Toast.makeText(getActivity(), getString(R.string.message_send_error), Toast.LENGTH_LONG).show(); } //resEntity.consumeContent(); } else { Toast.makeText(getActivity(), getString(R.string.message_send_error), Toast.LENGTH_LONG).show(); } pd.dismiss(); } catch (Exception e) { Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } return true; } default: break; } } catch (Exception ignored) { mUiHandler.sendEmptyMessage(HANDLE_CONN_ERROR); } return false; } }; Comment mPost; CacheManager mCache = CacheManager.getInstance(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View sender = inflater.inflate(R.layout.fragment_message_sender, container, false); mSharedPrefs = getActivity().getSharedPreferences(Utils.mPrefsFile, Context.MODE_PRIVATE); mPost = new Post(); postParams = new ArrayList<>(); HandlerThread thr = new HandlerThread("ServiceThread"); thr.start(); mLooper = thr.getLooper(); mHandler = new Handler(mLooper, HttpCallback); mUiHandler = new Handler(UiCallback); IntentFilter paneActionsFilter = new IntentFilter(); paneActionsFilter.addAction(Utils.OPENING_PANE_BROADCAST); paneActionsFilter.addAction(Utils.CLOSING_PANE_BROADCAST); LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mPaneStateReceiver, paneActionsFilter); mMainLayout = (LinearLayout) sender.findViewById(R.id.message_main_layout); toText = (EditText) sender.findViewById(R.id.message_to); mGetReceipt = (CheckBox) sender.findViewById(R.id.message_getreceipt); mRequote = (CheckBox) sender.findViewById(R.id.message_requote); mRequote.setOnCheckedChangeListener(this); mCopyMessage = (CheckBox) sender.findViewById(R.id.message_copy); titleText = (EditText) sender.findViewById(R.id.message_title); contentText = (EditText) sender.findViewById(R.id.message_content); requoteText = (EditText) sender.findViewById(R.id.message_requote_content); themesText = (MultiAutoCompleteTextView) sender.findViewById(R.id.message_themes); themesText.setTokenizer(new SemicolonTokenizer()); musicText = (MultiAutoCompleteTextView) sender.findViewById(R.id.message_music); musicText.setTokenizer(new SemicolonTokenizer()); moodText = (MultiAutoCompleteTextView) sender.findViewById(R.id.message_mood); moodText.setTokenizer(new SemicolonTokenizer()); mPublish = (Button) sender.findViewById(R.id.message_publish); mPublish.setOnClickListener(this); mSaveDraft = (Button) sender.findViewById(R.id.message_save_draft); mSaveDraft.setOnClickListener(this); mLoadDraft = (Button) sender.findViewById(R.id.message_load_draft); mLoadDraft.setOnClickListener(this); mTitle = (TextView) sender.findViewById(R.id.fragment_title); mCurrentPage = (TextView) sender.findViewById(R.id.fragment_page); final LinearLayout specials = (LinearLayout) sender.findViewById(R.id.message_specials); for (int i = 0; i < specials.getChildCount(); ++i) specials.getChildAt(i).setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { int cursorPos = contentText.getSelectionStart(); if (cursorPos == -1) cursorPos = contentText.getText().length(); String toPaste = ((Button) view).getText().toString(); contentText.setText(contentText.getText().toString().substring(0, cursorPos) + toPaste + contentText.getText().toString().substring(cursorPos, contentText.getText().length())); contentText.setSelection(contentText.getText().toString().indexOf(toPaste, cursorPos) + 1); } }); mPollTitle = (EditText) sender.findViewById(R.id.message_poll_title); mPollChoice1 = (EditText) sender.findViewById(R.id.message_poll_1); mPollChoice2 = (EditText) sender.findViewById(R.id.message_poll_2); mPollChoice3 = (EditText) sender.findViewById(R.id.message_poll_3); mPollChoice4 = (EditText) sender.findViewById(R.id.message_poll_4); mPollChoice5 = (EditText) sender.findViewById(R.id.message_poll_5); mPollChoice6 = (EditText) sender.findViewById(R.id.message_poll_6); mPollChoice7 = (EditText) sender.findViewById(R.id.message_poll_7); mPollChoice8 = (EditText) sender.findViewById(R.id.message_poll_8); mPollChoice9 = (EditText) sender.findViewById(R.id.message_poll_9); mPollChoice10 = (EditText) sender.findViewById(R.id.message_poll_10); mCloseOpts = (RadioGroup) sender.findViewById(R.id.close_opts); mCloseOpts.setOnCheckedChangeListener(this); mCloseAllowList = (EditText) sender.findViewById(R.id.close_allowed_list); mCloseDenyList = (EditText) sender.findViewById(R.id.close_denied_list); mCloseText = (EditText) sender.findViewById(R.id.close_text); mNoComments = (CheckBox) sender.findViewById(R.id.message_no_comments); mCustomAvatar = (CheckBox) sender.findViewById(R.id.message_custom_avatar); mAvatars = (LinearLayout) sender.findViewById(R.id.message_avatars); mCustomAvatar.setOnCheckedChangeListener(this); mShowOptionals = (CheckBox) sender.findViewById(R.id.message_optional); mShowOptionals.setOnCheckedChangeListener(this); mOptionals = (LinearLayout) sender.findViewById(R.id.optionals_layout); mShowPoll = (CheckBox) sender.findViewById(R.id.message_poll); mShowPoll.setOnCheckedChangeListener(this); mPoll = (LinearLayout) sender.findViewById(R.id.poll_layout); mSubscribe = (CheckBox) sender.findViewById(R.id.message_subscribe); mShowCloseOptions = (CheckBox) sender.findViewById(R.id.message_close); mShowCloseOptions.setOnCheckedChangeListener(this); mSecureOptions = (RadioGroup) sender.findViewById(R.id.message_security); mSecureOptions.setOnCheckedChangeListener(this); mUserLogin = (EditText) sender.findViewById(R.id.as_user_login); mUserPassword = (EditText) sender.findViewById(R.id.as_user_password); mAsUserLayout = (LinearLayout) sender.findViewById(R.id.as_user_layout); mShowSmilies = (Button) sender.findViewById(R.id.message_show_smilies); mShowSmilies.setOnClickListener(this); mSmilies = (LinearLayout) sender.findViewById(R.id.message_smilies); mSmilieButtons = (LinearLayout) sender.findViewById(R.id.message_smilies_types); mPredefinedThemes = (LinearLayout) sender.findViewById(R.id.message_predef_themes); commentElements.add(mSubscribe); commentElements.add(mSecureOptions); postElements.add(mSaveDraft); postElements.add(mLoadDraft); postElements.add(titleText); postElements.add((View) titleText.getParent()); // контейнер (TextInputLayout) postElements.add(mShowOptionals); postElements.add(mShowCloseOptions); postElements.add(mShowPoll); postElements.add(mNoComments); umailElements.add(toText); umailElements.add((View) toText.getParent()); // контейнер (TextInputLayout) umailElements.add(titleText); umailElements.add((View) titleText.getParent()); // контейнер (TextInputLayout) umailElements.add(mGetReceipt); umailElements.add(mRequote); umailElements.add(mCopyMessage); umailElements.add(requoteText); return sender; } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.message_sender_a, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_special_paste: DialogFragment newFragment = PasteSelector.newInstance(); newFragment.show(getActivity().getSupportFragmentManager(), "selector"); return true; } return super.onOptionsItemSelected(item); } @Override public void onDestroyView() { mLooper.quit(); LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mPaneStateReceiver); super.onDestroyView(); } public String getContentText() { return contentText.getText().toString(); } public void setContentText(String text) { contentText.setText(text); } public void setSelection(int pos) { contentText.setSelection(pos); } public <T extends Comment> void prepareFragment(String signature, T contents) { prepareFragment(signature, contents, true); } public <T extends Comment> void prepareFragment(String signature, T contents, boolean checkSame) { mService = NetworkService.getInstance(getActivity()); assert (mService != null); mHttpClient = mService.mNetworkClient; final Comment oldpost = mPost; mPost = contents; // обязательно mSignature = signature; if (mPost.getClass() == Post.class) { // загружаем автодополнение тем, музыки и настроения loadCompletions(themesText, AutocompleteItem.AutocompleteType.THEME); loadCompletions(moodText, AutocompleteItem.AutocompleteType.MOOD); loadCompletions(musicText, AutocompleteItem.AutocompleteType.MUSIC); // Если это новый пост if (mPost.postID.isEmpty()) { mTitle.setText(R.string.new_post); mCurrentPage.setText(UserData.getInstance().getCurrentDiaryPage().getTitle()); purgeContents(); for (View v : postElements) v.setVisibility(View.VISIBLE); if (oldpost.getClass() == Post.class && ((Post) oldpost).diaryID.equals(((Post) mPost).diaryID)) { AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); builder.setTitle(R.string.confirmation).setMessage(R.string.clear_contents); builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { prepareUi((Post) mPost); } }); builder.setNegativeButton(R.string.no, null); builder.create().show(); } else prepareUi((Post) mPost); } else { // если редактирование поста mTitle.setText(R.string.edit_post); mCurrentPage.setText(UserData.getInstance().getCurrentDiaryPage().getTitle()); purgeContents(); for (View v : postElements) v.setVisibility(View.VISIBLE); prepareUi((Post) mPost); } } else if (mPost.getClass() == Comment.class) { // если это новый комментарий if (mPost.commentID.isEmpty()) { mTitle.setText(R.string.new_comment); mCurrentPage.setText(UserData.getInstance().getCurrentDiaryPage().getSubtitle()); purgeContents(); for (View v : commentElements) v.setVisibility(View.VISIBLE); if (checkSame && oldpost.getClass() == Comment.class && oldpost.postID.equals(mPost.postID)) { AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getActivity()); builder.setTitle(R.string.confirmation).setMessage(R.string.clear_contents); builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { prepareUi(mPost); } }); builder.setNegativeButton(R.string.no, null); builder.create().show(); } else prepareUi(mPost); } else { // редактирование комментария mTitle.setText(R.string.edit_comment); mCurrentPage.setText(UserData.getInstance().getCurrentDiaryPage().getSubtitle()); purgeContents(); for (View v : commentElements) v.setVisibility(View.VISIBLE); prepareUi(mPost); } } else if (mPost.getClass() == Umail.class) { // Если почта mTitle.setText(R.string.new_umail); mCurrentPage.setVisibility(View.GONE); purgeContents(); for (View v : umailElements) v.setVisibility(View.VISIBLE); prepareUi((Umail) mPost); } } private void prepareUi(Comment comment) { contentText.setText(comment.content); mSubscribe.setChecked(true); if (comment.commentID.isEmpty()) // новый коммент mSecureOptions.setVisibility(View.VISIBLE); else mSecureOptions.setVisibility(View.GONE); } @SuppressLint({"SetTextI18n", "DefaultLocale"}) private void prepareUi(Umail mail) { toText.setText(mail.receiver); if(mail.receiver.isEmpty() && mail.messageTheme.isEmpty()) { // новое сообщение titleText.setText(mail.messageTheme); } else if (mail.receiver.isEmpty()) { // пересылаемое сообщение titleText.setText("Fw: " + mail.messageTheme); } else { // сообщение-ответ Matcher replyFinder = EMAIL_ANSWER_REGEX.matcher(mail.messageTheme); if(replyFinder.find()) { // это ответ с номером, инкрементим int counter = Integer.parseInt(replyFinder.group(1)); String realTheme = replyFinder.group(2); titleText.setText(String.format("Re[%d]: %s", ++counter, realTheme)); } else if(mail.messageTheme.startsWith("Re:")) { // это ответ ещё без номера, вставляем titleText.setText(mail.messageTheme.replace("Re:", "Re[1]:")); } else { titleText.setText("Re: " + mail.messageTheme); // это первый ответ } } mRequote.setChecked(true); requoteText.setText(mail.reMessage); mCopyMessage.setChecked(true); } private void prepareUi(Post post) { titleText.setText(post.title); contentText.setText(post.content); if (!"".equals(post.music + post.mood + post.themes) || !post.predefinedTags.isEmpty()) mShowOptionals.setChecked(true); else mShowOptionals.setChecked(false); musicText.setText(post.music); moodText.setText(post.mood); themesText.setText(post.themes); if (!post.pollTitle.isEmpty()) mShowPoll.setChecked(true); else mShowPoll.setChecked(false); mPollTitle.setText(post.pollTitle); mPollChoice1.setText(post.pollAnswer1); mPollChoice2.setText(post.pollAnswer2); mPollChoice3.setText(post.pollAnswer3); mPollChoice4.setText(post.pollAnswer4); mPollChoice5.setText(post.pollAnswer5); mPollChoice6.setText(post.pollAnswer6); mPollChoice7.setText(post.pollAnswer7); mPollChoice8.setText(post.pollAnswer8); mPollChoice9.setText(post.pollAnswer9); mPollChoice10.setText(post.pollAnswer10); if (!post.closeAccessMode.isEmpty()) mShowCloseOptions.setChecked(true); else mShowCloseOptions.setChecked(false); switch (post.closeAccessMode) { case "6": mCloseOpts.check(R.id.close_only_reg); break; case "1": mCloseOpts.check(R.id.close_only_fav); break; case "5": mCloseOpts.check(R.id.close_only_sub); break; case "4": mCloseOpts.check(R.id.close_only_white); break; case "3": mCloseOpts.check(R.id.close_for_list); break; case "2": mCloseOpts.check(R.id.close_only_list); break; case "7": mCloseOpts.check(R.id.close_for_all); break; } mCloseText.setText(post.closeText); mCloseAllowList.setText(post.closeAllowList); mCloseDenyList.setText(post.closeDenyList); mNoComments.setChecked(post.noComments); mPredefinedThemes.removeAllViews(); // always clear all checks since we recreate them now LinearLayout horizontal = null; int i = 0; for (Map.Entry<String, Boolean> theme : post.predefinedTags.entrySet()) { if (i % 4 == 0) // по 4 темы в горизонтальный ряд { horizontal = new LinearLayout(getActivity()); horizontal.setOrientation(LinearLayout.HORIZONTAL); horizontal.setVerticalGravity(Gravity.CENTER); mPredefinedThemes.addView(horizontal); } CheckBox current = new CheckBox(getActivity()); current.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12); current.setEms(12); current.setMaxLines(2); current.setEllipsize(TextUtils.TruncateAt.END); current.setText(theme.getKey()); current.setChecked(theme.getValue()); horizontal.addView(current); ++i; } } public void insertInCursorPosition(@NonNull CharSequence prefix, @NonNull CharSequence what, @NonNull CharSequence suffix) { int cursorPos = contentText.getSelectionStart(); if (cursorPos == -1) cursorPos = contentText.getText().length(); String beforeCursor = contentText.getText().toString().substring(0, cursorPos); String afterCursor = contentText.getText().toString().substring(cursorPos, contentText.getText().length()); String beforeCursorWithPrefix = beforeCursor + prefix; String suffixWithAfterCursor = suffix + afterCursor; contentText.setText(beforeCursorWithPrefix + what + suffixWithAfterCursor); if(what.length() == 0) { // пустая строчка между тэгами, позиционируем в центр contentText.setSelection(contentText.getText().toString().indexOf(suffixWithAfterCursor, cursorPos)); } else if(afterCursor.isEmpty()) { // вставляем в конец, позиционируем на конец строки contentText.setSelection(contentText.getText().length()); } else { // вставляем в середину, позиционируем на строку после вставки contentText.setSelection(contentText.getText().toString().indexOf(afterCursor, cursorPos)); } } public void onClick(View view) { // обработка кнопок аватаров if (view instanceof ImageButton && view.getTag(R.integer.avatar_id) != null && view.getParent() == mAvatars) { postParams.clear(); postParams.add(Pair.create("use_avatar_id", view.getTag(R.integer.avatar_id).toString())); postParams.add(Pair.create("avatar_url", "")); postParams.add(Pair.create("signature", mSignature)); mHandler.sendEmptyMessage(HANDLE_SET_AVATAR); } // обработка кнопок смайлов if (view instanceof GifImageButton && view.getTag(R.integer.smile_key) != null && view.getParent() == mSmilies) { insertInCursorPosition("", (CharSequence) view.getTag(R.integer.smile_key), ""); } if (view instanceof Button && view.getTag(R.integer.smile_page) != null && view.getParent() == mSmilieButtons) { pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.loading_data) .progress(true, 0) .build(); pd.show(); mHandler.sendMessage(mHandler.obtainMessage(HANDLE_GET_SMILIES, view.getTag(R.integer.smile_page))); } // обычные кнопки switch (view.getId()) { case R.id.message_save_draft: case R.id.message_publish: { sendMessage(view); break; } case R.id.message_show_smilies: pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.loading_data) .progress(true, 0) .build(); pd.show(); mHandler.sendMessage(mHandler.obtainMessage(HANDLE_GET_SMILIES, null)); break; case R.id.message_load_draft: pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.loading_data) .progress(true, 0) .build(); pd.show(); mHandler.sendMessage(mHandler.obtainMessage(HANDLE_GET_DRAFTS, null)); break; } } private void sendMessage(View view) { postParams.clear(); // Добавляем параметры из настроек postParams.add(Pair.create("signature", mSignature)); postParams.add(Pair.create("action", "dosend")); pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.sending_data) .progress(true, 0) .cancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { mHttpClient.abort(); } }) .build(); pd.show(); //ProgressDialog.show(getActivity(), getString(R.string.loading), getString(R.string.sending_data), true, false); // Если пост if (mPost.getClass() == Post.class) { // сохраняем темы, музыку, настроение для автокомплита saveCompletions(themesText, AutocompleteItem.AutocompleteType.THEME); saveCompletions(moodText, AutocompleteItem.AutocompleteType.MOOD); saveCompletions(musicText, AutocompleteItem.AutocompleteType.MUSIC); postParams.add(Pair.create("avatar", "1")); // Показываем аватарку postParams.add(Pair.create("module", "journal")); postParams.add(Pair.create("resulttype", "2")); postParams.add(Pair.create("save_type", "js2")); postParams.add(Pair.create("journal_id", ((Post) mPost).diaryID)); postParams.add(Pair.create("referer", mHttpClient.getCurrentUrl())); postParams.add(Pair.create("attachment", "")); // draft or publish if(view.getId() == R.id.message_save_draft) { postParams.add(Pair.create("draft_save", "draft_save")); } else { postParams.add(Pair.create("rewrite", "rewrite")); } if (mPost.postID.isEmpty()) { // новый пост postParams.add(Pair.create("message", contentText.getText().toString() + mSharedPrefs.getString("post.signature", ""))); postParams.add(Pair.create("act", "new_post_post")); postParams.add(Pair.create("post_id", "")); postParams.add(Pair.create("post_type", "")); } else { // редактируем пост postParams.add(Pair.create("message", contentText.getText().toString())); postParams.add(Pair.create("act", "edit_post_post")); postParams.add(Pair.create("post_id", mPost.postID)); postParams.add(Pair.create("post_type", ((Post) mPost).postType)); } postParams.add(Pair.create("title", titleText.getText().toString())); if (mShowOptionals.isChecked()) { postParams.add(Pair.create("themes", themesText.getText().toString() + (mPost.postID.isEmpty() ? mSharedPrefs.getString("post.tags", "") : ""))); for (int i = 0; i < mPredefinedThemes.getChildCount(); ++i) { LinearLayout horizontal = (LinearLayout) mPredefinedThemes.getChildAt(i); for (int j = 0; j < horizontal.getChildCount(); ++j) { CheckBox check = (CheckBox) horizontal.getChildAt(j); if (check.isChecked()) postParams.add(Pair.create("fvtags[]", check.getText().toString())); } } postParams.add(Pair.create("current_music", musicText.getText().toString())); postParams.add(Pair.create("current_mood", moodText.getText().toString())); } else { postParams.add(Pair.create("themes", "")); postParams.add(Pair.create("current_music", "")); postParams.add(Pair.create("current_mood", "")); } if (mShowPoll.isChecked()) { postParams.add(Pair.create("poll_title", mPollTitle.getText().toString())); postParams.add(Pair.create("poll_answer_1", mPollChoice1.getText().toString())); postParams.add(Pair.create("poll_answer_2", mPollChoice2.getText().toString())); postParams.add(Pair.create("poll_answer_3", mPollChoice3.getText().toString())); postParams.add(Pair.create("poll_answer_4", mPollChoice4.getText().toString())); postParams.add(Pair.create("poll_answer_5", mPollChoice5.getText().toString())); postParams.add(Pair.create("poll_answer_6", mPollChoice6.getText().toString())); postParams.add(Pair.create("poll_answer_7", mPollChoice7.getText().toString())); postParams.add(Pair.create("poll_answer_8", mPollChoice8.getText().toString())); postParams.add(Pair.create("poll_answer_9", mPollChoice9.getText().toString())); postParams.add(Pair.create("poll_answer_10", mPollChoice10.getText().toString())); } else { postParams.add(Pair.create("poll_title", "")); postParams.add(Pair.create("poll_answer_1", "")); postParams.add(Pair.create("poll_answer_2", "")); postParams.add(Pair.create("poll_answer_3", "")); postParams.add(Pair.create("poll_answer_4", "")); postParams.add(Pair.create("poll_answer_5", "")); postParams.add(Pair.create("poll_answer_6", "")); postParams.add(Pair.create("poll_answer_7", "")); postParams.add(Pair.create("poll_answer_8", "")); postParams.add(Pair.create("poll_answer_9", "")); postParams.add(Pair.create("poll_answer_10", "")); } if (mShowCloseOptions.isChecked()) { postParams.add(Pair.create("private_post", "1")); if (!mCloseText.getText().toString().isEmpty()) { postParams.add(Pair.create("check_close_text", "1")); postParams.add(Pair.create("close_text", mCloseText.getText().toString())); } switch (mCloseOpts.getCheckedRadioButtonId()) { case R.id.close_only_reg: postParams.add(Pair.create("close_access_mode", "6")); break; case R.id.close_only_fav: postParams.add(Pair.create("close_access_mode", "1")); break; case R.id.close_only_sub: postParams.add(Pair.create("close_access_mode", "5")); break; case R.id.close_only_white: postParams.add(Pair.create("close_access_mode", "4")); break; case R.id.close_for_list: postParams.add(Pair.create("close_access_mode", "2")); postParams.add(Pair.create("access_list", mCloseDenyList.getText().toString())); break; case R.id.close_only_list: postParams.add(Pair.create("close_access_mode", "3")); postParams.add(Pair.create("access_list", mCloseAllowList.getText().toString())); break; case R.id.close_for_all: postParams.add(Pair.create("close_access_mode", "7")); break; } } if (mNoComments.isChecked()) postParams.add(Pair.create("no_comments", "1")); mHandler.sendEmptyMessage(HANDLE_DO_POST); } else if (mPost.getClass() == Comment.class) { // если коммент postParams.add(Pair.create("avatar", "1")); // Показываем аватарку postParams.add(Pair.create("module", "journal")); postParams.add(Pair.create("resulttype", "2")); if (mPost.commentID.isEmpty()) { // новый пост switch (mSecureOptions.getCheckedRadioButtonId()) { case R.id.message_anonymous: postParams.add(Pair.create("write_from", "1")); break; case R.id.message_as_user: postParams.add(Pair.create("write_from", "2")); postParams.add(Pair.create("write_from_name", mUserLogin.getText().toString())); postParams.add(Pair.create("write_from_pass", mUserPassword.getText().toString())); break; default: postParams.add(Pair.create("write_from", "0")); break; } postParams.add(Pair.create("message", contentText.getText().toString() + mSharedPrefs.getString("post.signature", ""))); postParams.add(Pair.create("act", "new_comment_post")); postParams.add(Pair.create("commentid", "")); } else { // редактируем пост postParams.add(Pair.create("message", contentText.getText().toString())); postParams.add(Pair.create("act", "edit_comment_post")); postParams.add(Pair.create("commentid", mPost.commentID)); } postParams.add(Pair.create("post_id", mPost.postID)); postParams.add(Pair.create("referer", "")); postParams.add(Pair.create("page", "last")); postParams.add(Pair.create("open_uri", "")); postParams.add(Pair.create("subscribe", mSubscribe.isChecked() ? "1/" : "")); postParams.add(Pair.create("attachment1", "")); mHandler.sendEmptyMessage(HANDLE_DO_COMMENT); } else if (mPost.getClass() == Umail.class) { // если почта postParams.add(Pair.create("message", contentText.getText().toString() + mSharedPrefs.getString("post.signature", ""))); postParams.add(Pair.create("module", "umail")); postParams.add(Pair.create("act", "umail_send")); postParams.add(Pair.create("from_folder", "")); postParams.add(Pair.create("to_user", toText.getText().toString())); postParams.add(Pair.create("title", titleText.getText().toString())); postParams.add(Pair.create("save_copy", mCopyMessage.isChecked() ? "yes" : "")); postParams.add(Pair.create("need_receipt", mGetReceipt.isChecked() ? "yes" : "")); if (mRequote.isChecked()) { postParams.add(Pair.create("requote", "yes")); postParams.add(Pair.create("remessage", "\n\n" + requoteText.getText().toString())); } mHandler.sendEmptyMessage(HANDLE_DO_UMAIL); } } private void saveCompletions(EditText edit, AutocompleteItem.AutocompleteType type) { RuntimeExceptionDao<AutocompleteItem, Long> acDao = DbProvider.getHelper().getAutocompleteDao(); String tokenString = edit.getText().toString(); if(!tokenString.isEmpty()) { for(String token : tokenString.split(";")) { String testToken = token.trim(); if(testToken.isEmpty()) { continue; } SelectArg textEscaped = new SelectArg(testToken); List<AutocompleteItem> found = acDao.queryForEq("text", textEscaped); AutocompleteItem item = found.isEmpty() ? new AutocompleteItem() : found.get(0); item.setType(type); item.setText(testToken); acDao.createOrUpdate(item); } } } private void loadCompletions(MultiAutoCompleteTextView edit, AutocompleteItem.AutocompleteType type) { RuntimeExceptionDao<AutocompleteItem, Long> acDao = DbProvider.getHelper().getAutocompleteDao(); List<AutocompleteItem> tokens = acDao.queryForEq("type", type); ArrayAdapter<AutocompleteItem> tokenAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, tokens); edit.setAdapter(tokenAdapter); } public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (buttonView.getId()) { case R.id.message_requote: if (isChecked) requoteText.setVisibility(View.VISIBLE); else requoteText.setVisibility(View.GONE); break; case R.id.message_optional: if (isChecked) mOptionals.setVisibility(View.VISIBLE); else mOptionals.setVisibility(View.GONE); break; case R.id.message_poll: if (isChecked) mPoll.setVisibility(View.VISIBLE); else mPoll.setVisibility(View.GONE); break; case R.id.message_close: if (isChecked) mCloseOpts.setVisibility(View.VISIBLE); else mCloseOpts.setVisibility(View.GONE); break; case R.id.message_custom_avatar: if (isChecked) { mAvatars.setVisibility(View.VISIBLE); if (avatarMap == null) { pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.loading_data) .progress(true, 0) .build(); pd.show(); mHandler.sendEmptyMessage(HANDLE_REQUEST_AVATARS); } } else mAvatars.setVisibility(View.GONE); default: break; } } public void onCheckedChanged(RadioGroup group, int checkedId) { if (group == mCloseOpts) switch (checkedId) { case R.id.close_for_list: mCloseDenyList.setVisibility(View.VISIBLE); mCloseAllowList.setVisibility(View.GONE); break; case R.id.close_only_list: mCloseAllowList.setVisibility(View.VISIBLE); mCloseDenyList.setVisibility(View.GONE); break; default: mCloseDenyList.setVisibility(View.GONE); mCloseAllowList.setVisibility(View.GONE); break; } else if (group == mSecureOptions) switch (checkedId) { case R.id.message_as_user: mAsUserLayout.setVisibility(View.VISIBLE); break; default: mAsUserLayout.setVisibility(View.GONE); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case Utils.ACTIVITY_ACTION_REQUEST_IMAGE: if (resultCode == Activity.RESULT_OK) { Uri uri = data.getData(); requestFileUpload(uri); } break; case Utils.ACTIVITY_ACTION_REQUEST_MUSIC: if (resultCode == Activity.RESULT_OK) { Uri uri = data.getData(); requestMusicUpload(uri); } break; case Utils.ACTIVITY_ACTION_REQUEST_GIF: if (resultCode == Activity.RESULT_OK) { Uri uri = data.getData(); requestGifUpload(uri); } break; } super.onActivityResult(requestCode, resultCode, data); } private void requestGifUpload(Uri uri) { File file = getFileFromUri(uri); try { if (file != null) { final Message msg = mHandler.obtainMessage(Utils.HANDLE_UPLOAD_GIF, file.getCanonicalPath()); msg.arg1 = 3; AlertDialogWrapper.Builder origOrMoreOrLink = new AlertDialogWrapper.Builder(getActivity()); DialogInterface.OnClickListener selector = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_NEGATIVE: msg.arg1 = 1; break; case DialogInterface.BUTTON_NEUTRAL: msg.arg1 = 2; break; case DialogInterface.BUTTON_POSITIVE: default: msg.arg1 = 3; break; } pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.sending_data) .progress(false, 100) .build(); pd.show(); mHandler.sendMessage(msg); } }; origOrMoreOrLink.setTitle(R.string.select_gif_width); origOrMoreOrLink.setNegativeButton(R.string.s100, selector); origOrMoreOrLink.setNeutralButton(R.string.s200, selector); origOrMoreOrLink.setPositiveButton(R.string.s300, selector); origOrMoreOrLink.create().show(); } else Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } catch (IOException e) { Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } } @Nullable private File getFileFromUri(Uri uri) { File file = null; if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(uri.getScheme())) { file = FileUtils.getFile(getActivity(), uri); } else if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(uri.getScheme())) file = new File(uri.getPath()); return file; } private void requestMusicUpload(Uri uri) { File file = getFileFromUri(uri); try { if (file != null) { final Message msg = mHandler.obtainMessage(Utils.HANDLE_UPLOAD_MUSIC, file.getCanonicalPath()); msg.arg1 = 2; AlertDialogWrapper.Builder pleerType = new AlertDialogWrapper.Builder(getActivity()); DialogInterface.OnClickListener selector = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_NEGATIVE: msg.arg1 = 1; break; case DialogInterface.BUTTON_POSITIVE: default: msg.arg1 = 2; break; } pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.sending_data) .progress(false, 100) .build(); pd.show(); mHandler.sendMessage(msg); } }; pleerType.setTitle(R.string.select_pleer_color); pleerType.setNegativeButton(R.string.black, selector); pleerType.setPositiveButton(R.string.grey, selector); pleerType.create().show(); } else Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } catch (IOException e) { Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } } public void requestFileUpload(Uri uri) { File file = getFileFromUri(uri); try { if (file != null) { final Message msg = mHandler.obtainMessage(Utils.HANDLE_UPLOAD_FILE, file.getCanonicalPath()); msg.arg1 = 3; AlertDialogWrapper.Builder origOrMoreOrLink = new AlertDialogWrapper.Builder(getActivity()); DialogInterface.OnClickListener selector = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_NEGATIVE: msg.arg1 = 1; break; case DialogInterface.BUTTON_NEUTRAL: msg.arg1 = 2; break; case DialogInterface.BUTTON_POSITIVE: default: msg.arg1 = 3; break; } pd = new MaterialDialog.Builder(getActivity()) .title(R.string.loading) .content(R.string.sending_data) .progress(false, 100) .build(); pd.show(); mHandler.sendMessage(msg); } }; origOrMoreOrLink.setTitle(R.string.howto_send_img); origOrMoreOrLink.setNegativeButton(R.string.pack_inoriginal, selector); origOrMoreOrLink.setPositiveButton(R.string.pack_inmore, selector); origOrMoreOrLink.setNeutralButton(R.string.pack_inlink, selector); origOrMoreOrLink.create().show(); } else Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } catch (IOException e) { Toast.makeText(getActivity(), getString(R.string.file_not_found), Toast.LENGTH_SHORT).show(); } } private void closeMe(boolean reload) { ((DiaryActivity) getActivity()).onMessagePaneRemove(reload); } private void setSmiliesState(boolean animate) { int childCount = mSmilies.getChildCount(); for(int i = 0; i < childCount; ++i) { GifImageButton gib = (GifImageButton) mSmilies.getChildAt(i); GifDrawable gd = (GifDrawable) gib.getDrawable(); if(animate) { gd.start(); } else { gd.stop(); } } } private void purgeContents() { for (int i = 0; i < mMainLayout.getChildCount(); ++i) { View curr = mMainLayout.getChildAt(i); if (curr.getContentDescription() == null || !curr.getContentDescription().toString().equals("persistent")) mMainLayout.getChildAt(i).setVisibility(View.GONE); if (curr instanceof CheckBox) ((CheckBox) curr).setChecked(false); if (curr instanceof RadioGroup) ((RadioGroup) curr).clearCheck(); } // TODO: переделать обработку с использованием ViewGroup mSaveDraft.setVisibility(View.GONE); mLoadDraft.setVisibility(View.GONE); } private class SendProgressListener implements DiaryHttpClient.ProgressListener { private final long length; public SendProgressListener(long length) { this.length = length; } @Override public void transferred(long transferredBytes) { long percent = (transferredBytes * 100) / length; mUiHandler.sendMessage(mUiHandler.obtainMessage(HANDLE_PROGRESS, (int) percent)); } } }