diff options
author | Renard | 2016-04-05 01:52:13 -0300 |
---|---|---|
committer | Renard | 2016-04-05 01:52:13 -0300 |
commit | 90ca8b34d823eed19d26f6611716ca231d60424c (patch) | |
tree | 65d389b05acb542f14a8faba8abeaa7b36ae227e /app/src | |
download | BaiApp-90ca8b34d823eed19d26f6611716ca231d60424c.tar.gz BaiApp-90ca8b34d823eed19d26f6611716ca231d60424c.tar.xz BaiApp-90ca8b34d823eed19d26f6611716ca231d60424c.zip |
Initial commit
Diffstat (limited to 'app/src')
88 files changed, 4215 insertions, 0 deletions
diff --git a/app/src/androidTest/java/org/bienvenidoainternet/baiparser/ApplicationTest.java b/app/src/androidTest/java/org/bienvenidoainternet/baiparser/ApplicationTest.java new file mode 100644 index 0000000..ca23e0c --- /dev/null +++ b/app/src/androidTest/java/org/bienvenidoainternet/baiparser/ApplicationTest.java @@ -0,0 +1,13 @@ +package org.bienvenidoainternet.baiparser; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> + */ +public class ApplicationTest extends ApplicationTestCase<Application> { + public ApplicationTest() { + super(Application.class); + } +}
\ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..31f37e2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.bienvenidoainternet.baiparser"> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + + <application + android:allowBackup="true" + android:icon="@drawable/bai_mona" + android:label="@string/app_name" + android:supportsRtl="true" + android:theme="@style/Theme.AppCompat.Light"> + <activity + android:name=".MainActivity" + android:label="@string/app_name" + android:theme="@style/AppTheme.NoActionBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity android:name=".ResponseActivity" /> + <activity + android:name=".SettingsActivity" + android:label="@string/title_activity_settings" /> + <activity + android:name=".ViewerActivity" + android:theme="@style/TransparentCompat"></activity> + <activity android:name=".UpdaterActivity"></activity> + </application> + +</manifest> diff --git a/app/src/main/assets/fonts/mona.ttf b/app/src/main/assets/fonts/mona.ttf Binary files differnew file mode 100644 index 0000000..d19a9ec --- /dev/null +++ b/app/src/main/assets/fonts/mona.ttf diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png Binary files differnew file mode 100644 index 0000000..57044d4 --- /dev/null +++ b/app/src/main/ic_launcher-web.png diff --git a/app/src/main/java/layout/fragmentThreadList.java b/app/src/main/java/layout/fragmentThreadList.java new file mode 100644 index 0000000..c06fd93 --- /dev/null +++ b/app/src/main/java/layout/fragmentThreadList.java @@ -0,0 +1,779 @@ +package layout; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.ColorDrawable; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.support.v7.view.ContextThemeWrapper; +import android.util.Log; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.koushikdutta.async.future.FutureCallback; +import com.koushikdutta.ion.Ion; + +import org.bienvenidoainternet.baiparser.MainActivity; +import org.bienvenidoainternet.baiparser.R; +import org.bienvenidoainternet.baiparser.RecentPostAdapter; +import org.bienvenidoainternet.baiparser.ResponseActivity; +import org.bienvenidoainternet.baiparser.ThreadListAdapter; +import org.bienvenidoainternet.baiparser.structure.Board; +import org.bienvenidoainternet.baiparser.structure.BoardItem; +import org.bienvenidoainternet.baiparser.structure.ReplyID; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.List; + +public class fragmentThreadList extends Fragment { + public static final String ARG_CURRENTBOARD = "currentBoard", ARG_THREAD_ID = "currentThreadId", ARG_MAIN_FRAGMENT = "imMainFragment", + SAVED_BOARDITEMS = "savedBoardItems", RECENT_POST_MODE = "recentpostmode", ARG_CURRENT_THREAD = "currentThread"; + List<ReplyID> idList = new ArrayList<>(); + public ArrayList<BoardItem> boardItems = new ArrayList<BoardItem>(); + public Board currentBoard = null; + public BoardItem currentThread = null; + private boolean imMainFragment; + private OnFragmentInteractionListener mListener; + private ThreadListAdapter listViewAdapter; + private RecentPostAdapter recentPostAdapter; + private ListView listViewBoardItems = null;; + private ProgressBar loadingBar = null; + SharedPreferences settings; + private boolean loadingMoreThreads = false; + View themedContext; + private int currentOffset = 0; + + ViewGroup rootView; + private boolean recentPostMode = false; + +// ProgressBar barThreadProcess; + LinearLayout layoutThreadProcess; + TextView txtThreadProcess; + + public fragmentThreadList() { + // Required empty public constructor + + } + + public static fragmentThreadList newInstance(boolean mainFragment, Board board, BoardItem thread){ + fragmentThreadList fragment = new fragmentThreadList(); + Bundle args = new Bundle(); + args.putParcelable(ARG_CURRENTBOARD, board); + args.putParcelable(ARG_CURRENT_THREAD, thread); + args.putBoolean(ARG_MAIN_FRAGMENT, mainFragment); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.setRetainInstance(true); + if (getArguments() != null) { + this.currentBoard = getArguments().getParcelable(ARG_CURRENTBOARD); + this.currentThread = getArguments().getParcelable(ARG_CURRENT_THREAD); + this.imMainFragment = getArguments().getBoolean(ARG_MAIN_FRAGMENT); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelableArrayList(SAVED_BOARDITEMS, boardItems); + outState.putBoolean(RECENT_POST_MODE, recentPostMode); + outState.putParcelable(ARG_CURRENT_THREAD, currentThread); + outState.putParcelable(ARG_CURRENTBOARD, currentBoard); + } + + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // cargamos la instancia si esta guardada + if (savedInstanceState != null){ + recentPostMode = savedInstanceState.getBoolean(RECENT_POST_MODE); + currentBoard = savedInstanceState.getParcelable(ARG_CURRENTBOARD); + currentThread = savedInstanceState.getParcelable(ARG_CURRENT_THREAD); + boardItems = savedInstanceState.getParcelableArrayList(SAVED_BOARDITEMS); + } + + // Aplicación del Tema + settings = PreferenceManager.getDefaultSharedPreferences(this.getContext()); + int themeResId = ((MainActivity)getActivity()).getCurrentThemeId(); + Context context = new ContextThemeWrapper(getActivity(), themeResId); + LayoutInflater localInflater = inflater.cloneInContext(context); + View v = localInflater.inflate(R.layout.fragment_fragment_thread_list, container, false); + themedContext = v; + this.rootView = (ViewGroup)v; + + // Seteamos los controles que son guardados globalmente + listViewBoardItems = (ListView)v.findViewById(R.id.lvThreadList); +// barThreadProcess = (ProgressBar)rootView.findViewById(R.id.barThreadProcess); + layoutThreadProcess = (LinearLayout)rootView.findViewById(R.id.layoutThreadProcess); + txtThreadProcess = (TextView)rootView.findViewById(R.id.txtThreadError); + this.loadingBar = (ProgressBar)rootView.findViewById(R.id.progressBar); + + // Agregamos color al divider del listview + ColorDrawable cd = new ColorDrawable((((MainActivity) getActivity()).themeManager).getMarginColor()); + listViewBoardItems.setDivider(cd); + listViewBoardItems.setDividerHeight(1); + + // registramos los menus del listview + registerForContextMenu(listViewBoardItems); + // Creamos los dos adaptadores y los seteamos dependiendo del modo del fragmento + listViewAdapter = new ThreadListAdapter(v.getContext(), boardItems, (((MainActivity) getActivity()).themeManager)); + recentPostAdapter = new RecentPostAdapter(v.getContext(), boardItems); + if (recentPostMode){ + listViewBoardItems.setAdapter(recentPostAdapter); + }else{ + listViewBoardItems.setAdapter(listViewAdapter); + } + + if (!imMainFragment){ + listViewAdapter.listThreads = true; + } + + listViewBoardItems.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + if (imMainFragment && !recentPostMode) { + BoardItem bi = listViewAdapter.getItem(position); + mListener.showThread(currentBoard, bi); + }else if (imMainFragment && recentPostMode){ + BoardItem bi = boardItems.get(position); + mListener.showThread(bi.getParentBoard(), bi); + } + } + }); + + listViewBoardItems.setOnScrollListener(new AbsListView.OnScrollListener() { + private int lastFirstVisibleItem = 0; + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + if(lastFirstVisibleItem < firstVisibleItem) { // Scrolling down + mListener.hideActionButton(); + }else if(lastFirstVisibleItem > firstVisibleItem) { // Scrolling Up + mListener.showActionButton(); + } + lastFirstVisibleItem = firstVisibleItem; + for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) { + if (!recentPostMode){ + BoardItem bi = listViewAdapter.getItem(i); + if (!bi.getThumb().isEmpty() && bi.getThumbBitmap() == null && !bi.downloadingThumb) { + getThumbnail(bi); + } + } + } +// System.out.println("[Scroll] firstItem: " + firstVisibleItem + " visible: " + visibleItemCount + " total: " + totalItemCount); + if (totalItemCount == firstVisibleItem + visibleItemCount && !loadingMoreThreads && imMainFragment && totalItemCount != 0 && !recentPostMode) { + loadingMoreThreads = true; + currentOffset += 10; + System.out.println("[Scroll] loading more threads! currentThreadCount " + totalItemCount); + getThreadList(currentOffset); // TODO: Offset incorrecto +// new TaskParseJSON(currentBoard, true).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + }); + hideProgressBar(); + if (boardItems.isEmpty()){ + if (currentBoard == null && currentThread == null && imMainFragment){ + loadRecentPost(); + }else{ + updateBoardItems(currentBoard, currentThread); + } + }else{ + listViewAdapter.notifyDataSetChanged(); + recentPostAdapter.notifyDataSetChanged(); + } + return v; + } + + private void hideProgressBar(){ + if (loadingBar != null) + loadingBar.setVisibility(View.GONE); + } + + private void showProgressBar(){ + if (loadingBar != null) + loadingBar.setVisibility(View.VISIBLE); + } + + + public void onButtonPressed(Uri uri) { + if (mListener != null) { + mListener.onFragmentInteraction(uri); + } + } + + public void updateBoardItems(Board board, BoardItem thread){ + currentBoard = board; + currentThread = thread; + + if (listViewAdapter != null){ + boardItems.clear(); + listViewAdapter.notifyDataSetChanged(); + } + if (imMainFragment){ + if (currentBoard != null) { + System.out.println("[MainFragment] Updating -> boardName: " + board.getBoardName() + " dir: " + board.getBoardDir()); + if (currentThread == null){ + System.out.println("[MainFragment] isCurrentThread null? (it should be!) " + (currentThread == null)); + } + showProgressBar(); +// new TaskParseJSON(board).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + getThreadList(0); + }else{ + System.out.println("[MainFragment] Trying to update from a null board object"); + } + }else{ + if (currentBoard != null && currentThread != null){ + System.out.println("atUpdateBoardItems ChildFragment threadID: " + currentThread.getId() + " parentID: " + currentThread.getParentId() + " boardName: " + board.getBoardName() + " " + board.getBoardDir()); + showProgressBar(); +// new TaskParseJSON(currentBoard, currentThread).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + getThreadReplies(); + }else{ + System.out.println("[childFragment] trying to update from null objects"); + System.out.println("[childFragment] isCurrentBoard null? " + (currentBoard == null)); + System.out.println("[childFragment] isCurrentThread null? " + (currentThread == null)); + } + } + } + + + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); + if (info.targetView.getParent() == listViewBoardItems){ + BoardItem bi = boardItems.get(info.position); + switch (item.getItemId()){ + case R.id.menu_copy: + System.out.println("Post copiado"); + ClipboardManager cm = (ClipboardManager)getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData cd = ClipData.newPlainText("Reply", boardItems.get(info.position).getMessage()); + cm.setPrimaryClip(cd); + break; + case R.id.menu_reply: + Intent in = new Intent(getActivity().getApplicationContext(), ResponseActivity.class); + Bundle b = new Bundle(); + b.putParcelable("theReply", boardItems.get(info.position)); + b.putParcelable("theBoard", currentBoard); + in.putExtras(b); + getActivity().startActivity(in); + break; + case R.id.menu_savereply: + try { + File txt = new File(Environment.getExternalStorageDirectory().getPath() + "/Bai/" + bi.getParentBoard().getBoardDir() + "_" + bi.getId() + ".txt"); + FileOutputStream stream = new FileOutputStream(txt); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(stream); + outputStreamWriter.write(bi.getMessage()); + outputStreamWriter.close(); + stream.close(); + Toast.makeText(getContext(), bi.getParentBoard().getBoardDir() + "_" + bi.getId() + ".txt guardado.", Toast.LENGTH_SHORT).show(); + }catch (Exception e){ + e.printStackTrace(); + } + break; + case R.id.menu_delpost: + deletePost(false, bi); + break; + case R.id.menu_delimage: + deletePost(true, bi); + break; + } + } + return super.onContextItemSelected(item); + } + + + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + if (v.getId() == R.id.lvThreadList){ + getActivity().getMenuInflater().inflate(R.menu.menu_reply, menu); + return; + } + super.onCreateContextMenu(menu, v, menuInfo); + } + + public void refresh() { + if (recentPostMode){ + boardItems.clear(); + recentPostAdapter.notifyDataSetChanged(); + getRecentPosts(); + }else{ + updateBoardItems(currentBoard, currentThread); + } + } + + public void setRecentPostMode() { + this.recentPostMode = true; + } + + public void setCatalogMode() { + if (recentPostMode){ + boardItems.clear(); +// listViewAdapter = new ThreadListAdapter(themedContext.getContext(), boardItems, ((MainActivity)getActivity()).themeManager); + listViewBoardItems.setAdapter(listViewAdapter); + this.recentPostMode = false; + } + } + + public void loadRecentPost(){ + // Cambiamos el flag + setRecentPostMode(); + mListener.updateToolbar("Post recientes"); + // Borramos el listview + boardItems.clear(); + listViewAdapter.clear(); + listViewAdapter.notifyDataSetChanged(); + // Cargamos un nuevo adaptador. +// recentPostAdapter = new RecentPostAdapter(themedContext.getContext(), boardItems); + listViewBoardItems.setAdapter(recentPostAdapter); + // Cargamos la nueva lista + getRecentPosts(); + } + + public boolean getMode() { + return recentPostMode; + } + + + public interface OnFragmentInteractionListener { + void onFragmentInteraction(Uri uri); + void showThread(Board board, BoardItem thread); + void updateToolbar(Board currentBoard, BoardItem boardItem); + void updateToolbar(String s); + void hideActionButton(); + void showActionButton(); + } + + public void scrollToBotton(){ + if (!listViewAdapter.isEmpty()){ + listViewBoardItems.setSelection(boardItems.size()); + } + } + public void scrollToTop(){ + if (!listViewAdapter.isEmpty()){ + listViewBoardItems.setSelection(0); + } + } + + public void getThreadList(int offset){ + loadingMoreThreads = true; + showProgressBar(); + String strOffset = ""; + if (offset == 0){ + currentOffset = 0; + boardItems.clear(); + }else{ + strOffset = "&offset=" + offset; + } + setUpThreadProgess(); + + final String repliesForCatalog = settings.getString("pref_repliesperthread", "5"); + Ion.with(getContext()) + .load("http://bienvenidoainternet.org/cgi/api/list?dir=" + currentBoard.getBoardDir() + "&replies=" + repliesForCatalog + strOffset) + .setLogging("getThreadList", Log.INFO) +// .progressBar(barThreadProcess) + .noCache() + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + hideProgressBar(); + if (e != null) { + e.printStackTrace(); + displayError(e.getMessage()); + } else { + try { + JSONObject json = new JSONObject(result); + JSONArray threads = json.getJSONArray("threads"); + for (int i = 0; i < threads.length(); i++) { + JSONObject thread = threads.getJSONObject(i); + BoardItem item = new BoardItem(); + item.setEmail(thread.getString("email")); + item.setFile(thread.getString("file")); + item.setFilesize(thread.getInt("file_size")); + item.setId(thread.getInt("id")); + item.setMessage(thread.getString("message")); + item.setName(thread.getString("name")); + item.setSubject(thread.getString("subject")); + item.setThumb(thread.getString("thumb")); + item.setThumbHeight(thread.getInt("thumb_height")); + item.setThumbWidth(thread.getInt("thumb_width")); + item.setTimeStamp(thread.getLong("timestamp")); + item.setTotalFiles(thread.getInt("total_files")); + item.setTotalReplies(thread.getInt("total_replies")); + item.setTripcode(thread.getString("tripcode")); + item.setTimeStampFormatted(thread.getString("timestamp_formatted")); + if (item.getTimeStampFormatted().contains("ID")){ + item.setPosterId(item.getTimeStampFormatted().split(" ")[1].replace("ID :", "")); + } + item.setParentBoard(currentBoard); + item.setParentId(0); + item.setIdColor(addReplyID(item.getPosterId())); + if (currentBoard.getBoardType() == 1){ + item.setBbsId(1); + } + boardItems.add(item); + if (!repliesForCatalog.equals("0")){ + JSONArray replies = thread.getJSONArray("replies"); + for (int r = 0; r < replies.length(); r++){ + JSONObject jReply = replies.getJSONObject(r); + BoardItem reply = new BoardItem(); + reply.setDeletedCode(jReply.getInt("IS_DELETED")); + if (currentBoard.getBoardType() == 1){ + reply.setBbsId(item.getTotalReplies() - (Integer.valueOf(repliesForCatalog) - r) + 2); + } + if (reply.getDeletedCode() == 0){ + reply.setEmail(jReply.getString("email")); + reply.setFile(jReply.getString("file")); + reply.setFilesize(jReply.getInt("file_size")); + reply.setId(jReply.getInt("id")); + reply.setParentId(item.getId()); + reply.setMessage(jReply.getString("message")); + reply.setName(jReply.getString("name")); + reply.setSubject(jReply.getString("subject")); + reply.setThumb(jReply.getString("thumb")); + reply.setThumbHeight(jReply.getInt("thumb_height")); + reply.setThumbWidth(jReply.getInt("thumb_width")); + reply.setTimeStamp(jReply.getLong("timestamp")); + reply.setTripcode(jReply.getString("tripcode")); + reply.setParentBoard(currentBoard); + reply.setTimeStampFormatted(jReply.getString("timestamp_formatted")); + reply.isReply = true; + if (reply.getTimeStampFormatted().contains("ID")){ + reply.setPosterId(reply.getTimeStampFormatted().split(" ")[1].replace("ID:", "")); + } + reply.setIdColor(addReplyID(reply.getPosterId())); + // + reply.setTotalReplies(item.getTotalReplies()); + }else{ + reply.setTimeStamp(jReply.getLong("timestamp")); + reply.setId(jReply.getInt("id")); + reply.isReply = true; + } + boardItems.add(reply); + } + } + } + } catch (JSONException e1) { + e1.printStackTrace(); + displayError(e1.getMessage()); + } + } + listViewAdapter.notifyDataSetChanged(); + loadingMoreThreads = false; + if (boardItems.isEmpty()){ + mListener.updateToolbar(currentBoard, currentThread); + } + } + }); + + + } + + private void getThreadReplies() { + showProgressBar(); + boardItems.clear(); + setUpThreadProgess(); + int limit = Integer.valueOf(settings.getString("pref_lastreplies", "1000")); + int parentTotalReplies = currentThread.getTotalReplies(); // TODO: asddas + String offset = "&offset=0"; + if (limit <= parentTotalReplies){ + offset = "&offset=" + (parentTotalReplies - limit + 1); + }else{ + limit = 1337; + } + final int finalLimit = limit; + Ion.with(getContext()) + .load("http://bienvenidoainternet.org/cgi/api/thread?id=" + currentThread.realParentId() + "&dir=" + currentThread.getParentBoard().getBoardDir() + "&limit=" + limit + offset) + .setLogging("getThreadReplies", Log.INFO) + .noCache() + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + if (e != null){ + e.printStackTrace(); + displayError(e.getMessage()); + }else{ + try { + JSONObject json = new JSONObject(result); + JSONArray thread = json.getJSONArray("posts"); + for (int i = 0; i < thread.length(); i++){ + JSONObject reply = thread.getJSONObject(i); + BoardItem item = new BoardItem(); + item.setDeletedCode(reply.getInt("IS_DELETED")); + if (item.getDeletedCode() == 0){ + item.setEmail(reply.getString("email")); + item.setFile(reply.getString("file")); + item.setFilesize(reply.getInt("file_size")); + item.setId(reply.getInt("id")); + item.setMessage(reply.getString("message")); + item.setName(reply.getString("name")); + item.setSubject(reply.getString("subject")); + item.setThumb(reply.getString("thumb")); + item.setThumbHeight(reply.getInt("thumb_height")); + item.setThumbWidth(reply.getInt("thumb_width")); + item.setTimeStamp(reply.getLong("timestamp")); + item.setParentId(json.getInt("id")); + item.setTripcode(reply.getString("tripcode")); + item.setTimeStampFormatted(reply.getString("timestamp_formatted")); + if (item.getTimeStampFormatted().contains("ID")){ + item.setPosterId(item.getTimeStampFormatted().split(" ")[1].replace("ID:", "")); + } + item.setParentBoard(currentBoard); + item.isReply = true; + item.setIdColor(addReplyID(item.getPosterId())); + item.setTotalReplies(json.getInt("total_replies")); + if (currentBoard.getBoardType() == 1){ + if (item.getTotalReplies() < finalLimit){ + item.setBbsId(i + 1); + }else{ + item.setBbsId((item.getTotalReplies() - finalLimit + i) + 2); + } + } + + } else { + item.setId(reply.getInt("id")); + item.setTimeStamp(reply.getLong("timestamp")); + item.isReply = true; + item.setTotalReplies(json.getInt("total_replies")); + if (currentBoard.getBoardType() == 1){ + if (item.getTotalReplies() < finalLimit){ + item.setBbsId(i + 1); + }else{ + item.setBbsId((item.getTotalReplies() - finalLimit + i) + 2); + } + } + } + boardItems.add(item); + } + } catch (JSONException e1) { + e1.printStackTrace(); + displayError(e1.getMessage()); + } + } + listViewAdapter.notifyDataSetChanged(); + if (settings.getBoolean("setting_scrollatnewthread", true)){ + listViewBoardItems.setSelection(boardItems.size()); + mListener.showActionButton(); + } + hideProgressBar(); + } + }); + } + + private void getRecentPosts(){ + boardItems.clear(); + loadingMoreThreads = true; + setUpThreadProgess(); + String limit = settings.getString("pref_lastreplies_limit", "30"); + Ion.with(getContext()) + .load("http://bienvenidoainternet.org/cgi/api/last?limit=" + limit) + .setLogging("getRecentPosts", Log.INFO) +// .progressBar(barThreadProcess) + .noCache() + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + if (e != null){ + e.printStackTrace(); + displayError(e.getMessage()); + }else{ + try { + JSONObject json = new JSONObject(result); + JSONArray posts = json.getJSONArray("posts"); + for (int i = 0; i < posts.length(); i++){ + JSONObject jPost = posts.getJSONObject(i); + BoardItem recentPost = new BoardItem(); + recentPost.setEmail(jPost.getString("email")); + recentPost.setFile(jPost.getString("file")); + recentPost.setFilesize(jPost.getInt("file_size")); + recentPost.setId(jPost.getInt("id")); + recentPost.setMessage(jPost.getString("message")); + recentPost.setName(jPost.getString("name")); + recentPost.setSubject(jPost.getString("subject")); + recentPost.setThumb(jPost.getString("thumb")); + recentPost.setThumbHeight(jPost.getInt("thumb_height")); + recentPost.setThumbWidth(jPost.getInt("thumb_width")); + recentPost.setTimeStamp(jPost.getLong("timestamp")); + recentPost.setTripcode(jPost.getString("tripcode")); + recentPost.setTimeStampFormatted(jPost.getString("timestamp_formatted")); + if (recentPost.getTimeStampFormatted().contains("ID")){ + recentPost.setPosterId(recentPost.getTimeStampFormatted().split(" ")[1].replace("ID:", "")); + } + recentPost.setParentBoard(((MainActivity) getActivity()).getBoardFromDir(jPost.getString("dir"))); + recentPost.setParentId(jPost.getInt("parentid")); + boardItems.add(recentPost); + } + } catch (JSONException e1) { + e1.printStackTrace(); + displayError(e1.getMessage()); + } + } + recentPostAdapter.notifyDataSetChanged(); + } + }); + + } + + private void getThumbnail(final BoardItem bi){ + bi.downloadingThumb = true; + ConnectivityManager cm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo info = cm.getActiveNetworkInfo(); + boolean usingWifi = (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI); + + ContextWrapper cw = new ContextWrapper(getActivity().getApplicationContext()); + File directory = cw.getDir("thumbs", Context.MODE_PRIVATE); + File mypath = new File(directory, currentBoard.getBoardDir() + "_" + bi.getThumb()); + if (mypath.exists()){ + try { + Bitmap b = BitmapFactory.decodeStream(new FileInputStream(mypath)); + bi.setThumbBitmap(b); + Log.i("getThumb", bi.getThumb() + " from cache"); + return; + }catch (Exception e){ + e.printStackTrace(); + displayError(e.getMessage()); + } + } + if (settings.getBoolean("setting_downloadOnlyWithWifi", false) == true && !usingWifi){ + Log.i("getThumb", "Not using wifi"); + return; + } + Ion.with(getContext()) + .load("http://bienvenidoainternet.org/" + bi.getParentBoard().getBoardDir() + "/thumb/" + bi.getThumb()) + .setLogging("getThumbnail", Log.INFO) + .asBitmap() + .setCallback(new FutureCallback<Bitmap>() { + @Override + public void onCompleted(Exception e, Bitmap result) { + if (e != null) { + displayError(e.getMessage()); + e.printStackTrace(); + } else { + bi.setThumbBitmap(result); + listViewAdapter.notifyDataSetChanged(); + } + } + }); + } + + private void deletePost(final boolean imageOnly, BoardItem reply) { + String password = settings.getString("pref_password", "12345678"); + Ion.with(getContext()) + .load("http://bienvenidoainternet.org/cgi/api/delete?dir=" + currentThread.getParentBoard().getBoardDir() + "&id=" + reply.getId() + "&password=" + password + "&imageonly=" + (imageOnly ? 1 : 0)) + .setLogging("deletePost", Log.INFO) + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + if (e != null) { + e.printStackTrace(); + displayError(e.getMessage()); + } else { + JSONObject json = null; + try { + json = new JSONObject(result); + if (json.getString("state").equals("success")) { + Toast.makeText(getContext(), imageOnly ? "Imágen" : "Respuesta" + " eliminada", Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(getContext(), URLDecoder.decode(json.getString("message"), "UTF-8"), Toast.LENGTH_LONG).show(); + } + } catch (JSONException e1) { + e1.printStackTrace(); + displayError(e1.getMessage()); + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + displayError(e1.getMessage()); + } + } + } + }); + } + + + + public int addReplyID(String s){ + if (!idList.contains(new ReplyID(s))){ + idList.add(new ReplyID(s)); + } + for (ReplyID r : idList){ + if (r.id.equals(s)){return r.color;} + } + return 0; + } + + private void setUpThreadProgess(){ +// barThreadProcess.setVisibility(View.VISIBLE); + txtThreadProcess.setVisibility(View.GONE); + layoutThreadProcess.setVisibility(View.VISIBLE); + } + + private void displayError(String error){ + hideProgressBar(); + if (error != null){ + layoutThreadProcess.setVisibility(View.VISIBLE); + txtThreadProcess.setVisibility(View.VISIBLE); + txtThreadProcess.setText("( ; u ; ) \r\n/!\\ ERROR\r\n" + error); + } + + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/AppCompatPreferenceActivity.java b/app/src/main/java/org/bienvenidoainternet/baiparser/AppCompatPreferenceActivity.java new file mode 100644 index 0000000..e89a927 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/AppCompatPreferenceActivity.java @@ -0,0 +1,109 @@ +package org.bienvenidoainternet.baiparser; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatDelegate; +import android.support.v7.widget.Toolbar; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls + * to be used with AppCompat. + */ +public abstract class AppCompatPreferenceActivity extends PreferenceActivity { + + private AppCompatDelegate mDelegate; + + @Override + protected void onCreate(Bundle savedInstanceState) { + getDelegate().installViewFactory(); + getDelegate().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + getDelegate().onPostCreate(savedInstanceState); + } + + public ActionBar getSupportActionBar() { + return getDelegate().getSupportActionBar(); + } + + public void setSupportActionBar(@Nullable Toolbar toolbar) { + getDelegate().setSupportActionBar(toolbar); + } + + @Override + public MenuInflater getMenuInflater() { + return getDelegate().getMenuInflater(); + } + + @Override + public void setContentView(@LayoutRes int layoutResID) { + getDelegate().setContentView(layoutResID); + } + + @Override + public void setContentView(View view) { + getDelegate().setContentView(view); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().setContentView(view, params); + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().addContentView(view, params); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getDelegate().onPostResume(); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + super.onTitleChanged(title, color); + getDelegate().setTitle(title); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getDelegate().onConfigurationChanged(newConfig); + } + + @Override + protected void onStop() { + super.onStop(); + getDelegate().onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getDelegate().onDestroy(); + } + + public void invalidateOptionsMenu() { + getDelegate().invalidateOptionsMenu(); + } + + private AppCompatDelegate getDelegate() { + if (mDelegate == null) { + mDelegate = AppCompatDelegate.create(this, null); + } + return mDelegate; + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/CustomFragmentPagerAdapter.java b/app/src/main/java/org/bienvenidoainternet/baiparser/CustomFragmentPagerAdapter.java new file mode 100644 index 0000000..40052b8 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/CustomFragmentPagerAdapter.java @@ -0,0 +1,53 @@ +package org.bienvenidoainternet.baiparser; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Renard on 04-03-2016. + */ + +public class CustomFragmentPagerAdapter extends FragmentPagerAdapter { + + // List of fragments which are going to set in the view pager widget + List<Fragment> fragments; + + /** + * Constructor + * + * @param fm + * interface for interacting with Fragment objects inside of an + * Activity + */ + public CustomFragmentPagerAdapter(FragmentManager fm) { + super(fm); + this.fragments = new ArrayList<Fragment>(); + } + + /** + * Add a new fragment in the list. + * + * @param fragment + * a new fragment + */ + public void addFragment(Fragment fragment) { + this.fragments.add(fragment); + } + + @Override + public Fragment getItem(int arg0) { + return this.fragments.get(arg0); + } + + @Override + public int getCount() { + return this.fragments.size(); + } + + + +}
\ No newline at end of file diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/MainActivity.java b/app/src/main/java/org/bienvenidoainternet/baiparser/MainActivity.java new file mode 100644 index 0000000..050cfe9 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/MainActivity.java @@ -0,0 +1,478 @@ +package org.bienvenidoainternet.baiparser; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.NavigationView; +import android.support.design.widget.Snackbar; +import android.support.v4.view.GravityCompat; +import android.support.v4.view.ViewPager; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; +import android.view.View; +import android.widget.BaseAdapter; +import android.widget.HeaderViewListAdapter; +import android.widget.ListView; +import android.widget.Toast; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.koushikdutta.async.future.FutureCallback; +import com.koushikdutta.ion.Ion; + +import org.bienvenidoainternet.baiparser.structure.Board; +import org.bienvenidoainternet.baiparser.structure.BoardItem; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Random; + +import layout.fragmentThreadList; + +public class MainActivity extends AppCompatActivity + implements NavigationView.OnNavigationItemSelectedListener, fragmentThreadList.OnFragmentInteractionListener { + + public static final float CURRENT_VERSION = 1.5F; + private ViewPager pager; // variable del ViewPager + CustomFragmentPagerAdapter pagerAdapter; // Adaptador del ViewPager + NavigationView navigationView; + DrawerLayout drawer; + FloatingActionButton fab; + public ThemeManager themeManager; + fragmentThreadList childFragment; // Segunda página del ViewPager, se muestra un solo hilo (selecionado del catálogo) + fragmentThreadList mainFragment; // Primera página del ViewPager, se muestra una lista de hilos. (catálogo) +// fragmentThreadList recentFragment; + Toolbar toolbar = null; + public int currentThemeId = 0, themeId = 0; // Id del recurso, Id del tema + public ArrayList<Board> boardList = new ArrayList<>(); + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt("currentThemeId", currentThemeId); + outState.putInt("themeId", themeId); + outState.putParcelableArrayList("boardList", boardList); + if (getSupportFragmentManager().getFragments() != null) { + if (getSupportFragmentManager().getFragments().size() != 0) { + try { + getSupportFragmentManager().putFragment(outState, "mainFragment", mainFragment); + getSupportFragmentManager().putFragment(outState, "childFragment", childFragment); + }catch (Exception e){ + e.printStackTrace(); + } + } + } + } + + public int getCurrentThemeId() { + return currentThemeId; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + currentThemeId = savedInstanceState.getInt("currentThemeId"); + boardList = savedInstanceState.getParcelableArrayList("boardList"); + } + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); + themeId = Integer.valueOf(settings.getString("pref_theme", "1")); + + if (settings.getString("pref_password", "").isEmpty()){ + SharedPreferences.Editor edit = settings.edit(); + edit.putString("pref_password", makePassword()); + edit.commit(); + } + + switch (themeId) { + case 1: + currentThemeId = R.style.AppTheme_NoActionBar; + break; + case 2: + currentThemeId = R.style.AppTheme_Dark; + break; + case 3: + currentThemeId = R.style.AppTheme_HeadLine; + setTheme(R.style.AppTheme_HeadLine_Activity); + break; + case 4: + currentThemeId = R.style.AppTheme_Black; + setTheme(R.style.AppTheme_Black_Activity); + break; + } + + themeManager = new ThemeManager(this); + Log.d("ThemeManager", "isDarkTheme: " + themeManager.isDarkTheme()); + + setContentView(R.layout.activity_main); + toolbar = (Toolbar) findViewById(R.id.toolbar); + toolbar.setTitle("Bievenido a internet"); + this.setSupportActionBar(toolbar); + + + fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (childFragment.currentBoard != null) { + if (!childFragment.boardItems.isEmpty()) { + try { + Intent in = new Intent(getApplicationContext(), ResponseActivity.class); + Bundle b = new Bundle(); + b.putParcelable("theReply", childFragment.boardItems.get(0)); + b.putParcelable("theBoard", childFragment.currentBoard); + in.putExtras(b); + startActivity(in); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + }); + fab.setVisibility(View.GONE); + + drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + drawer.setDrawerListener(toggle); + toggle.syncState(); + + navigationView = (NavigationView) findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + if (savedInstanceState != null) { + mainFragment = (fragmentThreadList) getSupportFragmentManager().getFragment(savedInstanceState, "mainFragment"); + childFragment = (fragmentThreadList) getSupportFragmentManager().getFragment(savedInstanceState, "childFragment"); +// recentFragment = (fragmentThreadList) getSupportFragmentManager().getFragment(savedInstanceState, "recentFragment"); + } else { + mainFragment = fragmentThreadList.newInstance(true, null, null); + childFragment = fragmentThreadList.newInstance(false, null, null); +// recentFragment = fragmentThreadList.newInstance(false, null, -1); + } + + this.pager = (ViewPager) findViewById(R.id.pager); + this.pagerAdapter = new CustomFragmentPagerAdapter(getSupportFragmentManager()); + pagerAdapter.addFragment(mainFragment); + pagerAdapter.addFragment(childFragment); +// pagerAdapter.addFragment(recentFragment); + this.pager.setAdapter(pagerAdapter); + + pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if (position == 0){ + if (mainFragment.currentBoard != null) { + toolbar.setTitle("Catálogo"); + toolbar.setSubtitle(mainFragment.currentBoard.getBoardName()); + } + if (mainFragment.getMode()){ + toolbar.setTitle("Post recientes"); + toolbar.setSubtitle(""); + } + fab.setVisibility(View.INVISIBLE); + }else if (position == 1){ + if (childFragment.currentBoard != null) { + toolbar.setTitle(childFragment.currentBoard.getBoardName()); + if (!childFragment.boardItems.isEmpty()){ + toolbar.setSubtitle(childFragment.boardItems.get(0).getSubject()); + } + fab.setVisibility(View.VISIBLE); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + if (boardList.isEmpty()){ + getBoardList(); + }else{ + Menu menu = navigationView.getMenu(); + SubMenu sub = menu.addSubMenu("Lista de Boards"); + for (Board b : boardList) { + sub.add(b.getBoardName()); + } + refreshNavigator(); + } + + // TODO: Aplicar tema al navigator +// navigationView.setBackgroundColor(themeManager.getPrimaryDarkColor()); + checkForUpdates(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 1) { + if(resultCode == Activity.RESULT_OK){ + boolean result = data.getBooleanExtra("result", false); + if (result){ + this.recreate(); + } + } + } + } + + @Override + public void onBackPressed() { + if (this.pager.getCurrentItem() == 0) { + super.onBackPressed(); + } else { + this.pager.setCurrentItem(this.pager.getCurrentItem() - 1); + return; + } + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else { + super.onBackPressed(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + switch (id) { + case R.id.action_exit: + System.exit(0); + break; + case R.id.action_refresh: + if (pager.getCurrentItem() == 0) { + mainFragment.refresh(); + } else { + childFragment.refresh(); + } + if (boardList.isEmpty()){ + getBoardList(); + } + break; + case R.id.action_settings: + Intent in2 = new Intent(getApplicationContext(), SettingsActivity.class); + startActivityForResult(in2, 1); + break; + case R.id.action_to_bot: + if (pager.getCurrentItem() == 0) { + mainFragment.scrollToBotton(); + } else { + childFragment.scrollToBotton(); + } + break; + case R.id.action_to_top: + if (pager.getCurrentItem() == 0) { + mainFragment.scrollToTop(); + } else { + childFragment.scrollToTop(); + } + break; + case R.id.action_update: + Intent updater = new Intent(getApplicationContext(), UpdaterActivity.class); + startActivity(updater); + } + return super.onOptionsItemSelected(item); + } + + @SuppressWarnings("StatementWithEmptyBody") + @Override + public boolean onNavigationItemSelected(MenuItem item) { + // Handle navigation view item clicks here. + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + int id = item.getItemId(); + toolbar.setSubtitle(item.getTitle()); + if (id == R.id.nav_recent_post){ + toolbar.setTitle("Post recientes"); + toolbar.setSubtitle(""); + pager.setCurrentItem(0); + mainFragment.loadRecentPost(); + } + for (Board b : boardList){ + if (b.getBoardName() == item.getTitle()){ + System.out.println("Updating mainfragment to " + b.getBoardName() + " d: " + b.getBoardDir()); + mainFragment.setCatalogMode(); + mainFragment.updateBoardItems(b, null); + pager.setCurrentItem(0); + navigationView.getMenu().findItem(R.id.nav_recent_post).setChecked(false); + } + } + return true; + } + + public Board getBoardFromDir(String dir){ + for (Board b : boardList){ + if (b.getBoardDir().equals(dir)){ + return b; + } + } + System.out.println("[MainActivity] Board not found " + dir); + return null; + } + + + @Override + public void onFragmentInteraction(Uri uri) { + + } + + @Override + public void showThread(Board board, BoardItem thread) { + childFragment.updateBoardItems(board, thread); + pager.setCurrentItem(1); + } + + + @Override + public void updateToolbar(Board cBoard, BoardItem btem) { + if (pager.getCurrentItem() == 1){ + toolbar.setTitle(cBoard.getBoardName()); + toolbar.setSubtitle(btem.getSubject()); + } + } + + @Override + public void updateToolbar(String s) { + toolbar.setTitle(s); + toolbar.setSubtitle(""); + } + + @Override + public void hideActionButton() { + if (pager.getCurrentItem() == 1){ + fab.hide(); + } + } + + @Override + public void showActionButton() { + if (pager.getCurrentItem() == 1){ + fab.show(); + } + } + + private void getBoardList(){ + Menu menu = navigationView.getMenu(); + final SubMenu sub = menu.addSubMenu("Lista de Boards"); + Ion.with(getApplicationContext()) + .load("http://bienvenidoainternet.org/cgi/api/boards") + .asJsonObject() + .setCallback(new FutureCallback<JsonObject>() { + @Override + public void onCompleted(Exception e, JsonObject result) { + if (e != null) { + e.printStackTrace(); + Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); + } else { + JsonArray boards = result.get("boards").getAsJsonArray(); + for (int i = 0; i < boards.size(); i++) { + try { + JSONObject board = new JSONObject(boards.get(i).toString()); + Board parsedBoard = new Board(board.getString("name"), board.getString("dir"), board.getInt("board_type")); + sub.add(parsedBoard.getBoardName()); + boardList.add(parsedBoard); + } catch (JSONException e1) { + e1.printStackTrace(); + Toast.makeText(getApplicationContext(), "Error parsing JSON", Toast.LENGTH_LONG).show(); + } + } + } + } + }); + refreshNavigator(); + } + + public void refreshNavigator(){ + for (int i = 0, count = navigationView.getChildCount(); i < count; i++) { + final View child = navigationView.getChildAt(i); + if (child != null && child instanceof ListView) { + final ListView menuView = (ListView) child; + final HeaderViewListAdapter adapter = (HeaderViewListAdapter) menuView.getAdapter(); + final BaseAdapter wrapped = (BaseAdapter) adapter.getWrappedAdapter(); + wrapped.notifyDataSetChanged(); + } + } + } + /* + Crea una secuencia de caracteres de 8 digitos aleatorios (incluye mayusculas, minisculas y numeros). + */ + + public String makePassword(){ + Random r = new Random(); + String rnd = ""; + for (int i = 0; i < 8; i++){ + int a = r.nextInt(3); + char b; + if (a == 0){ + b = (char)(66 + r.nextInt(25)); + }else if (a == 1){ + b = (char)(97 + r.nextInt(25)); + }else{ + b = (char) (48 + r.nextInt(9)); + } + rnd = rnd + b; + } + return rnd; + } + + public void checkForUpdates(){ + Ion.with(getApplicationContext()) + .load("http://ahri.xyz/bai/version.php") + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + if (e != null){ + e.printStackTrace(); + }else{ + try { + JSONObject version = new JSONObject(result); + float lastVersion = (float) version.getDouble("version"); + if (CURRENT_VERSION == lastVersion){ + Log.v("Updater", "Up to date"); + }else{ + Log.v("Updater", "New version available : " + lastVersion); + Snackbar.make(getCurrentFocus(), "Nueva versión disponible", Snackbar.LENGTH_LONG) + .setAction("Actualizar", new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent updater = new Intent(getApplicationContext(), UpdaterActivity.class); + startActivity(updater); + } + }) + .setActionTextColor(Color.rgb(255,127,0)) + .show(); + } + } catch (JSONException e1) { + e1.printStackTrace(); + } + } + } + }); + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/RecentPostAdapter.java b/app/src/main/java/org/bienvenidoainternet/baiparser/RecentPostAdapter.java new file mode 100644 index 0000000..e67f276 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/RecentPostAdapter.java @@ -0,0 +1,90 @@ +package org.bienvenidoainternet.baiparser; + +import android.content.Context; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import org.bienvenidoainternet.baiparser.structure.BoardItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Created by Renard on 21-03-2016. + */ +public class RecentPostAdapter extends ArrayAdapter<BoardItem> { + + public RecentPostAdapter(Context context, List<BoardItem> objects) { + super(context, 0, objects); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater)getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View listItemView = convertView; + if (null == convertView) { + listItemView = inflater.inflate( + R.layout.recentpost_item, + parent, + false); + } + final BoardItem postItem = getItem(position); + TextView rp_message = (TextView) listItemView.findViewById(R.id.rp_message); + TextView rp_title = (TextView) listItemView.findViewById(R.id.rp_title); + TextView rp_timediff = (TextView) listItemView.findViewById(R.id.rp_timediff); + if (postItem.getParentBoard() != null){ + rp_title.setText(postItem.getParentBoard().getBoardName() + ": " + postItem.getSubject()); + }else{ + rp_title.setText(postItem.getSubject()); + } + rp_message.setText(Html.fromHtml(postItem.getMessage())); + Map<TimeUnit,Long> timeDiff = computeDiff(new Date(postItem.getTimeStamp() * 1000L), new Date(System.currentTimeMillis())); + String strTimeDiff = ""; + if (timeDiff.get(TimeUnit.SECONDS) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.SECONDS) + (timeDiff.get(TimeUnit.SECONDS) == 1 ? " segundo" : " segundos"); + } + + if (timeDiff.get(TimeUnit.MINUTES) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.MINUTES) + (timeDiff.get(TimeUnit.MINUTES) == 1 ? " minuto" : " minutos"); + } + + if (timeDiff.get(TimeUnit.HOURS) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.HOURS) + (timeDiff.get(TimeUnit.HOURS) == 1 ? " hora" : " horas"); + } + + if (timeDiff.get(TimeUnit.DAYS) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.DAYS) + (timeDiff.get(TimeUnit.DAYS) == 1 ? " día" : " días"); + } + rp_timediff.setText(strTimeDiff); + + + return listItemView; + } + + + public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) { + long diffInMillies = date2.getTime() - date1.getTime(); + List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class)); + Collections.reverse(units); + Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>(); + long milliesRest = diffInMillies; + for ( TimeUnit unit : units ) { + long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS); + long diffInMilliesForUnit = unit.toMillis(diff); + milliesRest = milliesRest - diffInMilliesForUnit; + result.put(unit,diff); + } + return result; + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/ResponseActivity.java b/app/src/main/java/org/bienvenidoainternet/baiparser/ResponseActivity.java new file mode 100644 index 0000000..b319426 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/ResponseActivity.java @@ -0,0 +1,216 @@ +package org.bienvenidoainternet.baiparser; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.koushikdutta.async.future.FutureCallback; +import com.koushikdutta.ion.Ion; + +import org.bienvenidoainternet.baiparser.structure.Board; +import org.bienvenidoainternet.baiparser.structure.BoardItem; +import org.w3c.dom.Document; + +import java.io.File; + +import utils.ContentProviderUtils; + +//import org.apache.http.HttpEntity; +//import org.apache.http.entity.ContentType; +//import org.apache.http.entity.mime.HttpMultipartMode; +//import org.apache.http.entity.mime.MultipartEntityBuilder; +//import org.apache.http.entity.mime.content.FileBody; +//import org.apache.http.entity.mime.content.StringBody; + +public class ResponseActivity extends AppCompatActivity { + + private BoardItem theReply = null; + private Board currentBoard = null; + private SharedPreferences settings; + private String password; + private String selectedFile = ""; + private final int PICK_IMAGE = 1; + EditText filePath; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_response); + settings = PreferenceManager.getDefaultSharedPreferences(this); + password = settings.getString("pref_password", "12345678"); + Log.v("password", password); + + if (savedInstanceState != null){ + this.theReply = savedInstanceState.getParcelable("theReply"); + this.currentBoard = savedInstanceState.getParcelable("theBoard"); + } + if (getIntent().getExtras() != null){ + this.theReply = getIntent().getParcelableExtra("theReply"); + this.currentBoard = getIntent().getParcelableExtra("theBoard"); + } + if (theReply != null && currentBoard != null){ + System.out.println(theReply.getId() + " " + theReply.getName()); + } + + LinearLayout layoutProcess = (LinearLayout)findViewById(R.id.layoutPostProcess); + layoutProcess.setVisibility(View.GONE); + filePath = (EditText) findViewById(R.id.txtFilePath); + Button send = (Button)findViewById(R.id.btnSend); + send.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TextView txtName = (TextView) findViewById(R.id.txtPosterName); + TextView txtEmail = (TextView) findViewById(R.id.txtEmail); + TextView txtMessage = (TextView) findViewById(R.id.txtResponse); + makePost(txtName.getText().toString(), txtEmail.getText().toString(), txtMessage.getText().toString()); + + } + }); + + Button bBold = (Button) findViewById(R.id.buttonBold); + bBold.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TextView txtMessage = (TextView) findViewById(R.id.txtResponse); + if (txtMessage.getSelectionStart() == -1){ + txtMessage.setText(txtMessage.getText() + "<b></b>"); + }else{ + String s = txtMessage.getText().toString(); + String a = s.substring(0, txtMessage.getSelectionStart()); + String b = s.substring(txtMessage.getSelectionStart(), txtMessage.getSelectionEnd()); + String c = s.substring(txtMessage.getSelectionEnd(), txtMessage.getText().length()); + txtMessage.setText(a + "<b>" + b + "</b>" + c); + } + } + }); + Button bItalic = (Button) findViewById(R.id.buttonItalic); + bItalic.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TextView txtMessage = (TextView) findViewById(R.id.txtResponse); + if (txtMessage.getSelectionStart() == -1){ + txtMessage.setText(txtMessage.getText() + "<i></i>"); + }else{ + String s = txtMessage.getText().toString(); + String a = s.substring(0, txtMessage.getSelectionStart()); + String b = s.substring(txtMessage.getSelectionStart(), txtMessage.getSelectionEnd()); + String c = s.substring(txtMessage.getSelectionEnd(), txtMessage.getText().length()); + txtMessage.setText(a + "<i>" + b + "</i>" + c); + } + } + }); + + Button select = (Button) findViewById(R.id.btnSelectFiles); + + select.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(Intent.createChooser(intent, "Seleccionar Archivo"), PICK_IMAGE); + } + }); + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PICK_IMAGE && resultCode == RESULT_OK && null != data) { + Uri selectedImage = data.getData(); + String picturePath = ContentProviderUtils.getPath(getApplicationContext(), selectedImage); + selectedFile = picturePath; + filePath.setText(picturePath); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + private void makePost(String name, String email, String message){ + int parentId = theReply.getParentId(); + if (theReply.getParentId() == 0 || theReply.getParentId() == -1){ + parentId = theReply.getId(); + } + LinearLayout layoutProcess = (LinearLayout)findViewById(R.id.layoutPostProcess); + layoutProcess.setVisibility(View.VISIBLE); + final RelativeLayout formSendPost = (RelativeLayout) findViewById(R.id.layoutForm); + formSendPost.setVisibility(View.GONE); + ProgressBar progess = (ProgressBar) findViewById(R.id.barPosting); + final TextView err = (TextView)findViewById(R.id.txtPostingState); + err.setText(""); + File up = new File(selectedFile); + if (selectedFile.isEmpty()) Ion.with(getApplicationContext()) + .load("http://bienvenidoainternet.org/cgi/post") + .setLogging("posting", Log.VERBOSE) + .uploadProgressBar(progess) + .setMultipartParameter("board", currentBoard.getBoardDir()) + .setMultipartParameter("parent", String.valueOf(theReply.realParentId())) + .setMultipartParameter("password", password) + .setMultipartParameter("fielda", name) + .setMultipartParameter("fieldb", email) + .setMultipartParameter("name", "") + .setMultipartParameter("email", "") + .setMultipartParameter("message", message) + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + Log.v("sendPost", result); + if (e != null){ + Toast.makeText(getApplicationContext(), "Ha ocurrido un error! ;_;", Toast.LENGTH_LONG).show(); + formSendPost.setVisibility(View.VISIBLE); + err.setText("Error: " + e.getMessage()); + e.printStackTrace(); + }else{ + Toast.makeText(getApplicationContext(), "Post enviado", Toast.LENGTH_LONG).show(); + finish(); + } + } + }); + else{ + Ion.with(getApplicationContext()) + .load("http://bienvenidoainternet.org/cgi/post") + .uploadProgressBar(progess) + .setMultipartParameter("board", currentBoard.getBoardDir()) + .setMultipartParameter("parent", String.valueOf(parentId)) + .setMultipartParameter("password", password) + .setMultipartParameter("fielda", name) + .setMultipartParameter("fieldb", email) + .setMultipartParameter("name", "") + .setMultipartParameter("email", "") + .setMultipartParameter("message", message) + .setMultipartFile("file", up) + .asDocument() + .setCallback(new FutureCallback<Document>() { + @Override + public void onCompleted(Exception e, Document result) { + if (e != null){ + Toast.makeText(getApplicationContext(), "Ha ocurrido un error! ;_;", Toast.LENGTH_LONG).show(); + formSendPost.setVisibility(View.VISIBLE); + err.setText("Error: " + e.getMessage()); + e.printStackTrace(); + }else{ + Toast.makeText(getApplicationContext(), "Post enviado", Toast.LENGTH_LONG).show(); + finish(); + } + } + }); + } + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/SettingsActivity.java b/app/src/main/java/org/bienvenidoainternet/baiparser/SettingsActivity.java new file mode 100644 index 0000000..e8e7df4 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/SettingsActivity.java @@ -0,0 +1,184 @@ +package org.bienvenidoainternet.baiparser; + + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; +import android.support.v7.app.ActionBar; +import android.view.MenuItem; + +import java.util.List; + +/** + * A {@link PreferenceActivity} that presents a set of application settings. On + * handset devices, settings are presented as a single list. On tablets, + * settings are split by category, with category headers shown to the left of + * the list of settings. + * <p/> + * See <a href="http://developer.android.com/design/patterns/settings.html"> + * Android Design: Settings</a> for design guidelines and the <a + * href="http://developer.android.com/guide/topics/ui/settings.html">Settings + * API Guide</a> for more information on developing a Settings UI. + */ +public class SettingsActivity extends AppCompatPreferenceActivity { + /** + * A preference value change listener that updates the preference's summary + * to reflect its new value. + */ + private static boolean requireReset = false; + private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + String stringValue = value.toString(); + + if (preference instanceof ListPreference) { + // For list preferences, look up the correct display value in + // the preference's 'entries' list. + ListPreference listPreference = (ListPreference) preference; + int index = listPreference.findIndexOfValue(stringValue); + + // Set the summary to reflect the new value. + preference.setSummary( + index >= 0 + ? listPreference.getEntries()[index] + : null); + + }else { + // For all other preferences, set the summary to the value's + // simple string representation. + preference.setSummary(stringValue); + } + System.out.println(preference.getKey()); + return true; + } + }; + + /** + * Helper method to determine if the device has an extra-large screen. For + * example, 10" tablets are extra-large. + */ + private static boolean isXLargeTablet(Context context) { + return (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; + } + + /** + * Binds a preference's summary to its value. More specifically, when the + * preference's value is changed, its summary (line of text below the + * preference title) is updated to reflect the value. The summary is also + * immediately updated upon calling this method. The exact display format is + * dependent on the type of preference. + * + * @see #sBindPreferenceSummaryToValueListener + */ + private static void bindPreferenceSummaryToValue(Preference preference) { + // Set the listener to watch for value changes. + preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); + requireReset = true; + // Trigger the listener immediately with the preference's + // current value. + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, + PreferenceManager + .getDefaultSharedPreferences(preference.getContext()) + .getString(preference.getKey(), "")); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setupActionBar(); + getFragmentManager().beginTransaction().replace(android.R.id.content, new GeneralPreferenceFragment()).commit(); + } + + /** + * Set up the {@link android.app.ActionBar}, if the API is available. + */ + private void setupActionBar() { + ActionBar actionBar = getSupportActionBar(); + + if (actionBar != null) { + // Show the Up button in the action bar. + actionBar.setDisplayHomeAsUpEnabled(true); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onIsMultiPane() { + return isXLargeTablet(this); + } + + /** + * {@inheritDoc} + */ + @Override + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void onBuildHeaders(List<Header> target) { +// loadHeadersFromResource(R.xml.pref_headers, target); + } + + /** + * This method stops fragment injection in malicious applications. + * Make sure to deny any unknown fragments here. + */ + protected boolean isValidFragment(String fragmentName) { + return PreferenceFragment.class.getName().equals(fragmentName) + || GeneralPreferenceFragment.class.getName().equals(fragmentName) + ; + } + + @Override + public void onBackPressed() { + Intent returnIntent = new Intent(); + returnIntent.putExtra("result", requireReset); + setResult(Activity.RESULT_OK,returnIntent); + finish(); + super.onBackPressed(); + } + + /** + * This fragment shows general preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public class GeneralPreferenceFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + setHasOptionsMenu(true); + + // Bind the summaries of EditText/List/Dialog/Ringtone preferences + // to their values. When their values change, their summaries are + // updated to reflect the new value, per the Android Design + // guidelines. +// bindPreferenceSummaryToValue(findPreference("example_text")); + bindPreferenceSummaryToValue(findPreference("pref_theme")); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == android.R.id.home) { +// startActivity(new Intent(getActivity(), SettingsActivity.class)); + Intent returnIntent = new Intent(); + returnIntent.putExtra("result",requireReset); + setResult(Activity.RESULT_OK,returnIntent); + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/ThemeManager.java b/app/src/main/java/org/bienvenidoainternet/baiparser/ThemeManager.java new file mode 100644 index 0000000..7f0be86 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/ThemeManager.java @@ -0,0 +1,55 @@ +package org.bienvenidoainternet.baiparser; + +import android.content.res.TypedArray; +import android.graphics.Color; + +/** + * Created by Renard on 16-03-2016. + */ +public class ThemeManager { + private MainActivity ac; + private int currentThemeId; + public ThemeManager(MainActivity ac){ + this.ac = ac; + this.currentThemeId = ac.getCurrentThemeId(); + } + + public int getSageColor(){ + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.sageColor}); + return a.getColor(0, Color.CYAN); + } + + public int getMarginColor(){ + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.marginColor}); + return a.getColor(0, Color.CYAN); + } + + public void updateThemeId(int id){ + this.currentThemeId = id; + } + + public int getNameColor() { + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.nameColor}); + return a.getColor(0, Color.CYAN); + } + + public int getTripcodeColor() { + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.tripcodeColor}); + return a.getColor(0, Color.CYAN); + } + + public int getPrimaryColor(){ + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.colorPrimary}); + return a.getColor(0, Color.CYAN); + } + public int getPrimaryDarkColor(){ + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.colorPrimaryDark}); + return a.getColor(0, Color.CYAN); + } + + public boolean isDarkTheme(){ + TypedArray a = ac.getTheme().obtainStyledAttributes(currentThemeId, new int[]{R.attr.isDarkTheme}); + return a.getBoolean(0, false); + } + +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/ThreadListAdapter.java b/app/src/main/java/org/bienvenidoainternet/baiparser/ThreadListAdapter.java new file mode 100644 index 0000000..118e9c6 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/ThreadListAdapter.java @@ -0,0 +1,281 @@ +package org.bienvenidoainternet.baiparser; + +import android.animation.ArgbEvaluator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.graphics.drawable.ColorDrawable; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Html; +import android.text.Layout; +import android.text.Spannable; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import org.bienvenidoainternet.baiparser.structure.BoardItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Created by Renard on 11-03-2016. + */ +public class ThreadListAdapter extends ArrayAdapter<BoardItem>{ + private Context context; + private ThemeManager tm; + Typeface monaFont; + public boolean listThreads = false; + + public ThreadListAdapter(Context context, List<BoardItem> objects, ThemeManager tm) { + super(context, 0, objects); + this.context = context; + this.tm = tm; + monaFont = Typeface.createFromAsset(context.getAssets(), "fonts/mona.ttf"); + } + + private String intToHexString(int i){ + return String.format("#%06X", (0xFFFFFF & i)); + } + public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) { + long diffInMillies = date2.getTime() - date1.getTime(); + List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class)); + Collections.reverse(units); + Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>(); + long milliesRest = diffInMillies; + for ( TimeUnit unit : units ) { + long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS); + long diffInMilliesForUnit = unit.toMillis(diff); + milliesRest = milliesRest - diffInMilliesForUnit; + result.put(unit,diff); + } + return result; + } + @Override + public View getView(int position, final View convertView, final ViewGroup parent){ + LayoutInflater inflater = (LayoutInflater)getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View listItemView = convertView; + if (null == convertView) { + listItemView = inflater.inflate( + R.layout.thread_item, + parent, + false); + } + + final BoardItem boardItem = getItem(position); + if (boardItem == null){ + return listItemView; + } + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this.getContext()); + boolean useMonaFont = settings.getBoolean("setting_monafont", true); + boolean monaBbsOnly = settings.getBoolean("setting_mona_bbsonly", true); + int marginColor = tm.getMarginColor(); + int sageColor = tm.getSageColor(); + int nameColor = tm.getNameColor(); + int tripcodeColor = tm.getTripcodeColor(); + String hexColor =intToHexString(boardItem.getIdColor()); + String sageHexColor = intToHexString(sageColor); + String nameHexColor = intToHexString(nameColor); + String tripcodeHexColor = intToHexString(tripcodeColor); + String strId = ""; + + TextView txtTitle = (TextView)listItemView.findViewById(R.id.lv_txtTitle); + TextView txtPoster = (TextView)listItemView.findViewById(R.id.lv_txtPoster); + TextView txtBody = (TextView) listItemView.findViewById(R.id.lv_txtBody); + TextView txtReplies = (TextView) listItemView.findViewById(R.id.lv_txtReplyCounter); + TextView txtFileInfo = (TextView) listItemView.findViewById(R.id.lv_txtFileInfo); + ImageView ivMargin = (ImageView)listItemView.findViewById(R.id.ivMargin); + ImageView ivThumb = (ImageView)listItemView.findViewById(R.id.ivThumb); + + ivThumb.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!boardItem.getThumb().isEmpty() && convertView != null){ + if (boardItem.getFile().endsWith(".webm")){ + Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse("http://bienvenidoainternet.org/" + boardItem.getParentBoard().getBoardDir() + "/src/" + boardItem.getFile())); + in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + v.getContext().startActivity(in); + }else { + Intent in = new Intent(convertView.getContext(), ViewerActivity.class); + Bundle b = new Bundle(); + b.putParcelable("boardItem", boardItem); + in.putExtras(b); + convertView.getContext().startActivity(in); + } + } + } + }); + + + ivMargin.setImageDrawable(new ColorDrawable(marginColor)); + + if (useMonaFont){ + if (monaBbsOnly && boardItem.getParentBoard() != null){ + if (boardItem.getParentBoard().getBoardType() == 1){ + txtBody.setTypeface(monaFont); + } + }else{ + txtBody.setTypeface(monaFont); + } + } + + // Si es una respuesta ocultamos el margen + if (boardItem.isReply){ + ivMargin.setVisibility(View.VISIBLE); + txtTitle.setVisibility(View.GONE); + }else{ + txtTitle.setVisibility(View.VISIBLE); + ivMargin.setVisibility(View.GONE); + txtTitle.setText(boardItem.getSubject()); + } + + // Si el fragmento esta viendo un hilo ocultamos los margenes + if (listThreads){ + ivMargin.setVisibility(View.GONE); + } + + // Si el item está eliminado activamos el soporte de <strike> + if (boardItem.getDeletedCode() != 0){ + txtBody.setPaintFlags(txtBody.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + }else{ + txtBody.setPaintFlags(txtBody.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG)); + } + + + if (boardItem.getThumb().isEmpty()){ + ivThumb.setVisibility(View.GONE); + }else{ + if (boardItem.getThumbBitmap() != null){ + ivThumb.setVisibility(View.VISIBLE); + ivThumb.setImageBitmap(boardItem.getThumbBitmap()); + }else{ + ivThumb.setVisibility(View.VISIBLE); + ivThumb.setImageResource(R.drawable.blank); + } + } + + Map<TimeUnit,Long> timeDiff = computeDiff(new Date(boardItem.getTimeStamp() * 1000L), new Date(System.currentTimeMillis())); + String strTimeDiff = ""; + if (timeDiff.get(TimeUnit.SECONDS) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.SECONDS) + (timeDiff.get(TimeUnit.SECONDS) == 1 ? " segundo" : " segundos"); + } + if (timeDiff.get(TimeUnit.MINUTES) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.MINUTES) + (timeDiff.get(TimeUnit.MINUTES) == 1 ? " minuto" : " minutos"); + } + if (timeDiff.get(TimeUnit.HOURS) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.HOURS) + (timeDiff.get(TimeUnit.HOURS) == 1 ? " hora" : " horas"); + } + if (timeDiff.get(TimeUnit.DAYS) != 0){ + strTimeDiff = "Hace " + timeDiff.get(TimeUnit.DAYS) + (timeDiff.get(TimeUnit.DAYS) == 1 ? " día" : " días"); + } + + + if (!boardItem.getPosterId().isEmpty() && !boardItem.getPosterId().equals("???")){ + strId = "<font color=" + hexColor + ">[" + boardItem.getPosterId() + "]</font> "; + } + + // Si estamos mostrando un item de BBS, mostrar el ID_BBS en ves del ID del post + int idToDisplay = 0; + if (boardItem.getParentBoard() != null){ + if (boardItem.getParentBoard().getBoardType() == 1){ + idToDisplay = boardItem.getBbsId(); + }else{ + idToDisplay = boardItem.getId(); + } + }else{ + idToDisplay = boardItem.getId(); + } + + txtPoster.setText(Html.fromHtml("<b>No. " + idToDisplay + "</b> por <font color=" + (boardItem.isSage() ? sageHexColor : nameHexColor) + ">" + boardItem.getName() + "</font> " + + (boardItem.getTripcode() == "" ? "" : "<font color=" + tripcodeHexColor + ">" + boardItem.getTripcode() + "</font>") + strId + " " + strTimeDiff)); + txtBody.setText(Html.fromHtml(boardItem.getMessage())); + + txtReplies.setVisibility(boardItem.isReply ? View.GONE : View.VISIBLE); + txtReplies.setText(boardItem.getTotalReplies() + " respuestas " + (boardItem.getTotalFiles() == 0 ? "" : ", " + boardItem.getTotalFiles() + " archivos")); + + txtFileInfo.setVisibility(boardItem.getThumb().isEmpty() ? View.GONE : View.VISIBLE); + txtFileInfo.setText((boardItem.getFileSize() / 1024) + " KB " + boardItem.getThumbHeight() + "x" + boardItem.getThumbWidth()); + + // Trasnparentar items con sage + if (convertView != null){ + convertView.setAlpha(boardItem.isSage() ? 0.75F : 1.0F); + } + + /* + http://stackoverflow.com/questions/8558732/listview-textview-with-linkmovementmethod-makes-list-item-unclickable + */ + txtBody.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + boolean ret = false; + CharSequence text = ((TextView) v).getText(); + Spannable stext = Spannable.Factory.getInstance().newSpannable(text); + TextView widget = (TextView) v; + int action = event.getAction(); + + if (action == MotionEvent.ACTION_UP || + action == MotionEvent.ACTION_DOWN) { + int x = (int) event.getX(); + int y = (int) event.getY(); + + x -= widget.getTotalPaddingLeft(); + y -= widget.getTotalPaddingTop(); + + x += widget.getScrollX(); + y += widget.getScrollY(); + + Layout layout = widget.getLayout(); + int line = layout.getLineForVertical(y); + int off = layout.getOffsetForHorizontal(line, x); + + ClickableSpan[] link = stext.getSpans(off, off, ClickableSpan.class); +/*04-03 17:46:54.646 13693-13693/org.bienvenidoainternet.baiparser V/URLParts: zonavip +04-03 17:46:54.646 13693-13693/org.bienvenidoainternet.baiparser V/URLParts: read +04-03 17:46:54.646 13693-13693/org.bienvenidoainternet.baiparser V/URLParts: 43872 +04-03 17:46:54.650 13693-13693/org.bienvenidoainternet.baiparser V/URLParts: 25*/ + if (link.length != 0) { + if (link[0] instanceof URLSpan){ + URLSpan uspan = (URLSpan) link[0]; + if (uspan.getURL().contains("/read/") && !uspan.getURL().contains("http")){ + String url = uspan.getURL(); + String[] parts = url.split("/"); + if (parts.length == 4 && listThreads){ + Log.v("ConvertView", convertView.getParent().toString()); + } + return true; + } + } + if (action == MotionEvent.ACTION_UP) { + link[0].onClick(widget); + } + ret = true; + } + } + return ret; + } + }); + return listItemView; + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/UpdaterActivity.java b/app/src/main/java/org/bienvenidoainternet/baiparser/UpdaterActivity.java new file mode 100644 index 0000000..e98f303 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/UpdaterActivity.java @@ -0,0 +1,127 @@ +package org.bienvenidoainternet.baiparser; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.net.Uri; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.text.Html; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.koushikdutta.async.future.FutureCallback; +import com.koushikdutta.ion.Ion; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; + +public class UpdaterActivity extends AppCompatActivity { + private float lastVersion = 1.0F; + Button btnUpdate; + ProgressBar barUpdate; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_updater); + setTheme(R.style.AppTheme_Black_Activity); + btnUpdate = (Button) findViewById(R.id.btnDownloadLastVersion); + barUpdate = (ProgressBar) findViewById(R.id.barUpdateProgress); + TextView txtCurrentVersion = (TextView) findViewById(R.id.txtCurrentVersion); + btnUpdate.setEnabled(false); + txtCurrentVersion.setText("Versión actual: " + MainActivity.CURRENT_VERSION); + getVersionData(); + btnUpdate.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + downloadApk(); + } + }); + } + + private void getVersionData(){ + Ion.with(getApplicationContext()) + .load("http://ahri.xyz/bai/version.php") + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + if (e != null) { + e.printStackTrace(); + } else { + JSONObject version = null; + try { + version = new JSONObject(result); + lastVersion = (float) version.getDouble("version"); + TextView txtLastVersion = (TextView) findViewById(R.id.txtLastVersion); + txtLastVersion.setText("Última versión: " + lastVersion); + + if (lastVersion > MainActivity.CURRENT_VERSION) { + getChangelog(); + btnUpdate.setEnabled(true); + } + } catch (JSONException e1) { + e1.printStackTrace(); + } + } + } + }); + } + + private void getChangelog(){ + Ion.with(getApplicationContext()) + .load("http://ahri.xyz/bai/lastChangelog.txt") + .asString() + .setCallback(new FutureCallback<String>() { + @Override + public void onCompleted(Exception e, String result) { + if (e != null){ + e.printStackTrace(); + }else{ + TextView txtChangelog = (TextView) findViewById(R.id.txtChangelog); + txtChangelog.setText(Html.fromHtml(result)); + } + } + }); + } + + private void downloadApk(){ + ContextWrapper cw = new ContextWrapper(getApplicationContext()); + File directory = cw.getDir("src", Context.MODE_PRIVATE); + if (!directory.exists()) { + directory.mkdir(); + } + final File filePath = new File(directory, "last.apk"); + if (filePath.exists()) { + filePath.delete(); + } + Ion.with(getApplicationContext()) + .load("http://ahri.xyz/bai/" + lastVersion + "/last.apk") + .setLogging("Updater", Log.VERBOSE) + .progressBar(barUpdate) + .write(filePath) + .setCallback(new FutureCallback<File>() { + @Override + public void onCompleted(Exception e, File result) { + if (e != null) { + Toast.makeText(getApplicationContext(), "Error: " + e.getMessage(), Toast.LENGTH_LONG).show(); + } else { + Intent promptInstall = new Intent(Intent.ACTION_VIEW) + .setDataAndType(Uri.fromFile(filePath), + "application/vnd.android.package-archive"); + startActivity(promptInstall); + } + } + }); + } +} + + diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/ViewerActivity.java b/app/src/main/java/org/bienvenidoainternet/baiparser/ViewerActivity.java new file mode 100644 index 0000000..b113c2a --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/ViewerActivity.java @@ -0,0 +1,247 @@ +package org.bienvenidoainternet.baiparser; + +import android.content.Context; +import android.content.ContextWrapper; +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.support.v7.app.AppCompatActivity; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.davemorrissey.labs.subscaleview.ImageSource; +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView; +import com.koushikdutta.async.future.FutureCallback; +import com.koushikdutta.ion.Ion; + +import org.bienvenidoainternet.baiparser.structure.BoardItem; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import pl.droidsonroids.gif.GifDrawable; +import pl.droidsonroids.gif.GifImageView; + +public class ViewerActivity extends AppCompatActivity { + private SubsamplingScaleImageView imageView; + private GifImageView gifView; + private BoardItem bi; + File imagePath; + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + +// SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); +// int themeId = Integer.valueOf(settings.getString("setting_theme", "1")), currentThemeId = R.style.AppTheme; +// switch (themeId) { +// case 1: +// currentThemeId = R.style.AppTheme_NoActionBar; +// break; +// case 2: +// currentThemeId = R.style.AppTheme_Dark; +// break; +// case 3: +// currentThemeId = R.style.AppTheme_HeadLine; +// break; +// case 4: +// currentThemeId = R.style.AppTheme_Black; +// break; +// } +// setTheme(currentThemeId); + + + if (savedInstanceState != null){ + bi = savedInstanceState.getParcelable("boardItem"); + } + if (getIntent().getExtras() != null){ + bi = getIntent().getParcelableExtra("boardItem"); + } + setContentView(R.layout.activity_viewer); + imageView = (SubsamplingScaleImageView)findViewById(R.id.imageView); + gifView = (GifImageView) findViewById(R.id.gifView); + setTitle(bi.getFile()); +// imageView.setOnClickListener(new View.OnClickListener() { +// new TaskDownloadFile().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + downloadFile(); + this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + File baiDir = new File(Environment.getExternalStorageDirectory().getPath() + "/Bai/"); + if (!baiDir.exists()){ + baiDir.mkdir(); + } + if (item.getItemId() == R.id.menu_save_img){ + File to = new File(Environment.getExternalStorageDirectory().getPath() + "/Bai/" + bi.getFile()); + try{ + InputStream in = new FileInputStream(imagePath); + OutputStream out = new FileOutputStream(to); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + Toast.makeText(getApplicationContext(), bi.getFile() + " guardado.", Toast.LENGTH_LONG).show(); + }catch (Exception e){ + e.printStackTrace(); + } + + } + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + } + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_viewer, menu); + return true; + } + + private void downloadFile(){ + ContextWrapper cw = new ContextWrapper(getApplicationContext()); + File directory = cw.getDir("src", Context.MODE_PRIVATE); + final File filePath = new File(directory, bi.getParentBoard().getBoardDir() + "_" + bi.getFile()); + final ProgressBar downloadBar = (ProgressBar) findViewById(R.id.downloadProgressBar); + if (filePath.exists()){ + downloadBar.setVisibility(View.GONE); + if (bi.getFile().endsWith(".gif")){ + try { + GifDrawable gifFromFile = new GifDrawable(filePath); + gifView.setImageDrawable(gifFromFile); + imageView.setVisibility(View.GONE); + }catch(Exception e){ + e.printStackTrace(); + } + }else{ + imageView.setImage(ImageSource.uri(filePath.toURI().getPath())); + gifView.setVisibility(View.GONE); + } + } + Ion.with(getApplicationContext()) + .load("http://bienvenidoainternet.org/" + bi.getParentBoard().getBoardDir() + "/src/" + bi.getFile()) + .progressBar(downloadBar) + .asInputStream() + .setCallback(new FutureCallback<InputStream>() { + @Override + public void onCompleted(Exception e, InputStream result) { + downloadBar.setVisibility(View.GONE); + if (e != null){ + e.printStackTrace(); + }else{ + FileOutputStream fout; + try { + fout = new FileOutputStream(filePath); + final byte data[] = new byte[1024]; + int count; + while ((count = result.read(data, 0, 1024)) != -1) { + fout.write(data, 0, count); + } + }catch(Exception e1) { + e1.printStackTrace(); + } + if (bi.getFile().endsWith(".gif")){ + try { + GifDrawable gifFromFile = new GifDrawable(filePath); + gifView.setImageDrawable(gifFromFile); + imageView.setVisibility(View.GONE); + }catch(Exception e2){ + e2.printStackTrace(); + } + }else{ + imageView.setImage(ImageSource.uri(filePath.toURI().getPath())); + gifView.setVisibility(View.GONE); + } + } + } + }); + } + + class TaskDownloadFile extends AsyncTask<Void, Void, File> { + + @Override + protected File doInBackground(Void... params) { + Bitmap downloadedBitmap = null; + ContextWrapper cw = new ContextWrapper(getApplicationContext()); + File directory = cw.getDir("src", Context.MODE_PRIVATE); + File mypath = new File(directory, bi.getParentBoard().getBoardDir() + "_" + bi.getFile()); + if (mypath.exists()){ + System.out.println("[Viewer] resource exist!"); + return mypath; + } + try { + String sUrl = "http://bienvenidoainternet.org/" + bi.getParentBoard().getBoardDir() + "/src/" + bi.getFile(); + System.out.println("[Viewer]dwonloading " + sUrl); +// System.out.println(sUrl); + InputStream in = new java.net.URL(sUrl).openStream(); +// downloadedBitmap = BitmapFactory.decodeStream(in); + +// if (downloadedBitmap != null){ + FileOutputStream fout = null; + try { +// in = new BufferedInputStream(new URL(urlString).openStream()); + fout = new FileOutputStream(mypath); + + final byte data[] = new byte[1024]; + int count; + while ((count = in.read(data, 0, 1024)) != -1) { + fout.write(data, 0, count); + } + + + }catch(Exception e){ + e.printStackTrace(); + }finally { + if (in != null) { + in.close(); + } + if (fout != null) { + fout.close(); + } + } +// } + } catch (Exception e) { + e.printStackTrace(); + } + + return mypath; + } + + @Override + protected void onPostExecute(File file) { + super.onPostExecute(file); + imagePath = file; +// iv.setImageBitmap(bitmap); + if (bi.getFile().endsWith(".gif")){ + try { + GifDrawable gifFromFile = new GifDrawable(file); + gifView.setImageDrawable(gifFromFile); + imageView.setVisibility(View.GONE); + }catch(Exception e){ + e.printStackTrace(); + } + }else{ + imageView.setImage(ImageSource.uri(file.toURI().getPath())); + gifView.setVisibility(View.GONE); +// imageView.setImage(ImageSource.resource(R.drawable.bai)); +// System.out.println("not a gif file: " + file.toURI().getPath()); + } + + } + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/structure/Board.java b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/Board.java new file mode 100644 index 0000000..209804e --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/Board.java @@ -0,0 +1,60 @@ +package org.bienvenidoainternet.baiparser.structure; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Created by Renard on 17-03-2016. + */ + +public class Board implements Parcelable{ + private String boardName, boardDir; + private int boardType; + public Board(String boardName,String boardDir,int boardType){ + this.boardName = boardName; + this.boardDir = boardDir; + this.boardType = boardType; + } + + public Board(Parcel in){ + this.boardName = in.readString(); + this.boardDir = in.readString(); + this.boardType = in.readInt(); + } + + public String getBoardDir() { + return boardDir; + } + + public String getBoardName() { + return boardName; + } + + public int getBoardType() { + return boardType; + } + + public static final Creator<Board> CREATOR = new Creator<Board>() { + @Override + public Board createFromParcel(Parcel in) { + return new Board(in); + } + + @Override + public Board[] newArray(int size) { + return new Board[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(boardName); + dest.writeString(boardDir); + dest.writeInt(boardType); + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/structure/BoardItem.java b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/BoardItem.java new file mode 100644 index 0000000..c43384a --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/BoardItem.java @@ -0,0 +1,310 @@ +package org.bienvenidoainternet.baiparser.structure; + +import android.graphics.Bitmap; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Created by Renard on 17-03-2016. + */ +public class BoardItem implements Parcelable { + private String name = ""; + private String timestamp_formatted = ""; + private String thumb = ""; + private String tripcode = ""; + private String email = ""; + private String file = ""; + private String message = ""; + private String subject = ""; + private String posterId = ""; + private int parentid, id, idcolor, totalreplies = 0, totalfiles, thumb_height, thumb_weight, filesize, deleted_code, bbs_id = 1, parentPostCount; + private long timestamp = 0; + + private Bitmap thumbBitmap = null; + public boolean downloadingThumb = false; + public boolean isReply = false; + private Board parentBoard = null; + + protected BoardItem(Parcel in) { + name = in.readString(); + timestamp_formatted = in.readString(); + thumb = in.readString(); + tripcode = in.readString(); + email = in.readString(); + file = in.readString(); + message = in.readString(); + subject = in.readString(); + posterId = in.readString(); + parentid = in.readInt(); + id = in.readInt(); + idcolor = in.readInt(); + totalreplies = in.readInt(); + totalfiles = in.readInt(); + thumb_height = in.readInt(); + thumb_weight = in.readInt(); + filesize = in.readInt(); + deleted_code = in.readInt(); + bbs_id = in.readInt(); + parentPostCount = in.readInt(); + timestamp = in.readLong(); + thumbBitmap = in.readParcelable(Bitmap.class.getClassLoader()); + downloadingThumb = in.readByte() != 0; + isReply = in.readByte() != 0; + parentBoard = in.readParcelable(Board.class.getClassLoader()); + } + + public static final Creator<BoardItem> CREATOR = new Creator<BoardItem>() { + @Override + public BoardItem createFromParcel(Parcel in) { + return new BoardItem(in); + } + + @Override + public BoardItem[] newArray(int size) { + return new BoardItem[size]; + } + }; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFile() { + return file; + } + + public void setFile(String file) { + this.file = file; + } + + public int getFileSize() { + return filesize; + } + + public void setFilesize(int filesize) { + this.filesize = filesize; + } + + public int getIdColor() { + return idcolor; + } + + public void setIdColor(int idcolor) { + this.idcolor = idcolor; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + // TODO: Dar formato a los mensajes de otra forma + this.message = message.replace("<span class=\"unkfunc\">", "<font color=#85c749><i>"); + this.message = this.message.replace("</span>", "</i></font>"); + if (this.message.contains("<hr")){ + this.message = this.message.replace("<hr />", "<br><br><small><font color=#FF8800><i>") + "</i></small></font>"; + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Board getParentBoard() { + return parentBoard; + } + + public void setParentBoard(Board parentBoard) { + this.parentBoard = parentBoard; + } + + public int getParentId() { + return parentid; + } + + public void setParentId(int parentid) { + this.parentid = parentid; + } + + public int getParentPostCount() { + return parentPostCount; + } + + public void setParentPostCount(int parentPostCount) { + this.parentPostCount = parentPostCount; + } + + public String getPosterId() { + return posterId; + } + + public void setPosterId(String posterId) { + this.posterId = posterId; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getThumb() { + return thumb; + } + + public void setThumb(String thumb) { + this.thumb = thumb; + } + + public int getThumbHeight() { + return thumb_height; + } + + public void setThumbHeight(int thumb_height) { + this.thumb_height = thumb_height; + } + + public int getThumbWidth() { + return thumb_weight; + } + + public void setThumbWidth(int thumb_weight) { + this.thumb_weight = thumb_weight; + } + + public Bitmap getThumbBitmap() { + return thumbBitmap; + } + + public void setThumbBitmap(Bitmap thumbBitmap) { + this.thumbBitmap = thumbBitmap; + } + + public long getTimeStamp() { + return timestamp; + } + + public void setTimeStamp(long timestamp) { + this.timestamp = timestamp; + } + + public String getTimeStampFormatted() { + return timestamp_formatted; + } + + public void setTimeStampFormatted(String timestamp_formatted) { + this.timestamp_formatted = timestamp_formatted; + } + + public int getTotalFiles() { + return totalfiles; + } + + public void setTotalFiles(int totalfiles) { + this.totalfiles = totalfiles; + } + + public int getTotalReplies() { + return totalreplies; + } + + public void setTotalReplies(int totalreplies) { + this.totalreplies = totalreplies; + } + + public String getTripcode() { + return tripcode; + } + + public void setTripcode(String tripcode) { + this.tripcode = tripcode; + } + + public int getDeletedCode() { + return deleted_code; + } + + public void setDeletedCode(int deleted_code) { + this.deleted_code = deleted_code; + if (deleted_code == 1){ + this.message = "Eliminado por el usuario."; + }else if (deleted_code == 2){ + this.message = "Eliminado por el Staff."; + } + } + + public int getBbsId() { + return bbs_id; + } + + public void setBbsId(int bbs_id) { + this.bbs_id = bbs_id; + } + + public int realParentId(){ + if (parentid == 0){ + return id; + } + return parentid; + } + + public BoardItem() { + + } + + public boolean isSage(){ + return this.email.equals("sage"); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(name); + dest.writeString(timestamp_formatted); + dest.writeString(thumb); + dest.writeString(tripcode); + dest.writeString(email); + dest.writeString(file); + dest.writeString(message); + dest.writeString(subject); + dest.writeString(posterId); + dest.writeInt(parentid); + dest.writeInt(id); + dest.writeInt(idcolor); + dest.writeInt(totalreplies); + dest.writeInt(totalfiles); + dest.writeInt(thumb_height); + dest.writeInt(thumb_weight); + dest.writeInt(filesize); + dest.writeInt(deleted_code); + dest.writeInt(bbs_id); + dest.writeInt(parentPostCount); + dest.writeLong(timestamp); + dest.writeParcelable(thumbBitmap, flags); + dest.writeByte((byte) (downloadingThumb ? 1 : 0)); + dest.writeByte((byte) (isReply ? 1 : 0)); + dest.writeParcelable(parentBoard, flags); + } +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/structure/JsonType.java b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/JsonType.java new file mode 100644 index 0000000..8db5c11 --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/JsonType.java @@ -0,0 +1,10 @@ +package org.bienvenidoainternet.baiparser.structure; + +/** + * Created by Renard on 17-03-2016. + */ +public enum JsonType { + BOARD_THREAD_LIST, + THREAD_REPLY_LIST, + BOARD_LIST; +} diff --git a/app/src/main/java/org/bienvenidoainternet/baiparser/structure/ReplyID.java b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/ReplyID.java new file mode 100644 index 0000000..b6758fb --- /dev/null +++ b/app/src/main/java/org/bienvenidoainternet/baiparser/structure/ReplyID.java @@ -0,0 +1,48 @@ +package org.bienvenidoainternet.baiparser.structure; + +import android.graphics.Color; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Random; + +/** + * Created by Renard on 18-03-2016. + */ +public class ReplyID implements Parcelable{ + public String id; + public int color; + public ReplyID(String id){ + this.id = id; + Random r = new Random(); + this.color = Color.rgb(r.nextInt(125) + 127, r.nextInt(127) + 127, r.nextInt(127) + 127); + } + + protected ReplyID(Parcel in) { + id = in.readString(); + color = in.readInt(); + } + + public static final Creator<ReplyID> CREATOR = new Creator<ReplyID>() { + @Override + public ReplyID createFromParcel(Parcel in) { + return new ReplyID(in); + } + + @Override + public ReplyID[] newArray(int size) { + return new ReplyID[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(id); + dest.writeInt(color); + } +} diff --git a/app/src/main/java/utils/ContentProviderUtils.java b/app/src/main/java/utils/ContentProviderUtils.java new file mode 100644 index 0000000..fca8477 --- /dev/null +++ b/app/src/main/java/utils/ContentProviderUtils.java @@ -0,0 +1,148 @@ +package utils; + +import android.annotation.TargetApi; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; + +/** + * Created by Paul Burke + * http://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-framework + */ + +public class ContentProviderUtils { + /** + * Get a file path from a Uri. This will get the the path for Storage Access + * Framework Documents, as well as the _data field for the MediaStore and + * other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @author paulburke + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + public static String getPath(final Context context, final Uri uri) { + + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + + // TODO handle non-primary volumes + } + // DownloadsProvider + else if (isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + + return getDataColumn(context, contentUri, null, null); + } + // MediaProvider + else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + return getDataColumn(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + return null; + } + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + */ + public static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, + null); + if (cursor != null && cursor.moveToFirst()) { + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_action_download.png b/app/src/main/res/drawable-hdpi/ic_action_download.png Binary files differnew file mode 100644 index 0000000..f08b335 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_download.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_font_bold.png b/app/src/main/res/drawable-hdpi/ic_action_font_bold.png Binary files differnew file mode 100644 index 0000000..480e2fb --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_font_bold.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_font_italic.png b/app/src/main/res/drawable-hdpi/ic_action_font_italic.png Binary files differnew file mode 100644 index 0000000..0405024 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_font_italic.png diff --git a/app/src/main/res/drawable-hdpi/ic_edit.png b/app/src/main/res/drawable-hdpi/ic_edit.png Binary files differnew file mode 100644 index 0000000..29046d9 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_edit.png diff --git a/app/src/main/res/drawable-hdpi/ic_refresh.png b/app/src/main/res/drawable-hdpi/ic_refresh.png Binary files differnew file mode 100644 index 0000000..455000e --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_refresh.png diff --git a/app/src/main/res/drawable-hdpi/ic_sync.png b/app/src/main/res/drawable-hdpi/ic_sync.png Binary files differnew file mode 100644 index 0000000..4840445 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_sync.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_download.png b/app/src/main/res/drawable-mdpi/ic_action_download.png Binary files differnew file mode 100644 index 0000000..76e1c9b --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_download.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_font_bold.png b/app/src/main/res/drawable-mdpi/ic_action_font_bold.png Binary files differnew file mode 100644 index 0000000..66242fc --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_font_bold.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_font_italic.png b/app/src/main/res/drawable-mdpi/ic_action_font_italic.png Binary files differnew file mode 100644 index 0000000..19868a5 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_font_italic.png diff --git a/app/src/main/res/drawable-mdpi/ic_addreply.png b/app/src/main/res/drawable-mdpi/ic_addreply.png Binary files differnew file mode 100644 index 0000000..cacba05 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_addreply.png diff --git a/app/src/main/res/drawable-mdpi/ic_edit.png b/app/src/main/res/drawable-mdpi/ic_edit.png Binary files differnew file mode 100644 index 0000000..559aac9 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_edit.png diff --git a/app/src/main/res/drawable-mdpi/ic_refresh.png b/app/src/main/res/drawable-mdpi/ic_refresh.png Binary files differnew file mode 100644 index 0000000..765ed43 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_refresh.png diff --git a/app/src/main/res/drawable-mdpi/ic_sync.png b/app/src/main/res/drawable-mdpi/ic_sync.png Binary files differnew file mode 100644 index 0000000..ecdd7f1 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_sync.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_download.png b/app/src/main/res/drawable-xhdpi/ic_action_download.png Binary files differnew file mode 100644 index 0000000..46501ca --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_download.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_font_bold.png b/app/src/main/res/drawable-xhdpi/ic_action_font_bold.png Binary files differnew file mode 100644 index 0000000..bec0285 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_font_bold.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_font_italic.png b/app/src/main/res/drawable-xhdpi/ic_action_font_italic.png Binary files differnew file mode 100644 index 0000000..1959c9f --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_font_italic.png diff --git a/app/src/main/res/drawable-xhdpi/ic_edit.png b/app/src/main/res/drawable-xhdpi/ic_edit.png Binary files differnew file mode 100644 index 0000000..daa50e6 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_edit.png diff --git a/app/src/main/res/drawable-xhdpi/ic_refresh.png b/app/src/main/res/drawable-xhdpi/ic_refresh.png Binary files differnew file mode 100644 index 0000000..58b116e --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_refresh.png diff --git a/app/src/main/res/drawable-xhdpi/ic_sync.png b/app/src/main/res/drawable-xhdpi/ic_sync.png Binary files differnew file mode 100644 index 0000000..3b8bbbc --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_sync.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_download.png b/app/src/main/res/drawable-xxhdpi/ic_action_download.png Binary files differnew file mode 100644 index 0000000..80a2365 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_download.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_font_bold.png b/app/src/main/res/drawable-xxhdpi/ic_action_font_bold.png Binary files differnew file mode 100644 index 0000000..c5428d6 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_font_bold.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_font_italic.png b/app/src/main/res/drawable-xxhdpi/ic_action_font_italic.png Binary files differnew file mode 100644 index 0000000..8c04ef7 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_font_italic.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_edit.png b/app/src/main/res/drawable-xxhdpi/ic_edit.png Binary files differnew file mode 100644 index 0000000..e36a9c2 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_edit.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_refresh.png b/app/src/main/res/drawable-xxhdpi/ic_refresh.png Binary files differnew file mode 100644 index 0000000..98cdb9c --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_refresh.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_sync.png b/app/src/main/res/drawable-xxhdpi/ic_sync.png Binary files differnew file mode 100644 index 0000000..08f7a61 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_sync.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_download.png b/app/src/main/res/drawable-xxxhdpi/ic_action_download.png Binary files differnew file mode 100644 index 0000000..a017260 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_download.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_font_bold.png b/app/src/main/res/drawable-xxxhdpi/ic_action_font_bold.png Binary files differnew file mode 100644 index 0000000..c0da59e --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_font_bold.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_font_italic.png b/app/src/main/res/drawable-xxxhdpi/ic_action_font_italic.png Binary files differnew file mode 100644 index 0000000..e756a29 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_font_italic.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_edit.png b/app/src/main/res/drawable-xxxhdpi/ic_edit.png Binary files differnew file mode 100644 index 0000000..c7fa470 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_edit.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_refresh.png b/app/src/main/res/drawable-xxxhdpi/ic_refresh.png Binary files differnew file mode 100644 index 0000000..02e21a8 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_refresh.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_sync.png b/app/src/main/res/drawable-xxxhdpi/ic_sync.png Binary files differnew file mode 100644 index 0000000..0bf53c6 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_sync.png diff --git a/app/src/main/res/drawable/Thumbs.db b/app/src/main/res/drawable/Thumbs.db Binary files differnew file mode 100644 index 0000000..07c6d5a --- /dev/null +++ b/app/src/main/res/drawable/Thumbs.db diff --git a/app/src/main/res/drawable/bai_banner.png b/app/src/main/res/drawable/bai_banner.png Binary files differnew file mode 100644 index 0000000..d919b2f --- /dev/null +++ b/app/src/main/res/drawable/bai_banner.png diff --git a/app/src/main/res/drawable/bai_logo.png b/app/src/main/res/drawable/bai_logo.png Binary files differnew file mode 100644 index 0000000..a1bf494 --- /dev/null +++ b/app/src/main/res/drawable/bai_logo.png diff --git a/app/src/main/res/drawable/bai_mona.png b/app/src/main/res/drawable/bai_mona.png Binary files differnew file mode 100644 index 0000000..b583466 --- /dev/null +++ b/app/src/main/res/drawable/bai_mona.png diff --git a/app/src/main/res/drawable/blank.png b/app/src/main/res/drawable/blank.png Binary files differnew file mode 100644 index 0000000..874fc75 --- /dev/null +++ b/app/src/main/res/drawable/blank.png diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000..73fe2d2 --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,8 @@ +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <gradient + android:angle="90" + android:endColor="@color/colorPrimaryDark" + android:startColor="@color/colorPrimary" + android:type="linear" /> +</shape>
\ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..a61d8a6 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/drawer_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true" + tools:openDrawer="start"> + + <include + layout="@layout/app_bar_main" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + <android.support.design.widget.NavigationView + android:id="@+id/nav_view" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="start" + android:fitsSystemWindows="true" + app:headerLayout="@layout/nav_header_main" + app:menu="@menu/activity_main_drawer" /> + +</android.support.v4.widget.DrawerLayout> diff --git a/app/src/main/res/layout/activity_response.xml b/app/src/main/res/layout/activity_response.xml new file mode 100644 index 0000000..19194d4 --- /dev/null +++ b/app/src/main/res/layout/activity_response.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + tools:context="org.bienvenidoainternet.baiparser.ResponseActivity" + android:textAlignment="textEnd"> + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/layoutForm"> + <EditText + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textPersonName" + android:ems="10" + android:id="@+id/txtPosterName" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:hint="@string/txt_postername" /> + + <EditText + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textEmailAddress" + android:ems="10" + android:id="@+id/txtEmail" + android:layout_below="@+id/txtPosterName" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:hint="@string/txt_email" /> + + <EditText + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textMultiLine" + android:ems="10" + android:id="@+id/txtResponse" + android:hint="@string/txt_response" + android:layout_below="@+id/buttonBold" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:clickable="false" + android:capitalize="sentences" /> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/btn_send" + android:id="@+id/btnSend" + android:layout_alignWithParentIfMissing="false" + android:layout_below="@+id/txtResponse" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" /> + + <Button + style="?android:attr/buttonStyleSmall" + android:layout_width="32dp" + android:layout_height="32dp" + android:id="@+id/buttonBold" + android:background="@drawable/ic_action_font_bold" + android:layout_below="@+id/txtFilePath" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> + + <Button + style="?android:attr/buttonStyleSmall" + android:layout_width="32dp" + android:layout_height="32dp" + android:background="@drawable/ic_action_font_italic" + android:id="@+id/buttonItalic" + android:layout_alignTop="@+id/buttonBold" + android:layout_toRightOf="@+id/buttonBold" + android:layout_toEndOf="@+id/buttonBold" /> + + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/txtFilePath" + android:layout_below="@+id/txtEmail" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:enabled="false" + android:hint="Archivo " + android:layout_toLeftOf="@+id/btnSelectFiles" + android:layout_toStartOf="@+id/btnSelectFiles" /> + + <Button + style="?android:attr/buttonStyleSmall" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="..." + android:id="@+id/btnSelectFiles" + android:layout_below="@+id/txtEmail" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" /> + + </RelativeLayout> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_below="@+id/layoutForm" + android:layout_centerHorizontal="true" + android:id="@+id/layoutPostProcess"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="Diviendiendo por 0 ..." + android:id="@+id/txtPostingState" + android:layout_gravity="center_horizontal" /> + + <ProgressBar + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/barPosting" + android:layout_below="@+id/relativeLayout" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_alignRight="@+id/relativeLayout" + android:layout_alignEnd="@+id/relativeLayout" + android:layout_marginTop="3dp" /> + </LinearLayout> + +</RelativeLayout> diff --git a/app/src/main/res/layout/activity_updater.xml b/app/src/main/res/layout/activity_updater.xml new file mode 100644 index 0000000..b287293 --- /dev/null +++ b/app/src/main/res/layout/activity_updater.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + tools:context="org.bienvenidoainternet.baiparser.UpdaterActivity"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="Versión actual:" + android:id="@+id/txtCurrentVersion" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="Última versión:" + android:id="@+id/txtLastVersion" + android:layout_below="@+id/txtCurrentVersion" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Descargar última versión" + android:id="@+id/btnDownloadLastVersion" + android:layout_alignParentBottom="true" + android:layout_centerHorizontal="true" /> + + <ProgressBar + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/barUpdateProgress" + android:layout_above="@+id/btnDownloadLastVersion" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="" + android:id="@+id/txtChangelog" + android:layout_below="@+id/txtLastVersion" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:layout_marginTop="5dp" + android:typeface="monospace" + android:layout_above="@+id/barUpdateProgress" + android:layout_marginBottom="5dp" /> +</RelativeLayout> diff --git a/app/src/main/res/layout/activity_viewer.xml b/app/src/main/res/layout/activity_viewer.xml new file mode 100644 index 0000000..b66e66b --- /dev/null +++ b/app/src/main/res/layout/activity_viewer.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="org.bienvenidoainternet.baiparser.ViewerActivity"> + + <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView + android:id="@+id/imageView" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + <pl.droidsonroids.gif.GifImageView + android:id="@+id/gifView" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + + <ProgressBar + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/downloadProgressBar" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" /> +</RelativeLayout> diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml new file mode 100644 index 0000000..1055aa2 --- /dev/null +++ b/app/src/main/res/layout/app_bar_main.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true" + tools:context="org.bienvenidoainternet.baiparser.MainActivity"> + + <android.support.design.widget.AppBarLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/AppTheme.AppBarOverlay"> + + <android.support.v7.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + android:background="?attr/colorPrimary" + app:popupTheme="@style/AppTheme.PopupOverlay" /> + + </android.support.design.widget.AppBarLayout> + + <include layout="@layout/content_main" /> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_margin="@dimen/fab_margin" + android:src="@drawable/ic_edit" + android:alpha="128" /> + +</android.support.design.widget.CoordinatorLayout> diff --git a/app/src/main/res/layout/boardthread_item.xml b/app/src/main/res/layout/boardthread_item.xml new file mode 100644 index 0000000..e969e5e --- /dev/null +++ b/app/src/main/res/layout/boardthread_item.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" android:layout_height="match_parent"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="thread_title" + android:id="@+id/threadlist_thread_title" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginTop="10dp" + android:layout_marginLeft="10dp" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="reply_count" + android:id="@+id/threadlist_replycount" + android:layout_below="@+id/threadlist_thread_title" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginLeft="10dp" + android:layout_marginBottom="10dp" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="last_reply" + android:id="@+id/threadlist_lastreply" + android:layout_alignTop="@+id/threadlist_replycount" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:layout_marginRight="10dp" /> +</RelativeLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..28cc377 --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + + app:layout_behavior="@string/appbar_scrolling_view_behavior" + tools:context="org.bienvenidoainternet.baiparser.MainActivity" + tools:showIn="@layout/app_bar_main"> + <android.support.v4.view.ViewPager + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + +</RelativeLayout> + + <!--android:paddingBottom="@dimen/activity_vertical_margin"--> + <!--android:paddingLeft="@dimen/activity_horizontal_margin"--> + <!--android:paddingRight="@dimen/activity_horizontal_margin"--> + <!--android:paddingTop="@dimen/activity_vertical_margin"-->
\ No newline at end of file diff --git a/app/src/main/res/layout/fragment_fragment_recent.xml b/app/src/main/res/layout/fragment_fragment_recent.xml new file mode 100644 index 0000000..fa6e67c --- /dev/null +++ b/app/src/main/res/layout/fragment_fragment_recent.xml @@ -0,0 +1,17 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="layout.fragmentRecent"> + + <!-- TODO: Update blank fragment layout --> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="New Text" + android:id="@+id/textView" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> +</RelativeLayout> diff --git a/app/src/main/res/layout/fragment_fragment_thread_list.xml b/app/src/main/res/layout/fragment_fragment_thread_list.xml new file mode 100644 index 0000000..af88df4 --- /dev/null +++ b/app/src/main/res/layout/fragment_fragment_thread_list.xml @@ -0,0 +1,61 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/layoutThreadProcess" + android:visibility="gone"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="Error: Unknow" + android:id="@+id/txtThreadError" + android:layout_margin="3dp" + android:textColor="#ff0000" + android:visibility="visible" + android:textAlignment="center" /> + + </LinearLayout> + + <RelativeLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_below="@+id/layoutThreadProcess" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true"> + + <ProgressBar + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/progressBar" + android:layout_gravity="center_horizontal" + android:layout_weight="1" + android:indeterminate="true" + android:indeterminateBehavior="repeat" + android:indeterminateOnly="true" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" + android:layout_marginTop="20dp" /> + + <ListView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/lvThreadList" + android:divider="#FF00FF" + android:layout_weight="1" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> + </RelativeLayout> + +</RelativeLayout> diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml new file mode 100644 index 0000000..71f218d --- /dev/null +++ b/app/src/main/res/layout/nav_header_main.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="@dimen/nav_header_height" + android:background="@drawable/side_nav_bar" + android:theme="@style/ThemeOverlay.AppCompat.Dark"> + <!--android:gravity="bottom"--> + + <!--<ImageView--> + <!--android:layout_width="64dp"--> + <!--android:layout_height="64dp"--> + <!--android:paddingTop="@dimen/nav_header_vertical_spacing"--> + <!--android:src="@drawable/bai"--> + <!--android:id="@+id/imageView"--> + <!--android:layout_alignParentBottom="false"--> + <!--android:layout_centerHorizontal="true"--> + <!--android:layout_alignParentTop="true" />--> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/bai_banner" + android:background="#00000000" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:adjustViewBounds="true" /> +</RelativeLayout> diff --git a/app/src/main/res/layout/recentpost_item.xml b/app/src/main/res/layout/recentpost_item.xml new file mode 100644 index 0000000..852b317 --- /dev/null +++ b/app/src/main/res/layout/recentpost_item.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="rp_message" + android:id="@+id/rp_message" + android:layout_below="@+id/rp_title" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginLeft="5dp" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="rp_title" + android:id="@+id/rp_title" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_marginLeft="5dp" + android:layout_marginTop="5dp" + android:textSize="12sp" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="rp_timediff" + android:id="@+id/rp_timediff" + android:textSize="12sp" + android:layout_below="@+id/rp_message" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:layout_marginRight="5dp" + android:layout_marginBottom="3dp" /> +</RelativeLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/thread_item.xml b/app/src/main/res/layout/thread_item.xml new file mode 100644 index 0000000..a4396b4 --- /dev/null +++ b/app/src/main/res/layout/thread_item.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:layout_width="5dp" + android:layout_height="match_parent" + android:id="@+id/ivMargin" + android:scaleType="fitXY" + android:src="@color/defaultMarginColor" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" /> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:layout_toRightOf="@+id/ivMargin" + android:layout_toEndOf="@+id/ivMargin"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="397 Nombre: VIPPEADOR : 11/03/16(vie)20:18:31" + android:id="@+id/lv_txtPoster" + android:textSize="10sp" + android:layout_below="@+id/lv_txtTitle" + android:layout_toRightOf="@+id/ivThumb" + android:layout_toEndOf="@+id/ivThumb" + android:layout_marginLeft="3dp" + android:layout_marginTop="3dp" + android:layout_marginRight="3dp" /> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="Cuerpo del post" + android:id="@+id/lv_txtBody" + android:layout_below="@+id/lv_txtFileInfo" + android:layout_toRightOf="@+id/ivThumb" + android:layout_toEndOf="@+id/ivThumb" + android:layout_marginLeft="3dp" + android:layout_marginTop="3dp" + android:layout_marginRight="3dp" /> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="Titulo" + android:id="@+id/lv_txtTitle" + android:textStyle="bold" + android:textSize="14sp" + android:layout_alignParentTop="true" + android:layout_toRightOf="@+id/ivThumb" + android:layout_toEndOf="@+id/ivThumb" + android:layout_marginLeft="3dp" + android:layout_marginTop="3dp" + android:layout_marginRight="3dp" />/> + <ImageView + android:layout_width="70dp" + android:layout_height="70dp" + android:id="@+id/ivThumb" + android:src="@drawable/blank" + android:layout_alignParentTop="true" + android:scaleType="centerCrop" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="123 Respuestas, 123 Imágenes" + android:id="@+id/lv_txtReplyCounter" + android:layout_below="@+id/lv_txtBody" + android:layout_toRightOf="@+id/ivThumb" + android:layout_toEndOf="@+id/ivThumb" + android:layout_marginLeft="3dp" + android:layout_marginTop="3dp" + android:layout_marginBottom="3dp" + android:layout_marginRight="3dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="New Text" + android:id="@+id/lv_txtFileInfo" + android:textSize="10sp" + android:layout_below="@+id/lv_txtPoster" + android:layout_toRightOf="@+id/ivThumb" + android:layout_toEndOf="@+id/ivThumb" + android:layout_marginLeft="3dp" + android:layout_marginRight="3dp" /> + </RelativeLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml new file mode 100644 index 0000000..5561ddb --- /dev/null +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/nav_recent_post" + android:icon="@drawable/ic_sync" + android:title="Post recientes" /> +</menu> diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml new file mode 100644 index 0000000..280b121 --- /dev/null +++ b/app/src/main/res/menu/main.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/action_to_top" + android:title="Ir al principio" + android:orderInCategory="100" + app:showAsAction="never"/> + <item + android:id="@+id/action_to_bot" + android:title="Ir al final" + android:orderInCategory="100" + app:showAsAction="never"/> + <item + android:id="@+id/action_refresh" + android:orderInCategory="300" + android:icon="@drawable/ic_refresh" + android:title="@string/action_settings" + app:showAsAction="always" /> + <item + android:id="@+id/action_settings" + android:orderInCategory="400" + android:title="@string/action_settings" + app:showAsAction="never" /> + <item + android:title="Buscar actualizaciones" + android:id="@+id/action_update" + android:orderInCategory="500" + app:showAsAction="never"/> + <item + android:id="@+id/action_exit" + android:orderInCategory="600" + android:title="@string/action_exit" + app:showAsAction="never" /> +</menu> diff --git a/app/src/main/res/menu/menu_reply.xml b/app/src/main/res/menu/menu_reply.xml new file mode 100644 index 0000000..d0dcaaa --- /dev/null +++ b/app/src/main/res/menu/menu_reply.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_reply" + android:title="@string/menu_reply"/> + <item android:id="@+id/menu_copy" + android:title="@string/menu_copy"/> + <item android:id="@+id/menu_savereply" + android:title="@string/menu_savereply"/> + <item android:id="@+id/menu_delpost" + android:title="@string/menu_delpost"/> + <item android:id="@+id/menu_delimage" + android:title="@string/menu_delimage"/> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/menu/menu_viewer.xml b/app/src/main/res/menu/menu_viewer.xml new file mode 100644 index 0000000..31069eb --- /dev/null +++ b/app/src/main/res/menu/menu_viewer.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:tools="http://schemas.android.com/tools" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item android:title="Guardar" + android:id="@+id/menu_save_img" + android:orderInCategory="100" + android:icon="@drawable/ic_action_download" + app:showAsAction="always"/> +</menu>
\ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..0a0d553 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..6a879da --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..da08cb9 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..b55a4af --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..fa6a765 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000..251fb9f --- /dev/null +++ b/app/src/main/res/values-v21/styles.xml @@ -0,0 +1,9 @@ +<resources>> + + <style name="AppTheme.NoActionBar"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + <item name="android:windowDrawsSystemBarBackgrounds">true</item> + <item name="android:statusBarColor">@android:color/transparent</item> + </style> +</resources> diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ +<resources> + <!-- Example customization of dimensions originally defined in res/values/dimens.xml + (such as screen margins) for screens with more than 820dp of available width. This + would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> + <dimen name="activity_horizontal_margin">64dp</dimen> +</resources> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..ad73763 --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <attr name="sageColor" format="reference"/> + <attr name="marginColor" format="reference"/> + <attr name="nameColor" format="reference"/> + <attr name="tripcodeColor" format="reference"/> + <attr name="isDarkTheme" format="boolean"/> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..5806545 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="colorPrimary">#3B6B94</color> + <color name="colorPrimaryDark">#1B3345</color> + <color name="colorAccent">#3B6B94</color> + <color name="transparentBackground">#CC000000</color> + + <color name="defaultSageColor">#0000FF</color> + <color name="defaultNameColor">#008000</color> + <color name="defaultMarginColor">#CCCCCC</color> + <color name="defaultTripcodeColor">#FF0000</color> + + <color name="nightBackground">#2F3D48</color> <!-- 1 --> + <color name="nightMarginColor">#58636c</color> <!-- 3 58636c--> + <color name="nightTextColor">#979ea3</color> <!-- 6 --> + <color name="nightLinkColor">#c0c4c8</color> <!-- 8 --> + <color name="nightNameColor">#2e5f96</color> + <color name="nightSageColor">#5f962e</color> + <color name="nightTripcodeColor">#962e5f</color> + + <color name="headlineBackground">#DDDDDD</color> <!-- 1 --> + <color name="headlineMarginColor">#EEEEEE</color> <!-- 3 58636c--> + <color name="headlineTextColor">#333333</color> <!-- 6 --> + <color name="headlineLinkColor">#FF6600</color> <!-- 8 --> + <color name="headlineNameColor">#004A99</color> + <color name="headlineSageColor">#FF6600</color> + <color name="headlineTripcodeColor">#d279ef</color> + + <color name="blackBackground">#282A2E</color> <!-- 1 --> + <color name="blackMarginColor">#1D1F21</color> <!-- 3 58636c--> + <color name="blackTextColor">#c5c8c6</color> <!-- 6 --> + <color name="blackLinkColor">#81a2be</color> <!-- 8 --> + <color name="blackNameColor">#c5c8c6</color> + <color name="blackSageColor">#81a2be</color> + <color name="blackTripcodeColor">#b294bb</color> +</resources> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..c2effc5 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,9 @@ +<resources> + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="nav_header_vertical_spacing">16dp</dimen> + <dimen name="nav_header_height">160dp</dimen> + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="activity_horizontal_margin">16dp</dimen> + <dimen name="activity_vertical_margin">16dp</dimen> + <dimen name="fab_margin">16dp</dimen> +</resources> diff --git a/app/src/main/res/values/drawables.xml b/app/src/main/res/values/drawables.xml new file mode 100644 index 0000000..52c6a6c --- /dev/null +++ b/app/src/main/res/values/drawables.xml @@ -0,0 +1,8 @@ +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item> + <item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item> + <item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item> + <item name="ic_menu_manage" type="drawable">@android:drawable/ic_menu_manage</item> + <item name="ic_menu_share" type="drawable">@android:drawable/ic_menu_share</item> + <item name="ic_menu_send" type="drawable">@android:drawable/ic_menu_send</item> +</resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..7fa3e34 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,76 @@ +<resources> + <string name="app_name">Bienvenido a Internet</string> + + <string name="navigation_drawer_open">Open navigation drawer</string> + <string name="navigation_drawer_close">Close navigation drawer</string> + + <string name="action_settings">Opciones</string> + <string name="action_exit">Salir</string> + <string name="action_threadlist">Lista de Hilos</string> + + <string name="txt_postername">Nombre</string> + <string name="txt_email">E-mail</string> + <string name="txt_response">Respuesta</string> + <string name="btn_send">Responder</string> + + <string name="menu_reply">Citar</string> + <string name="menu_copy">Copiar</string> + <string name="menu_savereply">Guardar</string> + <string name="menu_delpost">Eliminar respuesta</string> + <string name="menu_delimage">Eliminar imagen</string> + + + <string name="todo_pasando">Todo pasando en B.a.I</string> + + <string-array name="pref_themes"> + <item>psud0ch</item> + <item>Night</item> + <item>Photon</item> + <item>Tomorrow</item> + </string-array> + <string-array name="pref_themes_values"> + <item>1</item> + <item>2</item> + <item>3</item> + <item>4</item> + </string-array> + <string-array name="pref_repliescount"> + <item>Todas las respuestas</item> + <item>500 ultimas respuestas</item> + <item>250 ultimas respuestas</item> + <item>100 ultimas respuestas</item> + <item>50 ultimas respuestas</item> + </string-array> + <string-array name="pref_repliescount_values"> + <item>1000</item> + <item>500</item> + <item>250</item> + <item>100</item> + <item>50</item> + </string-array> + <string-array name="pref_catalog_replies"> + <item>Mostrar solo el post original</item> + <item>5 respuestas</item> + <item>10 respuestas</item> + </string-array> + <string-array name="pref_catalog_replies_values"> + <item>0</item> + <item>5</item> + <item>10</item> + </string-array> + <string-array name="pref_lastreplies_desc"> + <item>50 items</item> + <item>30 items</item> + <item>10 items</item> + <item>5 items</item> + </string-array> + <string-array name="pref_lastreplies_values"> + <item>50</item> + <item>30</item> + <item>10</item> + <item>5</item> + </string-array> + + <string name="title_activity_settings">Opciones</string> + +</resources> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5cadb6e --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,88 @@ +<resources> + <style name="TransparentCompat" parent="@style/Theme.AppCompat.Light.DarkActionBar"> + <item name="android:windowNoTitle">true</item> + <item name="android:windowBackground">@color/transparentBackground</item> + <item name="android:colorBackgroundCacheHint">@null</item> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowAnimationStyle">@android:style/Animation</item> + </style> + <!-- Base application theme. --> + <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> + <item name="colorPrimary">@color/colorPrimary</item> + <item name="colorPrimaryDark">@color/colorPrimaryDark</item> + <item name="colorAccent">@color/colorAccent</item> + <item name="android:divider">@color/defaultMarginColor</item> + <item name="sageColor">@color/defaultSageColor</item> + <item name="nameColor">@color/defaultNameColor</item> + <item name="marginColor">@color/defaultMarginColor</item> + <item name="tripcodeColor">@color/defaultTripcodeColor</item> + <item name="isDarkTheme">false</item> + </style> + + <style name="AppTheme.Dark" parent="AppTheme.NoActionBar"> + <item name="android:textColor">@color/nightTextColor</item> + <item name="android:background">@color/nightBackground</item> + <item name="android:divider">@color/nightMarginColor</item> + <item name="android:textColorLink">@color/nightLinkColor</item> + <item name="sageColor">@color/nightSageColor</item> + <item name="nameColor">@color/nightNameColor</item> + <item name="marginColor">@color/nightMarginColor</item> + <item name="tripcodeColor">@color/nightTripcodeColor</item> + <item name="isDarkTheme">true</item> + </style> + + <style name="AppTheme.HeadLine.Activity" parent="AppTheme.NoActionBar"> + <item name="colorPrimary">@color/headlineTextColor</item> + <item name="colorPrimaryDark">@color/blackBackground</item> + <item name="colorAccent">@color/headlineLinkColor</item> + <item name="isDarkTheme">true</item> + </style> + + <style name="AppTheme.HeadLine" parent="AppTheme.NoActionBar"> + <item name="android:textColor">@color/headlineTextColor</item> + <item name="android:background">@color/headlineBackground</item> + <item name="android:divider">@color/headlineMarginColor</item> + <item name="android:textColorLink">@color/headlineLinkColor</item> + <item name="sageColor">@color/headlineSageColor</item> + <item name="nameColor">@color/headlineNameColor</item> + <item name="marginColor">@color/headlineMarginColor</item> + <item name="tripcodeColor">@color/headlineTripcodeColor</item> + <item name="colorPrimary">@color/headlineTextColor</item> + <item name="colorPrimaryDark">@color/headlineLinkColor</item> + <item name="colorAccent">@color/headlineLinkColor</item> + <item name="isDarkTheme">false</item> + </style> + + <style name="AppTheme.Black.Activity" parent="AppTheme.NoActionBar"> + <item name="colorPrimary">@color/blackBackground</item> + <item name="colorPrimaryDark">@color/blackMarginColor</item> + <item name="colorAccent">@color/blackMarginColor</item> + <item name="isDarkTheme">true</item> + </style> + + <style name="AppTheme.Black" parent="AppTheme.NoActionBar"> + <item name="android:textColor">@color/blackTextColor</item> + <item name="android:background">@color/blackBackground</item> + <item name="android:divider">@color/blackMarginColor</item> + <item name="android:textColorLink">@color/blackLinkColor</item> + <item name="sageColor">@color/blackSageColor</item> + <item name="nameColor">@color/blackNameColor</item> + <item name="marginColor">@color/blackMarginColor</item> + <item name="tripcodeColor">@color/blackTripcodeColor</item> + <item name="colorPrimary">@color/blackBackground</item> + <item name="colorPrimaryDark">@color/blackMarginColor</item> + <item name="colorAccent">@color/blackSageColor</item> + <item name="isDarkTheme">true</item> + </style> + + <style name="AppTheme.NoActionBar"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + + <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> + + <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> + + +</resources> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml new file mode 100644 index 0000000..7f6d5b9 --- /dev/null +++ b/app/src/main/res/xml/preferences.xml @@ -0,0 +1,61 @@ +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <PreferenceCategory + android:title="Apariencia"> + <ListPreference + android:title="Tema" + android:summary="Requiere un reinicio de la aplicación" + android:key="pref_theme" + android:defaultValue="1" + android:entries="@array/pref_themes" + android:entryValues="@array/pref_themes_values" /> + <SwitchPreference + android:title="Usar fuente Mona" + android:key="setting_monafont" + android:summary="No es compatible con todas las versiones de Android" + android:defaultValue="true" /> + <SwitchPreference + android:title="Usar Mona.tff solo en BSS" + android:key="setting_mona_bbsonly" + android:defaultValue="true"/> + </PreferenceCategory> + <PreferenceCategory + android:title="Comportamiento"> + <SwitchPreference + android:title="Descargar imágenes solo con Wi-Fi" + android:key="setting_downloadOnlyWithWifi" + android:defaultValue="true" /> + <SwitchPreference + android:title="Ir al final al abrir un hilo" + android:key="setting_scrollatnewthread" + android:defaultValue="false" /> + <ListPreference + android:title="Respuestas por tema" + android:key="pref_lastreplies" + android:summary="Cantidad de respuestas que serán cargadas en la vista de tema" + android:defaultValue="1000" + android:entries="@array/pref_repliescount" + android:entryValues="@array/pref_repliescount_values"/> + <ListPreference + android:title="Respuestas en catálogo" + android:key="pref_repliesperthread" + android:summary="Cantidad de respuestas que se muestran en el catálogo" + android:defaultValue="5" + android:entries="@array/pref_catalog_replies" + android:entryValues="@array/pref_catalog_replies_values"/> + <ListPreference + android:title="Post recientes" + android:summary="Cantidad de post a cargar" + android:key="pref_lastreplies_limit" + android:entries="@array/pref_lastreplies_desc" + android:entryValues="@array/pref_lastreplies_values" + android:defaultValue="30"/> + </PreferenceCategory> + <PreferenceCategory + android:title="Formulario de respuesta"> + <EditTextPreference + android:title="Contraseña" + android:summary="Usada para la eliminación de tus posts" + android:key="pref_password" /> + + </PreferenceCategory> +</PreferenceScreen>
\ No newline at end of file diff --git a/app/src/test/java/org/bienvenidoainternet/baiparser/ExampleUnitTest.java b/app/src/test/java/org/bienvenidoainternet/baiparser/ExampleUnitTest.java new file mode 100644 index 0000000..7c67f02 --- /dev/null +++ b/app/src/test/java/org/bienvenidoainternet/baiparser/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package org.bienvenidoainternet.baiparser; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +}
\ No newline at end of file |