mirror of https://github.com/kurisufriend/Clover
reads the html because there is no api endpoint for it. adds a new `archive` boolean to the Board model.refactor-toolbar
parent
162a0b2f68
commit
9c4f4334f9
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||||
|
* Copyright (C) 2014 Floens |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
package org.floens.chan.core.model; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class Archive { |
||||||
|
public final List<ArchiveItem> items; |
||||||
|
|
||||||
|
public static Archive fromItems(List<ArchiveItem> items) { |
||||||
|
return new Archive(items); |
||||||
|
} |
||||||
|
|
||||||
|
private Archive(List<ArchiveItem> items) { |
||||||
|
this.items = items; |
||||||
|
} |
||||||
|
|
||||||
|
public static class ArchiveItem { |
||||||
|
public final String description; |
||||||
|
|
||||||
|
public final int id; |
||||||
|
|
||||||
|
public static ArchiveItem fromDescriptionId(String description, int id) { |
||||||
|
return new ArchiveItem(description, id); |
||||||
|
} |
||||||
|
|
||||||
|
private ArchiveItem(String description, int id) { |
||||||
|
this.description = description; |
||||||
|
this.id = id; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
/* |
||||||
|
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||||
|
* Copyright (C) 2014 Floens |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
package org.floens.chan.core.net; |
||||||
|
|
||||||
|
import com.android.volley.NetworkResponse; |
||||||
|
import com.android.volley.Request; |
||||||
|
import com.android.volley.Response; |
||||||
|
import com.android.volley.Response.Listener; |
||||||
|
import com.android.volley.VolleyError; |
||||||
|
import com.android.volley.toolbox.HttpHeaderParser; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public abstract class HtmlReaderRequest<T> extends Request<T> { |
||||||
|
protected final Listener<T> listener; |
||||||
|
|
||||||
|
public HtmlReaderRequest(String url, Listener<T> listener, Response.ErrorListener errorListener) { |
||||||
|
super(Request.Method.GET, url, errorListener); |
||||||
|
|
||||||
|
this.listener = listener; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void deliverResponse(T response) { |
||||||
|
listener.onResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Response<T> parseNetworkResponse(NetworkResponse response) { |
||||||
|
try { |
||||||
|
Document document = Jsoup.parse(new ByteArrayInputStream(response.data), |
||||||
|
HttpHeaderParser.parseCharset(response.headers), getUrl()); |
||||||
|
|
||||||
|
T result = readDocument(document); |
||||||
|
|
||||||
|
return Response.success(result, HttpHeaderParser.parseCacheHeaders(response)); |
||||||
|
} catch (IOException e) { |
||||||
|
return Response.error(new VolleyError(e)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract T readDocument(Document document) throws IOException; |
||||||
|
} |
@ -0,0 +1,138 @@ |
|||||||
|
/* |
||||||
|
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||||
|
* Copyright (C) 2014 Floens |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
package org.floens.chan.core.presenter; |
||||||
|
|
||||||
|
import org.floens.chan.core.database.DatabaseManager; |
||||||
|
import org.floens.chan.core.model.Archive; |
||||||
|
import org.floens.chan.core.model.orm.Board; |
||||||
|
import org.floens.chan.core.model.orm.Loadable; |
||||||
|
import org.floens.chan.core.site.SiteActions; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Locale; |
||||||
|
|
||||||
|
import javax.inject.Inject; |
||||||
|
|
||||||
|
import static android.text.TextUtils.isEmpty; |
||||||
|
|
||||||
|
public class ArchivePresenter implements SiteActions.ArchiveListener { |
||||||
|
private DatabaseManager databaseManager; |
||||||
|
|
||||||
|
private Callback callback; |
||||||
|
private Board board; |
||||||
|
|
||||||
|
private boolean inRequest = false; |
||||||
|
|
||||||
|
private String filter; |
||||||
|
private List<Archive.ArchiveItem> items = new ArrayList<>(); |
||||||
|
private List<Archive.ArchiveItem> filteredItems = new ArrayList<>(); |
||||||
|
|
||||||
|
@Inject |
||||||
|
public ArchivePresenter(DatabaseManager databaseManager) { |
||||||
|
this.databaseManager = databaseManager; |
||||||
|
} |
||||||
|
|
||||||
|
public void create(Callback callback, Board board) { |
||||||
|
this.callback = callback; |
||||||
|
this.board = board; |
||||||
|
|
||||||
|
loadArchive(); |
||||||
|
} |
||||||
|
|
||||||
|
public void onRefresh() { |
||||||
|
if (!inRequest) { |
||||||
|
loadArchive(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void loadArchive() { |
||||||
|
inRequest = true; |
||||||
|
callback.showError(false); |
||||||
|
board.site.actions().archive(board, this); |
||||||
|
} |
||||||
|
|
||||||
|
public void onSearchEntered(String query) { |
||||||
|
filterArchive(query); |
||||||
|
} |
||||||
|
|
||||||
|
public void onSearchVisibility(boolean visible) { |
||||||
|
if (!visible) { |
||||||
|
filterArchive(null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void onItemClicked(Archive.ArchiveItem item) { |
||||||
|
Loadable loadable = databaseManager.getDatabaseLoadableManager() |
||||||
|
.get(Loadable.forThread(board.site, board, item.id)); |
||||||
|
|
||||||
|
callback.openThread(loadable); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onArchive(Archive archive) { |
||||||
|
inRequest = false; |
||||||
|
callback.hideRefreshing(); |
||||||
|
callback.showList(); |
||||||
|
items = archive.items; |
||||||
|
updateWithFilter(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onArchiveError() { |
||||||
|
inRequest = false; |
||||||
|
callback.hideRefreshing(); |
||||||
|
callback.showError(true); |
||||||
|
} |
||||||
|
|
||||||
|
private void filterArchive(String query) { |
||||||
|
filter = query; |
||||||
|
updateWithFilter(); |
||||||
|
} |
||||||
|
|
||||||
|
private void updateWithFilter() { |
||||||
|
filteredItems.clear(); |
||||||
|
if (isEmpty(filter)) { |
||||||
|
filteredItems.addAll(items); |
||||||
|
} else { |
||||||
|
for (Archive.ArchiveItem item : items) { |
||||||
|
if (filterApplies(item, filter)) { |
||||||
|
filteredItems.add(item); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
callback.setArchiveItems(filteredItems); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean filterApplies(Archive.ArchiveItem item, String filter) { |
||||||
|
return item.description.toLowerCase(Locale.ENGLISH).contains(filter.toLowerCase()); |
||||||
|
} |
||||||
|
|
||||||
|
public interface Callback { |
||||||
|
void setArchiveItems(List<Archive.ArchiveItem> items); |
||||||
|
|
||||||
|
void hideRefreshing(); |
||||||
|
|
||||||
|
void showList(); |
||||||
|
|
||||||
|
void showError(boolean show); |
||||||
|
|
||||||
|
void openThread(Loadable loadable); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
/* |
||||||
|
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||||
|
* Copyright (C) 2014 Floens |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
package org.floens.chan.core.site.sites.chan4; |
||||||
|
|
||||||
|
import com.android.volley.Response; |
||||||
|
|
||||||
|
import org.floens.chan.core.model.Archive; |
||||||
|
import org.floens.chan.core.model.orm.Board; |
||||||
|
import org.floens.chan.core.net.HtmlReaderRequest; |
||||||
|
import org.floens.chan.core.site.Site; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class Chan4ArchiveRequest extends HtmlReaderRequest<Archive> { |
||||||
|
public Chan4ArchiveRequest(Site site, Board board, |
||||||
|
Response.Listener<Archive> listener, |
||||||
|
Response.ErrorListener errorListener) { |
||||||
|
super(site.endpoints().archive(board).toString(), listener, errorListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Archive readDocument(Document document) throws IOException { |
||||||
|
List<Archive.ArchiveItem> items = new ArrayList<>(); |
||||||
|
|
||||||
|
Element table = document.getElementById("arc-list"); |
||||||
|
Element tableBody = table.getElementsByTag("tbody").first(); |
||||||
|
Elements trs = tableBody.getElementsByTag("tr"); |
||||||
|
for (Element tr : trs) { |
||||||
|
Elements dataElements = tr.getElementsByTag("td"); |
||||||
|
String description = dataElements.get(1).text(); |
||||||
|
int id = Integer.parseInt(dataElements.get(0).text()); |
||||||
|
items.add(Archive.ArchiveItem.fromDescriptionId(description, id)); |
||||||
|
} |
||||||
|
|
||||||
|
return Archive.fromItems(items); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,211 @@ |
|||||||
|
/* |
||||||
|
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||||
|
* Copyright (C) 2014 Floens |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
package org.floens.chan.ui.controller; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.support.v4.widget.SwipeRefreshLayout; |
||||||
|
import android.support.v7.widget.LinearLayoutManager; |
||||||
|
import android.support.v7.widget.RecyclerView; |
||||||
|
import android.view.LayoutInflater; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
import org.floens.chan.R; |
||||||
|
import org.floens.chan.controller.Controller; |
||||||
|
import org.floens.chan.core.model.Archive; |
||||||
|
import org.floens.chan.core.model.orm.Board; |
||||||
|
import org.floens.chan.core.model.orm.Loadable; |
||||||
|
import org.floens.chan.core.presenter.ArchivePresenter; |
||||||
|
import org.floens.chan.ui.helper.BoardHelper; |
||||||
|
import org.floens.chan.ui.toolbar.ToolbarMenu; |
||||||
|
import org.floens.chan.ui.toolbar.ToolbarMenuItem; |
||||||
|
import org.floens.chan.ui.view.CrossfadeView; |
||||||
|
import org.floens.chan.ui.view.DividerItemDecoration; |
||||||
|
import org.floens.chan.ui.view.FastScrollerHelper; |
||||||
|
import org.floens.chan.ui.view.FloatingMenuItem; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import javax.inject.Inject; |
||||||
|
|
||||||
|
import static org.floens.chan.Chan.inject; |
||||||
|
|
||||||
|
public class ArchiveController extends Controller implements ArchivePresenter.Callback, |
||||||
|
ToolbarMenuItem.ToolbarMenuItemCallback, |
||||||
|
ToolbarNavigationController.ToolbarSearchCallback, |
||||||
|
SwipeRefreshLayout.OnRefreshListener { |
||||||
|
private static final int SEARCH_ID = 1; |
||||||
|
|
||||||
|
private CrossfadeView crossfadeView; |
||||||
|
private SwipeRefreshLayout swipeRefreshLayout; |
||||||
|
private RecyclerView archiveRecyclerview; |
||||||
|
private View progress; |
||||||
|
private View errorView; |
||||||
|
|
||||||
|
@Inject |
||||||
|
private ArchivePresenter presenter; |
||||||
|
|
||||||
|
private ArchiveAdapter adapter; |
||||||
|
|
||||||
|
private Board board; |
||||||
|
|
||||||
|
public ArchiveController(Context context) { |
||||||
|
super(context); |
||||||
|
} |
||||||
|
|
||||||
|
public void setBoard(Board board) { |
||||||
|
this.board = board; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate() { |
||||||
|
super.onCreate(); |
||||||
|
inject(this); |
||||||
|
|
||||||
|
// Inflate
|
||||||
|
view = inflateRes(R.layout.controller_archive); |
||||||
|
|
||||||
|
// Navigation
|
||||||
|
navigation.title = context.getString(R.string.archive_title, BoardHelper.getName(board)); |
||||||
|
ToolbarMenu menu = new ToolbarMenu(context); |
||||||
|
navigation.menu = menu; |
||||||
|
menu.addItem(new ToolbarMenuItem(context, this, SEARCH_ID, R.drawable.ic_search_white_24dp)); |
||||||
|
|
||||||
|
// View binding
|
||||||
|
crossfadeView = view.findViewById(R.id.crossfade); |
||||||
|
swipeRefreshLayout = view.findViewById(R.id.swipe_refresh); |
||||||
|
archiveRecyclerview = view.findViewById(R.id.recycler_view); |
||||||
|
progress = view.findViewById(R.id.progress); |
||||||
|
errorView = view.findViewById(R.id.error_text); |
||||||
|
|
||||||
|
// Adapters
|
||||||
|
adapter = new ArchiveAdapter(); |
||||||
|
|
||||||
|
// View setup
|
||||||
|
archiveRecyclerview.setLayoutManager(new LinearLayoutManager(context)); |
||||||
|
archiveRecyclerview.setAdapter(adapter); |
||||||
|
archiveRecyclerview.addItemDecoration( |
||||||
|
new DividerItemDecoration(context, DividerItemDecoration.VERTICAL)); |
||||||
|
FastScrollerHelper.create(archiveRecyclerview); |
||||||
|
// archiveRecyclerview.setVerticalScrollBarEnabled(false);
|
||||||
|
crossfadeView.toggle(false, false); |
||||||
|
swipeRefreshLayout.setOnRefreshListener(this); |
||||||
|
|
||||||
|
// Presenter
|
||||||
|
presenter.create(this, board); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onMenuItemClicked(ToolbarMenuItem item) { |
||||||
|
((ToolbarNavigationController) navigationController).showSearch(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSubMenuItemClicked(ToolbarMenuItem parent, FloatingMenuItem item) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSearchEntered(String entered) { |
||||||
|
presenter.onSearchEntered(entered); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSearchVisibilityChanged(boolean visible) { |
||||||
|
presenter.onSearchVisibility(visible); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onRefresh() { |
||||||
|
presenter.onRefresh(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setArchiveItems(List<Archive.ArchiveItem> items) { |
||||||
|
adapter.setArchiveItems(items); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void hideRefreshing() { |
||||||
|
swipeRefreshLayout.setRefreshing(false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void showList() { |
||||||
|
crossfadeView.toggle(true, true); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void showError(boolean show) { |
||||||
|
progress.setVisibility(show ? View.GONE : View.VISIBLE); |
||||||
|
errorView.setVisibility(show ? View.VISIBLE : View.GONE); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void openThread(Loadable loadable) { |
||||||
|
ViewThreadController threadController = new ViewThreadController(context); |
||||||
|
threadController.setLoadable(loadable); |
||||||
|
navigationController.pushController(threadController); |
||||||
|
} |
||||||
|
|
||||||
|
private void onItemClicked(Archive.ArchiveItem item) { |
||||||
|
presenter.onItemClicked(item); |
||||||
|
} |
||||||
|
|
||||||
|
private class ArchiveAdapter extends RecyclerView.Adapter<ArchiveCell> { |
||||||
|
private List<Archive.ArchiveItem> archiveItems = new ArrayList<>(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getItemCount() { |
||||||
|
return archiveItems.size(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ArchiveCell onCreateViewHolder(ViewGroup parent, int viewType) { |
||||||
|
return new ArchiveCell(LayoutInflater.from(context) |
||||||
|
.inflate(R.layout.cell_archive, parent, false)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onBindViewHolder(ArchiveCell holder, int position) { |
||||||
|
Archive.ArchiveItem archiveItem = archiveItems.get(position); |
||||||
|
|
||||||
|
holder.item = archiveItem; |
||||||
|
holder.text.setText(archiveItem.description); |
||||||
|
} |
||||||
|
|
||||||
|
public void setArchiveItems(List<Archive.ArchiveItem> archiveItems) { |
||||||
|
this.archiveItems = archiveItems; |
||||||
|
notifyDataSetChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class ArchiveCell extends RecyclerView.ViewHolder { |
||||||
|
private TextView text; |
||||||
|
private Archive.ArchiveItem item; |
||||||
|
|
||||||
|
public ArchiveCell(View itemView) { |
||||||
|
super(itemView); |
||||||
|
|
||||||
|
itemView.setOnClickListener(v -> onItemClicked(item)); |
||||||
|
|
||||||
|
text = itemView.findViewById(R.id.text); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- |
||||||
|
Clover - 4chan browser https://github.com/Floens/Clover/ |
||||||
|
Copyright (C) 2014 Floens |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||||
|
--> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:background="?attr/selectableItemBackground" |
||||||
|
android:minHeight="48dp" |
||||||
|
android:orientation="horizontal"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/text" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:padding="8dp" |
||||||
|
android:textColor="?text_color_primary" |
||||||
|
android:textSize="14sp" /> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,63 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- |
||||||
|
Clover - 4chan browser https://github.com/Floens/Clover/ |
||||||
|
Copyright (C) 2014 Floens |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||||
|
--> |
||||||
|
<org.floens.chan.ui.view.CrossfadeView xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:id="@+id/crossfade" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:background="?backcolor"> |
||||||
|
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout |
||||||
|
android:id="@+id/swipe_refresh" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:visibility="gone"> |
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView |
||||||
|
android:id="@+id/recycler_view" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:clipToPadding="false" |
||||||
|
android:padding="8dp" /> |
||||||
|
|
||||||
|
</android.support.v4.widget.SwipeRefreshLayout> |
||||||
|
|
||||||
|
<FrameLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:animateLayoutChanges="true" |
||||||
|
android:padding="8dp" |
||||||
|
android:visibility="gone"> |
||||||
|
|
||||||
|
<ProgressBar |
||||||
|
android:id="@+id/progress" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/error_text" |
||||||
|
style="?android:attr/textAppearanceMedium" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:text="@string/archive_error" |
||||||
|
android:visibility="gone" /> |
||||||
|
|
||||||
|
</FrameLayout> |
||||||
|
|
||||||
|
</org.floens.chan.ui.view.CrossfadeView> |
Loading…
Reference in new issue