Converting adapters and retrofit services to kotlin.
This commit is contained in:
parent
97cee06ebe
commit
9b95404500
@ -4,6 +4,10 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- For firebase only -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<application
|
||||
android:name=".MyApp"
|
||||
android:allowBackup="true"
|
||||
|
@ -104,7 +104,7 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
if (title.isEmpty() || url.isEmpty() || mSpoutsValue == null || mSpoutsValue!!.isEmpty()) {
|
||||
Toast.makeText(this, R.string.form_not_complete, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
api.createSource(title, url, mSpoutsValue, mTags.text.toString(), "").enqueue(object : Callback<SuccessResponse> {
|
||||
api.createSource(title, url, mSpoutsValue!!, mTags.text.toString(), "").enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
if (response.body() != null && response.body().isSuccess) {
|
||||
finish()
|
||||
|
@ -55,7 +55,7 @@ class HomeActivity : AppCompatActivity() {
|
||||
private val REQUEST_INVITE_BYMAIL = 13232
|
||||
private var mRecyclerView: RecyclerView? = null
|
||||
private var api: SelfossApi? = null
|
||||
private var items: List<Item>? = null
|
||||
private var items: ArrayList<Item> = ArrayList()
|
||||
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null
|
||||
|
||||
private var clickBehavior = false
|
||||
@ -177,15 +177,15 @@ class HomeActivity : AppCompatActivity() {
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
|
||||
try {
|
||||
val i = items!![viewHolder.adapterPosition]
|
||||
val position = items!!.indexOf(i)
|
||||
val i = items[viewHolder.adapterPosition]
|
||||
val position = items.indexOf(i)
|
||||
|
||||
if (shouldBeCardView) {
|
||||
(mRecyclerView!!.adapter as ItemCardAdapter).removeItemAtIndex(position)
|
||||
} else {
|
||||
(mRecyclerView!!.adapter as ItemListAdapter).removeItemAtIndex(position)
|
||||
}
|
||||
tabNew!!.setBadgeCount(items!!.size - 1)
|
||||
tabNew!!.setBadgeCount(items.size - 1)
|
||||
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
FirebaseCrash.logcat(Log.ERROR, "SWIPE ERROR", "Swipe index out of bound")
|
||||
@ -248,7 +248,7 @@ class HomeActivity : AppCompatActivity() {
|
||||
api!!.unreadItems.enqueue(object : Callback<List<Item>> {
|
||||
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
|
||||
if (response.body() != null && response.body().isNotEmpty()) {
|
||||
items = response.body()
|
||||
items = response.body() as ArrayList<Item>
|
||||
} else {
|
||||
items = ArrayList()
|
||||
}
|
||||
@ -268,7 +268,7 @@ class HomeActivity : AppCompatActivity() {
|
||||
api!!.readItems.enqueue(object : Callback<List<Item>> {
|
||||
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
|
||||
if (response.body() != null && response.body().isNotEmpty()) {
|
||||
items = response.body()
|
||||
items = response.body() as ArrayList<Item>
|
||||
} else {
|
||||
items = ArrayList()
|
||||
}
|
||||
@ -288,7 +288,7 @@ class HomeActivity : AppCompatActivity() {
|
||||
api!!.starredItems.enqueue(object : Callback<List<Item>> {
|
||||
override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
|
||||
if (response.body() != null && response.body().isNotEmpty()) {
|
||||
items = response.body()
|
||||
items = response.body() as ArrayList<Item>
|
||||
} else {
|
||||
items = ArrayList()
|
||||
}
|
||||
@ -308,14 +308,14 @@ class HomeActivity : AppCompatActivity() {
|
||||
|
||||
val mAdapter: RecyclerView.Adapter<*>
|
||||
if (shouldBeCardView) {
|
||||
mAdapter = ItemCardAdapter(this, items, api, mCustomTabActivityHelper, internalBrowser, articleViewer, fullHeightCards)
|
||||
mAdapter = ItemCardAdapter(this, items, api!!, mCustomTabActivityHelper!!, internalBrowser, articleViewer, fullHeightCards)
|
||||
} else {
|
||||
mAdapter = ItemListAdapter(this, items, api, mCustomTabActivityHelper, clickBehavior, internalBrowser, articleViewer)
|
||||
mAdapter = ItemListAdapter(this, items, api!!, mCustomTabActivityHelper!!, clickBehavior, internalBrowser, articleViewer)
|
||||
}
|
||||
mRecyclerView!!.adapter = mAdapter
|
||||
mAdapter.notifyDataSetChanged()
|
||||
|
||||
if (items!!.isEmpty()) Toast.makeText(this@HomeActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
|
||||
if (items.isEmpty()) Toast.makeText(this@HomeActivity, R.string.nothing_here, Toast.LENGTH_SHORT).show()
|
||||
|
||||
reloadBadges()
|
||||
}
|
||||
@ -356,7 +356,7 @@ class HomeActivity : AppCompatActivity() {
|
||||
R.id.readAll -> {
|
||||
if (elementsShown == UNREAD_SHOWN) {
|
||||
mSwipeRefreshLayout!!.isRefreshing = false
|
||||
val ids = items!!.map { it.id }
|
||||
val ids = items.map { it.id }
|
||||
|
||||
api!!.readAll(ids).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
|
@ -23,6 +23,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.checkAndDisplayStoreApk
|
||||
import apps.amine.bou.readerforselfoss.utils.isUrlValid
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.mikepenz.aboutlibraries.Libs
|
||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
import retrofit2.Call
|
||||
@ -43,6 +44,8 @@ class LoginActivity : AppCompatActivity() {
|
||||
private var isWithLogin = false
|
||||
private var isWithHTTPLogin = false
|
||||
private var mLoginFormView: View? = null
|
||||
private var mFirebaseAnalytics: FirebaseAnalytics? = null
|
||||
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -60,6 +63,7 @@ class LoginActivity : AppCompatActivity() {
|
||||
isWithHTTPLogin = false
|
||||
inValidCount = 0
|
||||
|
||||
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this)
|
||||
mUrlView = findViewById(R.id.url) as EditText
|
||||
mLoginView = findViewById(R.id.login) as TextView
|
||||
mHTTPLoginView = findViewById(R.id.httpLogin) as TextView
|
||||
@ -200,7 +204,8 @@ class LoginActivity : AppCompatActivity() {
|
||||
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
if (response.body() != null && response.body().isSuccess) {
|
||||
goToMain()
|
||||
mFirebaseAnalytics!!.logEvent(FirebaseAnalytics.Event.LOGIN, Bundle())
|
||||
goToMain()
|
||||
} else {
|
||||
preferenceError()
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class SourcesActivity : AppCompatActivity() {
|
||||
val mRecyclerView = findViewById(R.id.activity_sources) as RecyclerView
|
||||
val mLayoutManager = LinearLayoutManager(this)
|
||||
val api = SelfossApi(this)
|
||||
var items: List<Sources> = ArrayList()
|
||||
var items: ArrayList<Sources> = ArrayList()
|
||||
|
||||
mFab.attachToRecyclerView(mRecyclerView)
|
||||
mRecyclerView.setHasFixedSize(true)
|
||||
@ -37,7 +37,7 @@ class SourcesActivity : AppCompatActivity() {
|
||||
api.sources.enqueue(object : Callback<List<Sources>> {
|
||||
override fun onResponse(call: Call<List<Sources>>, response: Response<List<Sources>>) {
|
||||
if (response.body() != null && response.body().isNotEmpty()) {
|
||||
items = response.body()
|
||||
items = response.body() as ArrayList<Sources>
|
||||
}
|
||||
val mAdapter = SourcesListAdapter(this@SourcesActivity, items, api)
|
||||
mRecyclerView.adapter = mAdapter
|
||||
|
@ -1,310 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters;
|
||||
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.support.constraint.ConstraintLayout;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Html;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.R;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse;
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper;
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.TextDrawable.IBuilder;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget;
|
||||
import com.like.LikeButton;
|
||||
import com.like.OnLikeListener;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
import static apps.amine.bou.readerforselfoss.utils.LinksUtilsKt.buildCustomTabsIntent;
|
||||
import static apps.amine.bou.readerforselfoss.utils.LinksUtilsKt.openItemUrl;
|
||||
|
||||
|
||||
public class ItemCardAdapter extends RecyclerView.Adapter<ItemCardAdapter.ViewHolder> {
|
||||
private final List<Item> items;
|
||||
private final SelfossApi api;
|
||||
private final CustomTabActivityHelper helper;
|
||||
private final Context c;
|
||||
private final boolean internalBrowser;
|
||||
private final boolean articleViewer;
|
||||
private final Activity app;
|
||||
private final ColorGenerator generator;
|
||||
private final boolean fullHeightCards;
|
||||
|
||||
public ItemCardAdapter(Activity a, List<Item> myObject, SelfossApi selfossApi,
|
||||
CustomTabActivityHelper mCustomTabActivityHelper, boolean internalBrowser,
|
||||
boolean articleViewer, boolean fullHeightCards) {
|
||||
app = a;
|
||||
items = myObject;
|
||||
api = selfossApi;
|
||||
helper = mCustomTabActivityHelper;
|
||||
c = app.getApplicationContext();
|
||||
this.internalBrowser = internalBrowser;
|
||||
this.articleViewer = articleViewer;
|
||||
generator = ColorGenerator.MATERIAL;
|
||||
this.fullHeightCards = fullHeightCards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
ConstraintLayout v = (ConstraintLayout) LayoutInflater.from(c).inflate(R.layout.card_item, parent, false);
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Item itm = items.get(position);
|
||||
|
||||
|
||||
holder.saveBtn.setLiked((itm.getStarred()));
|
||||
holder.title.setText(Html.fromHtml(itm.getTitle()));
|
||||
|
||||
String sourceAndDate = itm.getSourcetitle();
|
||||
long d;
|
||||
try {
|
||||
d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itm.getDatetime()).getTime();
|
||||
sourceAndDate += " " +
|
||||
DateUtils.getRelativeTimeSpanString(
|
||||
d,
|
||||
new Date().getTime(),
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
holder.sourceTitleAndDate.setText(sourceAndDate);
|
||||
|
||||
if (itm.getThumbnail(c).isEmpty()) {
|
||||
Glide.clear(holder.itemImage);
|
||||
holder.itemImage.setImageDrawable(null);
|
||||
} else {
|
||||
if (fullHeightCards) {
|
||||
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().fitCenter().into(holder.itemImage);
|
||||
} else {
|
||||
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().centerCrop().into(holder.itemImage);
|
||||
}
|
||||
}
|
||||
|
||||
final ViewHolder fHolder = holder;
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
int color = generator.getColor(itm.getSourcetitle());
|
||||
StringBuilder textDrawable = new StringBuilder();
|
||||
for(String s : itm.getSourcetitle().split(" "))
|
||||
{
|
||||
textDrawable.append(s.charAt(0));
|
||||
}
|
||||
|
||||
IBuilder builder = TextDrawable.builder().round();
|
||||
|
||||
TextDrawable drawable = builder.build(textDrawable.toString(), color);
|
||||
holder.sourceImage.setImageDrawable(drawable);
|
||||
} else {
|
||||
|
||||
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(new BitmapImageViewTarget(holder.sourceImage) {
|
||||
@Override
|
||||
protected void setResource(Bitmap resource) {
|
||||
RoundedBitmapDrawable circularBitmapDrawable =
|
||||
RoundedBitmapDrawableFactory.create(c.getResources(), resource);
|
||||
circularBitmapDrawable.setCircular(true);
|
||||
fHolder.sourceImage.setImageDrawable(circularBitmapDrawable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
holder.saveBtn.setLiked(itm.getStarred());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
private void doUnmark(final Item i, final int position) {
|
||||
Snackbar s = Snackbar
|
||||
.make(app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.undo_string, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
items.add(position, i);
|
||||
notifyItemInserted(position);
|
||||
|
||||
api.unmarkItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
items.remove(i);
|
||||
notifyItemRemoved(position);
|
||||
doUnmark(i, position);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
View view = s.getView();
|
||||
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
s.show();
|
||||
}
|
||||
|
||||
public void removeItemAtIndex(final int position) {
|
||||
|
||||
final Item i = items.get(position);
|
||||
|
||||
items.remove(i);
|
||||
notifyItemRemoved(position);
|
||||
|
||||
api.markItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {
|
||||
|
||||
doUnmark(i, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
Toast.makeText(app, app.getString(R.string.cant_mark_read), Toast.LENGTH_SHORT).show();
|
||||
items.add(i);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
LikeButton saveBtn;
|
||||
ImageButton browserBtn;
|
||||
ImageButton shareBtn;
|
||||
ImageView itemImage;
|
||||
ImageView sourceImage;
|
||||
TextView title;
|
||||
TextView sourceTitleAndDate;
|
||||
public ConstraintLayout mView;
|
||||
|
||||
public ViewHolder(ConstraintLayout itemView) {
|
||||
super(itemView);
|
||||
mView = itemView;
|
||||
handleClickListeners();
|
||||
handleCustomTabActions();
|
||||
}
|
||||
|
||||
private void handleClickListeners() {
|
||||
sourceImage = (ImageView) mView.findViewById( R.id.sourceImage);
|
||||
itemImage = (ImageView) mView.findViewById( R.id.itemImage);
|
||||
title = (TextView) mView.findViewById( R.id.title);
|
||||
sourceTitleAndDate = (TextView) mView.findViewById( R.id.sourceTitleAndDate);
|
||||
saveBtn = (LikeButton) mView.findViewById( R.id.favButton);
|
||||
shareBtn = (ImageButton) mView.findViewById( R.id.shareBtn);
|
||||
browserBtn = (ImageButton) mView.findViewById( R.id.browserBtn);
|
||||
|
||||
if (!fullHeightCards) {
|
||||
itemImage.setMaxHeight((int) c.getResources().getDimension(R.dimen.card_image_max_height));
|
||||
itemImage.setScaleType(ScaleType.CENTER_CROP);
|
||||
}
|
||||
|
||||
saveBtn.setOnLikeListener(new OnLikeListener() {
|
||||
@Override
|
||||
public void liked(LikeButton likeButton) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
api.starrItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
saveBtn.setLiked(false);
|
||||
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unLiked(LikeButton likeButton) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
api.unstarrItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
saveBtn.setLiked(true);
|
||||
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
shareBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, i.getLinkDecoded());
|
||||
sendIntent.setType("text/plain");
|
||||
c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
});
|
||||
|
||||
browserBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setData(Uri.parse(i.getLinkDecoded()));
|
||||
c.startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleCustomTabActions() {
|
||||
final CustomTabsIntent customTabsIntent = buildCustomTabsIntent(c);
|
||||
helper.bindCustomTabsService(app);
|
||||
|
||||
mView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openItemUrl(items.get(getAdapterPosition()),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app,
|
||||
c);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters
|
||||
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.support.constraint.ConstraintLayout
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.text.Html
|
||||
import android.text.format.DateUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.ImageView.ScaleType
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
||||
import com.amulyakhare.textdrawable.TextDrawable
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
||||
import com.like.LikeButton
|
||||
import com.like.OnLikeListener
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
class ItemCardAdapter(private val app: Activity, private val items: ArrayList<Item>, private val api: SelfossApi,
|
||||
private val helper: CustomTabActivityHelper, private val internalBrowser: Boolean,
|
||||
private val articleViewer: Boolean, private val fullHeightCards: Boolean) : RecyclerView.Adapter<ItemCardAdapter.ViewHolder>() {
|
||||
private val c: Context = app.applicationContext
|
||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val v = LayoutInflater.from(c).inflate(R.layout.card_item, parent, false) as ConstraintLayout
|
||||
return ViewHolder(v)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val itm = items[position]
|
||||
|
||||
|
||||
holder.saveBtn!!.isLiked = itm.starred
|
||||
holder.title!!.text = Html.fromHtml(itm.title)
|
||||
|
||||
var sourceAndDate = itm.sourcetitle
|
||||
val d: Long
|
||||
try {
|
||||
d = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itm.datetime).time
|
||||
sourceAndDate += " " + DateUtils.getRelativeTimeSpanString(
|
||||
d,
|
||||
Date().time,
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
)
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
holder.sourceTitleAndDate!!.text = sourceAndDate
|
||||
|
||||
if (itm.getThumbnail(c).isEmpty()) {
|
||||
Glide.clear(holder.itemImage)
|
||||
holder.itemImage!!.setImageDrawable(null)
|
||||
} else {
|
||||
if (fullHeightCards) {
|
||||
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().fitCenter().into(holder.itemImage)
|
||||
} else {
|
||||
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().centerCrop().into(holder.itemImage)
|
||||
}
|
||||
}
|
||||
|
||||
val fHolder = holder
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.sourcetitle)
|
||||
val textDrawable = StringBuilder()
|
||||
for (s in itm.sourcetitle.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||
textDrawable.append(s[0])
|
||||
}
|
||||
|
||||
val builder = TextDrawable.builder().round()
|
||||
|
||||
val drawable = builder.build(textDrawable.toString(), color)
|
||||
holder.sourceImage!!.setImageDrawable(drawable)
|
||||
} else {
|
||||
|
||||
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(object : BitmapImageViewTarget(holder.sourceImage) {
|
||||
override fun setResource(resource: Bitmap) {
|
||||
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource)
|
||||
circularBitmapDrawable.isCircular = true
|
||||
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
holder.saveBtn!!.isLiked = itm.starred
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
private fun doUnmark(i: Item, position: Int) {
|
||||
val s = Snackbar
|
||||
.make(app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.undo_string) {
|
||||
items.add(position, i)
|
||||
notifyItemInserted(position)
|
||||
|
||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
doUnmark(i, position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val view = s.view
|
||||
val tv = view.findViewById(android.support.design.R.id.snackbar_text) as TextView
|
||||
tv.setTextColor(Color.WHITE)
|
||||
s.show()
|
||||
}
|
||||
|
||||
fun removeItemAtIndex(position: Int) {
|
||||
|
||||
val i = items[position]
|
||||
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
|
||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
|
||||
doUnmark(i, position)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
Toast.makeText(app, app.getString(R.string.cant_mark_read), Toast.LENGTH_SHORT).show()
|
||||
items.add(i)
|
||||
notifyItemInserted(position)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||
var saveBtn: LikeButton? = null
|
||||
var browserBtn: ImageButton? = null
|
||||
var shareBtn: ImageButton? = null
|
||||
var itemImage: ImageView? = null
|
||||
var sourceImage: ImageView? = null
|
||||
var title: TextView? = null
|
||||
var sourceTitleAndDate: TextView? = null
|
||||
|
||||
init {
|
||||
handleClickListeners()
|
||||
handleCustomTabActions()
|
||||
}
|
||||
|
||||
private fun handleClickListeners() {
|
||||
sourceImage = mView.findViewById(R.id.sourceImage) as ImageView
|
||||
itemImage = mView.findViewById(R.id.itemImage) as ImageView
|
||||
title = mView.findViewById(R.id.title) as TextView
|
||||
sourceTitleAndDate = mView.findViewById(R.id.sourceTitleAndDate) as TextView
|
||||
saveBtn = mView.findViewById(R.id.favButton) as LikeButton
|
||||
shareBtn = mView.findViewById(R.id.shareBtn) as ImageButton
|
||||
browserBtn = mView.findViewById(R.id.browserBtn) as ImageButton
|
||||
|
||||
if (!fullHeightCards) {
|
||||
itemImage!!.maxHeight = c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
||||
itemImage!!.scaleType = ScaleType.CENTER_CROP
|
||||
}
|
||||
|
||||
saveBtn!!.setOnLikeListener(object : OnLikeListener {
|
||||
override fun liked(likeButton: LikeButton) {
|
||||
val (id) = items[adapterPosition]
|
||||
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
saveBtn!!.isLiked = false
|
||||
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun unLiked(likeButton: LikeButton) {
|
||||
val (id) = items[adapterPosition]
|
||||
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
saveBtn!!.isLiked = true
|
||||
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
shareBtn!!.setOnClickListener {
|
||||
val i = items[adapterPosition]
|
||||
val sendIntent = Intent()
|
||||
sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
sendIntent.action = Intent.ACTION_SEND
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, i.getLinkDecoded())
|
||||
sendIntent.type = "text/plain"
|
||||
c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||
}
|
||||
|
||||
browserBtn!!.setOnClickListener {
|
||||
val i = items[adapterPosition]
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
intent.data = Uri.parse(i.getLinkDecoded())
|
||||
c.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCustomTabActions() {
|
||||
val customTabsIntent = buildCustomTabsIntent(c)
|
||||
helper.bindCustomTabsService(app)
|
||||
|
||||
mView.setOnClickListener {
|
||||
openItemUrl(items[adapterPosition],
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app,
|
||||
c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,363 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters;
|
||||
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.support.constraint.ConstraintLayout;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Html;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.R;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse;
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper;
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget;
|
||||
import com.like.LikeButton;
|
||||
import com.like.OnLikeListener;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
import static apps.amine.bou.readerforselfoss.utils.LinksUtilsKt.buildCustomTabsIntent;
|
||||
import static apps.amine.bou.readerforselfoss.utils.LinksUtilsKt.openItemUrl;
|
||||
|
||||
|
||||
public class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ViewHolder> {
|
||||
private final boolean clickBehavior;
|
||||
private final boolean articleViewer;
|
||||
private final boolean internalBrowser;
|
||||
private final ColorGenerator generator;
|
||||
private SelfossApi api;
|
||||
private Context c;
|
||||
private List<Item> items;
|
||||
private List<Boolean> bars;
|
||||
private Activity app;
|
||||
private CustomTabActivityHelper helper;
|
||||
|
||||
public ItemListAdapter(Activity a, List<Item> myObject, SelfossApi selfossApi,
|
||||
CustomTabActivityHelper mCustomTabActivityHelper, boolean clickBehavior,
|
||||
boolean internalBrowser, boolean articleViewer) {
|
||||
app = a;
|
||||
items = myObject;
|
||||
api = selfossApi;
|
||||
helper = mCustomTabActivityHelper;
|
||||
c = app.getApplicationContext();
|
||||
this.clickBehavior = clickBehavior;
|
||||
this.internalBrowser = internalBrowser;
|
||||
this.articleViewer = articleViewer;
|
||||
bars = new ArrayList<>(Collections.nCopies(items.size() + 1, false));
|
||||
generator = ColorGenerator.MATERIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
ConstraintLayout v = (ConstraintLayout) LayoutInflater.from(c).inflate(R.layout.list_item, parent, false);
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Item itm = items.get(position);
|
||||
|
||||
|
||||
holder.saveBtn.setLiked((itm.getStarred()));
|
||||
holder.title.setText(Html.fromHtml(itm.getTitle()));
|
||||
|
||||
String sourceAndDate = itm.getSourcetitle();
|
||||
long d;
|
||||
try {
|
||||
d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itm.getDatetime()).getTime();
|
||||
sourceAndDate += " " +
|
||||
DateUtils.getRelativeTimeSpanString(
|
||||
d,
|
||||
new Date().getTime(),
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
holder.sourceTitleAndDate.setText(sourceAndDate);
|
||||
|
||||
if (itm.getThumbnail(c).isEmpty()) {
|
||||
int sizeInInt = 46;
|
||||
int sizeInDp = (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, sizeInInt, c.getResources()
|
||||
.getDisplayMetrics());
|
||||
|
||||
int marginInInt = 16;
|
||||
int marginInDp = (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, marginInInt, c.getResources()
|
||||
.getDisplayMetrics());
|
||||
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) holder.sourceImage.getLayoutParams();
|
||||
params.height = sizeInDp;
|
||||
params.width = sizeInDp;
|
||||
params.setMargins(marginInDp, 0, 0, 0);
|
||||
holder.sourceImage.setLayoutParams(params);
|
||||
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
int color = generator.getColor(itm.getSourcetitle());
|
||||
StringBuilder textDrawable = new StringBuilder();
|
||||
for(String s : itm.getSourcetitle().split(" "))
|
||||
{
|
||||
textDrawable.append(s.charAt(0));
|
||||
}
|
||||
|
||||
TextDrawable.IBuilder builder = TextDrawable.builder().round();
|
||||
|
||||
TextDrawable drawable = builder.build(textDrawable.toString(), color);
|
||||
holder.sourceImage.setImageDrawable(drawable);
|
||||
} else {
|
||||
|
||||
final ViewHolder fHolder = holder;
|
||||
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(new BitmapImageViewTarget(holder.sourceImage) {
|
||||
@Override
|
||||
protected void setResource(Bitmap resource) {
|
||||
RoundedBitmapDrawable circularBitmapDrawable =
|
||||
RoundedBitmapDrawableFactory.create(c.getResources(), resource);
|
||||
circularBitmapDrawable.setCircular(true);
|
||||
fHolder.sourceImage.setImageDrawable(circularBitmapDrawable);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().centerCrop().into(holder.sourceImage);
|
||||
}
|
||||
|
||||
if (bars.get(position)) {
|
||||
holder.actionBar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.actionBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.saveBtn.setLiked(itm.getStarred());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
|
||||
private void doUnmark(final Item i, final int position) {
|
||||
Snackbar s = Snackbar
|
||||
.make(app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.undo_string, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
items.add(position, i);
|
||||
notifyItemInserted(position);
|
||||
|
||||
api.unmarkItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
items.remove(i);
|
||||
notifyItemRemoved(position);
|
||||
doUnmark(i, position);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
View view = s.getView();
|
||||
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
s.show();
|
||||
}
|
||||
|
||||
public void removeItemAtIndex(final int position) {
|
||||
|
||||
final Item i = items.get(position);
|
||||
|
||||
items.remove(i);
|
||||
notifyItemRemoved(position);
|
||||
|
||||
api.markItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {
|
||||
doUnmark(i, position);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
Toast.makeText(app, app.getString(R.string.cant_mark_read), Toast.LENGTH_SHORT).show();
|
||||
items.add(i);
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
LikeButton saveBtn;
|
||||
ImageButton browserBtn;
|
||||
ImageButton shareBtn;
|
||||
public RelativeLayout actionBar;
|
||||
ImageView sourceImage;
|
||||
TextView title;
|
||||
TextView sourceTitleAndDate;
|
||||
public ConstraintLayout mView;
|
||||
|
||||
public ViewHolder(ConstraintLayout itemView) {
|
||||
super(itemView);
|
||||
mView = itemView;
|
||||
handleClickListeners();
|
||||
handleCustomTabActions();
|
||||
}
|
||||
|
||||
private void handleClickListeners() {
|
||||
actionBar = (RelativeLayout) mView.findViewById(R.id.actionBar);
|
||||
sourceImage = (ImageView) mView.findViewById( R.id.itemImage);
|
||||
title = (TextView) mView.findViewById( R.id.title);
|
||||
sourceTitleAndDate = (TextView) mView.findViewById( R.id.sourceTitleAndDate);
|
||||
saveBtn = (LikeButton) mView.findViewById( R.id.favButton);
|
||||
shareBtn = (ImageButton) mView.findViewById( R.id.shareBtn);
|
||||
browserBtn = (ImageButton) mView.findViewById( R.id.browserBtn);
|
||||
|
||||
|
||||
saveBtn.setOnLikeListener(new OnLikeListener() {
|
||||
@Override
|
||||
public void liked(LikeButton likeButton) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
api.starrItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
saveBtn.setLiked(false);
|
||||
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unLiked(LikeButton likeButton) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
api.unstarrItem(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
saveBtn.setLiked(true);
|
||||
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
shareBtn.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, i.getLinkDecoded());
|
||||
sendIntent.setType("text/plain");
|
||||
c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
});
|
||||
|
||||
browserBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Item i = items.get(getAdapterPosition());
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setData(Uri.parse(i.getLinkDecoded()));
|
||||
c.startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void handleCustomTabActions() {
|
||||
final CustomTabsIntent customTabsIntent = buildCustomTabsIntent(c);
|
||||
helper.bindCustomTabsService(app);
|
||||
|
||||
|
||||
if (!clickBehavior) {
|
||||
mView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openItemUrl(items.get(getAdapterPosition()),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app,
|
||||
c);
|
||||
}
|
||||
});
|
||||
mView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
actionBarShowHide();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
actionBarShowHide();
|
||||
}
|
||||
});
|
||||
mView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
openItemUrl(items.get(getAdapterPosition()),
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app,
|
||||
c);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void actionBarShowHide() {
|
||||
bars.set(getAdapterPosition(), true);
|
||||
if (actionBar.getVisibility() == View.GONE)
|
||||
actionBar.setVisibility(View.VISIBLE);
|
||||
else
|
||||
actionBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,290 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters
|
||||
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.support.constraint.ConstraintLayout
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.text.Html
|
||||
import android.text.format.DateUtils
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
||||
import com.amulyakhare.textdrawable.TextDrawable
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
||||
import com.like.LikeButton
|
||||
import com.like.OnLikeListener
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
class ItemListAdapter(private val app: Activity, private val items: ArrayList<Item>, private val api: SelfossApi,
|
||||
private val helper: CustomTabActivityHelper, private val clickBehavior: Boolean,
|
||||
private val internalBrowser: Boolean, private val articleViewer: Boolean) : RecyclerView.Adapter<ItemListAdapter.ViewHolder>() {
|
||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||
private val c: Context = app.applicationContext
|
||||
private val bars: ArrayList<Boolean> = ArrayList(Collections.nCopies(items.size + 1, false))
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val v = LayoutInflater.from(c).inflate(R.layout.list_item, parent, false) as ConstraintLayout
|
||||
return ViewHolder(v)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val itm = items[position]
|
||||
|
||||
|
||||
holder.saveBtn!!.isLiked = itm.starred
|
||||
holder.title!!.text = Html.fromHtml(itm.title)
|
||||
|
||||
var sourceAndDate = itm.sourcetitle
|
||||
val d: Long
|
||||
try {
|
||||
d = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(itm.datetime).time
|
||||
sourceAndDate += " " + DateUtils.getRelativeTimeSpanString(
|
||||
d,
|
||||
Date().time,
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
)
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
holder.sourceTitleAndDate!!.text = sourceAndDate
|
||||
|
||||
if (itm.getThumbnail(c).isEmpty()) {
|
||||
val sizeInInt = 46
|
||||
val sizeInDp = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
|
||||
.displayMetrics).toInt()
|
||||
|
||||
val marginInInt = 16
|
||||
val marginInDp = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
|
||||
.displayMetrics).toInt()
|
||||
|
||||
val params = holder.sourceImage!!.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.height = sizeInDp
|
||||
params.width = sizeInDp
|
||||
params.setMargins(marginInDp, 0, 0, 0)
|
||||
holder.sourceImage!!.layoutParams = params
|
||||
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.sourcetitle)
|
||||
val textDrawable = StringBuilder()
|
||||
for (s in itm.sourcetitle.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||
textDrawable.append(s[0])
|
||||
}
|
||||
|
||||
val builder = TextDrawable.builder().round()
|
||||
|
||||
val drawable = builder.build(textDrawable.toString(), color)
|
||||
holder.sourceImage!!.setImageDrawable(drawable)
|
||||
} else {
|
||||
|
||||
val fHolder = holder
|
||||
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(object : BitmapImageViewTarget(holder.sourceImage) {
|
||||
override fun setResource(resource: Bitmap) {
|
||||
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource)
|
||||
circularBitmapDrawable.isCircular = true
|
||||
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Glide.with(c).load(itm.getThumbnail(c)).asBitmap().centerCrop().into(holder.sourceImage)
|
||||
}
|
||||
|
||||
if (bars[position]) {
|
||||
holder.actionBar!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.actionBar!!.visibility = View.GONE
|
||||
}
|
||||
|
||||
holder.saveBtn!!.isLiked = itm.starred
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
|
||||
private fun doUnmark(i: Item, position: Int) {
|
||||
val s = Snackbar
|
||||
.make(app.findViewById(R.id.coordLayout), R.string.marked_as_read, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.undo_string) {
|
||||
items.add(position, i)
|
||||
notifyItemInserted(position)
|
||||
|
||||
api.unmarkItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
doUnmark(i, position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val view = s.view
|
||||
val tv = view.findViewById(android.support.design.R.id.snackbar_text) as TextView
|
||||
tv.setTextColor(Color.WHITE)
|
||||
s.show()
|
||||
}
|
||||
|
||||
fun removeItemAtIndex(position: Int) {
|
||||
|
||||
val i = items[position]
|
||||
|
||||
items.remove(i)
|
||||
notifyItemRemoved(position)
|
||||
|
||||
api.markItem(i.id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
doUnmark(i, position)
|
||||
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
Toast.makeText(app, app.getString(R.string.cant_mark_read), Toast.LENGTH_SHORT).show()
|
||||
items.add(i)
|
||||
notifyItemInserted(position)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
inner class ViewHolder(val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||
var saveBtn: LikeButton? = null
|
||||
var browserBtn: ImageButton? = null
|
||||
var shareBtn: ImageButton? = null
|
||||
var actionBar: RelativeLayout? = null
|
||||
var sourceImage: ImageView? = null
|
||||
var title: TextView? = null
|
||||
var sourceTitleAndDate: TextView? = null
|
||||
|
||||
init {
|
||||
handleClickListeners()
|
||||
handleCustomTabActions()
|
||||
}
|
||||
|
||||
private fun handleClickListeners() {
|
||||
actionBar = mView.findViewById(R.id.actionBar) as RelativeLayout
|
||||
sourceImage = mView.findViewById(R.id.itemImage) as ImageView
|
||||
title = mView.findViewById(R.id.title) as TextView
|
||||
sourceTitleAndDate = mView.findViewById(R.id.sourceTitleAndDate) as TextView
|
||||
saveBtn = mView.findViewById(R.id.favButton) as LikeButton
|
||||
shareBtn = mView.findViewById(R.id.shareBtn) as ImageButton
|
||||
browserBtn = mView.findViewById(R.id.browserBtn) as ImageButton
|
||||
|
||||
|
||||
saveBtn!!.setOnLikeListener(object : OnLikeListener {
|
||||
override fun liked(likeButton: LikeButton) {
|
||||
val (id) = items[adapterPosition]
|
||||
api.starrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
saveBtn!!.isLiked = false
|
||||
Toast.makeText(c, R.string.cant_mark_favortie, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun unLiked(likeButton: LikeButton) {
|
||||
val (id) = items[adapterPosition]
|
||||
api.unstarrItem(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
saveBtn!!.isLiked = true
|
||||
Toast.makeText(c, R.string.cant_unmark_favortie, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
shareBtn!!.setOnClickListener {
|
||||
val i = items[adapterPosition]
|
||||
val sendIntent = Intent()
|
||||
sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
sendIntent.action = Intent.ACTION_SEND
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, i.getLinkDecoded())
|
||||
sendIntent.type = "text/plain"
|
||||
c.startActivity(Intent.createChooser(sendIntent, c.getString(R.string.share)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||
}
|
||||
|
||||
browserBtn!!.setOnClickListener {
|
||||
val i = items[adapterPosition]
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
intent.data = Uri.parse(i.getLinkDecoded())
|
||||
c.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun handleCustomTabActions() {
|
||||
val customTabsIntent = buildCustomTabsIntent(c)
|
||||
helper.bindCustomTabsService(app)
|
||||
|
||||
|
||||
if (!clickBehavior) {
|
||||
mView.setOnClickListener {
|
||||
openItemUrl(items[adapterPosition],
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app,
|
||||
c)
|
||||
}
|
||||
mView.setOnLongClickListener {
|
||||
actionBarShowHide()
|
||||
true
|
||||
}
|
||||
} else {
|
||||
mView.setOnClickListener { actionBarShowHide() }
|
||||
mView.setOnLongClickListener {
|
||||
openItemUrl(items[adapterPosition],
|
||||
customTabsIntent,
|
||||
internalBrowser,
|
||||
articleViewer,
|
||||
app,
|
||||
c)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun actionBarShowHide() {
|
||||
bars[adapterPosition] = true
|
||||
if (actionBar!!.visibility == View.GONE)
|
||||
actionBar!!.visibility = View.VISIBLE
|
||||
else
|
||||
actionBar!!.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.constraint.ConstraintLayout;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.*;
|
||||
import apps.amine.bou.readerforselfoss.R;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Sources;
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse;
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SourcesListAdapter extends RecyclerView.Adapter<SourcesListAdapter.ViewHolder> {
|
||||
private final List<Sources> items;
|
||||
private final Activity app;
|
||||
private final SelfossApi api;
|
||||
private final Context c;
|
||||
private final ColorGenerator generator;
|
||||
|
||||
public SourcesListAdapter(Activity activity, List<Sources> items, SelfossApi api) {
|
||||
this.app = activity;
|
||||
this.items = items;
|
||||
this.api = api;
|
||||
this.c = app.getBaseContext();
|
||||
|
||||
generator = ColorGenerator.MATERIAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
ConstraintLayout v = (ConstraintLayout) LayoutInflater.from(c).inflate(R.layout.source_list_item, parent, false);
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Sources itm = items.get(position);
|
||||
|
||||
final ViewHolder fHolder = holder;
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
int color = generator.getColor(itm.getTitle());
|
||||
StringBuilder textDrawable = new StringBuilder();
|
||||
for(String s : itm.getTitle().split(" "))
|
||||
{
|
||||
textDrawable.append(s.charAt(0));
|
||||
}
|
||||
|
||||
TextDrawable.IBuilder builder = TextDrawable.builder().round();
|
||||
|
||||
TextDrawable drawable = builder.build(textDrawable.toString(), color);
|
||||
holder.sourceImage.setImageDrawable(drawable);
|
||||
} else {
|
||||
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(new BitmapImageViewTarget(holder.sourceImage) {
|
||||
@Override
|
||||
protected void setResource(Bitmap resource) {
|
||||
RoundedBitmapDrawable circularBitmapDrawable =
|
||||
RoundedBitmapDrawableFactory.create(c.getResources(), resource);
|
||||
circularBitmapDrawable.setCircular(true);
|
||||
fHolder.sourceImage.setImageDrawable(circularBitmapDrawable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
holder.sourceTitle.setText(itm.getTitle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ConstraintLayout mView;
|
||||
ImageView sourceImage;
|
||||
TextView sourceTitle;
|
||||
Button deleteBtn;
|
||||
|
||||
public ViewHolder(ConstraintLayout itemView) {
|
||||
super(itemView);
|
||||
mView = itemView;
|
||||
|
||||
handleClickListeners();
|
||||
}
|
||||
|
||||
private void handleClickListeners() {
|
||||
sourceImage = (ImageView) mView.findViewById(R.id.itemImage);
|
||||
sourceTitle = (TextView) mView.findViewById(R.id.sourceTitle);
|
||||
deleteBtn = (Button) mView.findViewById(R.id.deleteBtn);
|
||||
|
||||
deleteBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Sources i = items.get(getAdapterPosition());
|
||||
api.deleteSource(i.getId()).enqueue(new Callback<SuccessResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<SuccessResponse> call, Response<SuccessResponse> response) {
|
||||
if (response.body() != null && response.body().isSuccess()) {
|
||||
items.remove(getAdapterPosition());
|
||||
notifyItemRemoved(getAdapterPosition());
|
||||
notifyItemRangeChanged(getAdapterPosition(), getItemCount());
|
||||
}
|
||||
else {
|
||||
Toast.makeText(app, "Petit soucis lors de la suppression de la source.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SuccessResponse> call, Throwable t) {
|
||||
Toast.makeText(app, "Petit soucis lors de la suppression de la source.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package apps.amine.bou.readerforselfoss.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.support.constraint.ConstraintLayout
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Sources
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
|
||||
import com.amulyakhare.textdrawable.TextDrawable
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class SourcesListAdapter(private val app: Activity, private val items: ArrayList<Sources>, private val api: SelfossApi) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>() {
|
||||
private val c: Context = app.baseContext
|
||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val v = LayoutInflater.from(c).inflate(R.layout.source_list_item, parent, false) as ConstraintLayout
|
||||
return ViewHolder(v)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val itm = items[position]
|
||||
|
||||
val fHolder = holder
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.title)
|
||||
val textDrawable = StringBuilder()
|
||||
for (s in itm.title.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||
textDrawable.append(s[0])
|
||||
}
|
||||
|
||||
val builder = TextDrawable.builder().round()
|
||||
|
||||
val drawable = builder.build(textDrawable.toString(), color)
|
||||
holder.sourceImage!!.setImageDrawable(drawable)
|
||||
} else {
|
||||
Glide.with(c).load(itm.getIcon(c)).asBitmap().centerCrop().into(object : BitmapImageViewTarget(holder.sourceImage) {
|
||||
override fun setResource(resource: Bitmap) {
|
||||
val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(c.resources, resource)
|
||||
circularBitmapDrawable.isCircular = true
|
||||
fHolder.sourceImage!!.setImageDrawable(circularBitmapDrawable)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
holder.sourceTitle!!.text = itm.title
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
inner class ViewHolder(internal val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||
var sourceImage: ImageView? = null
|
||||
var sourceTitle: TextView? = null
|
||||
|
||||
init {
|
||||
|
||||
handleClickListeners()
|
||||
}
|
||||
|
||||
private fun handleClickListeners() {
|
||||
sourceImage = mView.findViewById(R.id.itemImage) as ImageView
|
||||
sourceTitle = mView.findViewById(R.id.sourceTitle) as TextView
|
||||
|
||||
val deleteBtn = mView.findViewById(R.id.deleteBtn) as Button
|
||||
|
||||
deleteBtn.setOnClickListener {
|
||||
val (id) = items[adapterPosition]
|
||||
api.deleteSource(id).enqueue(object : Callback<SuccessResponse> {
|
||||
override fun onResponse(call: Call<SuccessResponse>, response: Response<SuccessResponse>) {
|
||||
if (response.body() != null && response.body().isSuccess) {
|
||||
items.removeAt(adapterPosition)
|
||||
notifyItemRemoved(adapterPosition)
|
||||
notifyItemRangeChanged(adapterPosition, itemCount)
|
||||
} else {
|
||||
Toast.makeText(app, "Petit soucis lors de la suppression de la source.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
|
||||
Toast.makeText(app, "Petit soucis lors de la suppression de la source.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.api.mercury;
|
||||
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
|
||||
public class MercuryApi {
|
||||
private final MercuryService service;
|
||||
private final String key;
|
||||
|
||||
public MercuryApi(String key) {
|
||||
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
|
||||
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
this.key = key;
|
||||
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://mercury.postlight.com").client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson)).build();
|
||||
service = retrofit.create(MercuryService.class);
|
||||
}
|
||||
|
||||
public Call<ParsedContent> parseUrl(String url) {
|
||||
return service.parseUrl(url, this.key);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package apps.amine.bou.readerforselfoss.api.mercury
|
||||
|
||||
|
||||
import com.google.gson.GsonBuilder
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Call
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
|
||||
class MercuryApi(private val key: String) {
|
||||
private val service: MercuryService
|
||||
|
||||
init {
|
||||
|
||||
val interceptor = HttpLoggingInterceptor()
|
||||
interceptor.level = HttpLoggingInterceptor.Level.BODY
|
||||
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
|
||||
|
||||
val gson = GsonBuilder()
|
||||
.setLenient()
|
||||
.create()
|
||||
val retrofit = Retrofit.Builder().baseUrl("https://mercury.postlight.com").client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson)).build()
|
||||
service = retrofit.create(MercuryService::class.java)
|
||||
}
|
||||
|
||||
fun parseUrl(url: String): Call<ParsedContent> {
|
||||
return service.parseUrl(url, this.key)
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.api.mercury;
|
||||
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
|
||||
public interface MercuryService {
|
||||
@GET("parser")
|
||||
Call<ParsedContent> parseUrl(@Query("url") String url, @Header("x-api-key") String key);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package apps.amine.bou.readerforselfoss.api.mercury
|
||||
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Query
|
||||
|
||||
|
||||
interface MercuryService {
|
||||
@GET("parser")
|
||||
fun parseUrl(@Query("url") url: String, @Header("x-api-key") key: String): Call<ParsedContent>
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.api.selfoss;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import apps.amine.bou.readerforselfoss.utils.Config;
|
||||
import com.burgstaller.okhttp.AuthenticationCacheInterceptor;
|
||||
import com.burgstaller.okhttp.CachingAuthenticatorDecorator;
|
||||
import com.burgstaller.okhttp.DispatchingAuthenticator;
|
||||
import com.burgstaller.okhttp.basic.BasicAuthenticator;
|
||||
import com.burgstaller.okhttp.digest.CachingAuthenticator;
|
||||
import com.burgstaller.okhttp.digest.Credentials;
|
||||
import com.burgstaller.okhttp.digest.DigestAuthenticator;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
|
||||
public class SelfossApi {
|
||||
|
||||
private final SelfossService service;
|
||||
private final Config config;
|
||||
private final String userName;
|
||||
private final String password;
|
||||
|
||||
public SelfossApi(Context c) {
|
||||
this.config = new Config(c);
|
||||
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder();
|
||||
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
|
||||
|
||||
String httpUserName = config.getHttpUserLogin();
|
||||
String httpPassword = config.getHttpUserPassword();
|
||||
|
||||
Credentials credentials = new Credentials(httpUserName, httpPassword);
|
||||
final BasicAuthenticator basicAuthenticator = new BasicAuthenticator(credentials);
|
||||
final DigestAuthenticator digestAuthenticator = new DigestAuthenticator(credentials);
|
||||
|
||||
// note that all auth schemes should be registered as lowercase!
|
||||
DispatchingAuthenticator authenticator = new DispatchingAuthenticator.Builder()
|
||||
.with("digest", digestAuthenticator)
|
||||
.with("basic", basicAuthenticator)
|
||||
.build();
|
||||
|
||||
OkHttpClient client = httpBuilder
|
||||
.authenticator(new CachingAuthenticatorDecorator(authenticator, authCache))
|
||||
.addInterceptor(new AuthenticationCacheInterceptor(authCache))
|
||||
.addInterceptor(interceptor)
|
||||
.build();
|
||||
|
||||
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapter(boolean.class, new BooleanTypeAdapter());
|
||||
|
||||
Gson gson = builder
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
userName = config.getUserLogin();
|
||||
password = config.getUserPassword();
|
||||
Retrofit retrofit = new Retrofit.Builder().baseUrl(config.getBaseUrl()).client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson)).build();
|
||||
service = retrofit.create(SelfossService.class);
|
||||
}
|
||||
|
||||
public Call<SuccessResponse> login() {
|
||||
return service.loginToSelfoss(config.getUserLogin(), config.getUserPassword());
|
||||
}
|
||||
|
||||
public Call<List<Item>> getReadItems() {
|
||||
return getItems("read");
|
||||
}
|
||||
|
||||
public Call<List<Item>> getUnreadItems() {
|
||||
return getItems("unread");
|
||||
}
|
||||
|
||||
public Call<List<Item>> getStarredItems() {
|
||||
return getItems("starred");
|
||||
}
|
||||
|
||||
private Call<List<Item>> getItems(String type) {
|
||||
return service.getItems(type, userName, password);
|
||||
}
|
||||
|
||||
public Call<SuccessResponse> markItem(String itemId) {
|
||||
return service.markAsRead(itemId, userName, password);
|
||||
}
|
||||
|
||||
public Call<SuccessResponse> unmarkItem(String itemId) {
|
||||
return service.unmarkAsRead(itemId, userName, password);
|
||||
}
|
||||
|
||||
public Call<SuccessResponse> readAll(List<String> ids) {
|
||||
return service.markAllAsRead(ids, userName, password);
|
||||
}
|
||||
|
||||
public Call<SuccessResponse> starrItem(String itemId) {
|
||||
return service.starr(itemId, userName, password);
|
||||
}
|
||||
|
||||
|
||||
public Call<SuccessResponse> unstarrItem(String itemId) {
|
||||
return service.unstarr(itemId, userName, password);
|
||||
}
|
||||
|
||||
public Call<Stats> getStats() {
|
||||
return service.stats(userName, password);
|
||||
}
|
||||
|
||||
public Call<List<Tag>> getTags() {
|
||||
return service.tags(userName, password);
|
||||
}
|
||||
|
||||
public Call<String> update() {
|
||||
return service.update(userName, password);
|
||||
}
|
||||
|
||||
public Call<List<Sources>> getSources() { return service.sources(userName, password); }
|
||||
|
||||
public Call<SuccessResponse> deleteSource(String id) { return service.deleteSource(id, userName, password);}
|
||||
|
||||
public Call<Map<String, Spout>> spouts() { return service.spouts(userName, password); }
|
||||
|
||||
public Call<SuccessResponse> createSource(String title, String url, String spout, String tags, String filter) {return service.createSource(title, url, spout, tags, filter, userName, password);}
|
||||
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package apps.amine.bou.readerforselfoss.api.selfoss
|
||||
|
||||
|
||||
import android.content.Context
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import com.burgstaller.okhttp.AuthenticationCacheInterceptor
|
||||
import com.burgstaller.okhttp.CachingAuthenticatorDecorator
|
||||
import com.burgstaller.okhttp.DispatchingAuthenticator
|
||||
import com.burgstaller.okhttp.basic.BasicAuthenticator
|
||||
import com.burgstaller.okhttp.digest.CachingAuthenticator
|
||||
import com.burgstaller.okhttp.digest.Credentials
|
||||
import com.burgstaller.okhttp.digest.DigestAuthenticator
|
||||
import com.google.gson.GsonBuilder
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Call
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
|
||||
class SelfossApi(c: Context) {
|
||||
|
||||
private val service: SelfossService
|
||||
private val config: Config = Config(c)
|
||||
private val userName: String
|
||||
private val password: String
|
||||
|
||||
init {
|
||||
|
||||
val interceptor = HttpLoggingInterceptor()
|
||||
interceptor.level = HttpLoggingInterceptor.Level.BODY
|
||||
|
||||
val httpBuilder = OkHttpClient.Builder()
|
||||
val authCache = ConcurrentHashMap<String, CachingAuthenticator>()
|
||||
|
||||
val httpUserName = config.httpUserLogin
|
||||
val httpPassword = config.httpUserPassword
|
||||
|
||||
val credentials = Credentials(httpUserName, httpPassword)
|
||||
val basicAuthenticator = BasicAuthenticator(credentials)
|
||||
val digestAuthenticator = DigestAuthenticator(credentials)
|
||||
|
||||
// note that all auth schemes should be registered as lowercase!
|
||||
val authenticator = DispatchingAuthenticator.Builder()
|
||||
.with("digest", digestAuthenticator)
|
||||
.with("basic", basicAuthenticator)
|
||||
.build()
|
||||
|
||||
val client = httpBuilder
|
||||
.authenticator(CachingAuthenticatorDecorator(authenticator, authCache))
|
||||
.addInterceptor(AuthenticationCacheInterceptor(authCache))
|
||||
.addInterceptor(interceptor)
|
||||
.build()
|
||||
|
||||
|
||||
val builder = GsonBuilder()
|
||||
builder.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanTypeAdapter())
|
||||
|
||||
val gson = builder
|
||||
.setLenient()
|
||||
.create()
|
||||
|
||||
userName = config.userLogin
|
||||
password = config.userPassword
|
||||
val retrofit = Retrofit.Builder().baseUrl(config.baseUrl).client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create(gson)).build()
|
||||
service = retrofit.create(SelfossService::class.java)
|
||||
}
|
||||
|
||||
fun login(): Call<SuccessResponse> {
|
||||
return service.loginToSelfoss(config.userLogin, config.userPassword)
|
||||
}
|
||||
|
||||
val readItems: Call<List<Item>>
|
||||
get() = getItems("read")
|
||||
|
||||
val unreadItems: Call<List<Item>>
|
||||
get() = getItems("unread")
|
||||
|
||||
val starredItems: Call<List<Item>>
|
||||
get() = getItems("starred")
|
||||
|
||||
private fun getItems(type: String): Call<List<Item>> {
|
||||
return service.getItems(type, userName, password)
|
||||
}
|
||||
|
||||
fun markItem(itemId: String): Call<SuccessResponse> {
|
||||
return service.markAsRead(itemId, userName, password)
|
||||
}
|
||||
|
||||
fun unmarkItem(itemId: String): Call<SuccessResponse> {
|
||||
return service.unmarkAsRead(itemId, userName, password)
|
||||
}
|
||||
|
||||
fun readAll(ids: List<String>): Call<SuccessResponse> {
|
||||
return service.markAllAsRead(ids, userName, password)
|
||||
}
|
||||
|
||||
fun starrItem(itemId: String): Call<SuccessResponse> {
|
||||
return service.starr(itemId, userName, password)
|
||||
}
|
||||
|
||||
|
||||
fun unstarrItem(itemId: String): Call<SuccessResponse> {
|
||||
return service.unstarr(itemId, userName, password)
|
||||
}
|
||||
|
||||
val stats: Call<Stats>
|
||||
get() = service.stats(userName, password)
|
||||
|
||||
val tags: Call<List<Tag>>
|
||||
get() = service.tags(userName, password)
|
||||
|
||||
fun update(): Call<String> {
|
||||
return service.update(userName, password)
|
||||
}
|
||||
|
||||
val sources: Call<List<Sources>>
|
||||
get() = service.sources(userName, password)
|
||||
|
||||
fun deleteSource(id: String): Call<SuccessResponse> {
|
||||
return service.deleteSource(id, userName, password)
|
||||
}
|
||||
|
||||
fun spouts(): Call<Map<String, Spout>> {
|
||||
return service.spouts(userName, password)
|
||||
}
|
||||
|
||||
fun createSource(title: String, url: String, spout: String, tags: String, filter: String): Call<SuccessResponse> {
|
||||
return service.createSource(title, url, spout, tags, filter, userName, password)
|
||||
}
|
||||
|
||||
}
|
@ -68,8 +68,8 @@ data class Item(val id: String,
|
||||
id = source.readString(),
|
||||
datetime = source.readString(),
|
||||
title = source.readString(),
|
||||
unread = source.readByte() != 0,
|
||||
starred = source.readByte() != 0,
|
||||
unread = 0.toByte() != source.readByte(),
|
||||
starred = 0.toByte() != source.readByte(),
|
||||
thumbnail = source.readString(),
|
||||
icon = source.readString(),
|
||||
link = source.readString(),
|
||||
|
@ -1,68 +0,0 @@
|
||||
package apps.amine.bou.readerforselfoss.api.selfoss;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.DELETE;
|
||||
import retrofit2.http.Field;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
|
||||
interface SelfossService {
|
||||
@GET("login")
|
||||
Call<SuccessResponse> loginToSelfoss(@Query("username") String username, @Query("password") String password);
|
||||
|
||||
@GET("items")
|
||||
Call<List<Item>> getItems(@Query("type") String type, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
@POST("mark/{id}")
|
||||
Call<SuccessResponse> markAsRead(@Path("id") String id, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@POST("unmark/{id}")
|
||||
Call<SuccessResponse> unmarkAsRead(@Path("id") String id, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("mark")
|
||||
Call<SuccessResponse> markAllAsRead(@Field("ids[]") List<String> ids, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@POST("starr/{id}")
|
||||
Call<SuccessResponse> starr(@Path("id") String id, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@POST("unstarr/{id}")
|
||||
Call<SuccessResponse> unstarr(@Path("id") String id, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@GET("stats")
|
||||
Call<Stats> stats(@Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@GET("tags")
|
||||
Call<List<Tag>> tags(@Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@GET("update")
|
||||
Call<String> update(@Query("username") String username, @Query("password") String password);
|
||||
|
||||
@GET("sources/spouts")
|
||||
Call<Map<String, Spout>> spouts(@Query("username") String username, @Query("password") String password);
|
||||
|
||||
@GET("sources/list")
|
||||
Call<List<Sources>> sources(@Query("username") String username, @Query("password") String password);
|
||||
|
||||
|
||||
@DELETE("source/{id}")
|
||||
Call<SuccessResponse> deleteSource(@Path("id") String id, @Query("username") String username, @Query("password") String password);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("source")
|
||||
Call<SuccessResponse> createSource(@Field("title") String title, @Field("url") String url, @Field("spout") String spout, @Field("tags") String tags, @Field("filter") String filter, @Query("username") String username, @Query("password") String password);
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package apps.amine.bou.readerforselfoss.api.selfoss
|
||||
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
|
||||
internal interface SelfossService {
|
||||
@GET("login")
|
||||
fun loginToSelfoss(@Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
@GET("items")
|
||||
fun getItems(@Query("type") type: String, @Query("username") username: String, @Query("password") password: String): Call<List<Item>>
|
||||
|
||||
@POST("mark/{id}")
|
||||
fun markAsRead(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
|
||||
@POST("unmark/{id}")
|
||||
fun unmarkAsRead(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("mark")
|
||||
fun markAllAsRead(@Field("ids[]") ids: List<String>, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
|
||||
@POST("starr/{id}")
|
||||
fun starr(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
|
||||
@POST("unstarr/{id}")
|
||||
fun unstarr(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
|
||||
@GET("stats")
|
||||
fun stats(@Query("username") username: String, @Query("password") password: String): Call<Stats>
|
||||
|
||||
|
||||
@GET("tags")
|
||||
fun tags(@Query("username") username: String, @Query("password") password: String): Call<List<Tag>>
|
||||
|
||||
|
||||
@GET("update")
|
||||
fun update(@Query("username") username: String, @Query("password") password: String): Call<String>
|
||||
|
||||
@GET("sources/spouts")
|
||||
fun spouts(@Query("username") username: String, @Query("password") password: String): Call<Map<String, Spout>>
|
||||
|
||||
@GET("sources/list")
|
||||
fun sources(@Query("username") username: String, @Query("password") password: String): Call<List<Sources>>
|
||||
|
||||
|
||||
@DELETE("source/{id}")
|
||||
fun deleteSource(@Path("id") id: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("source")
|
||||
fun createSource(@Field("title") title: String, @Field("url") url: String, @Field("spout") spout: String, @Field("tags") tags: String, @Field("filter") filter: String, @Query("username") username: String, @Query("password") password: String): Call<SuccessResponse>
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package apps.amine.bou.readerforselfoss.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
|
@ -9,7 +9,7 @@
|
||||
<string name="prompt_url">"Url"</string>
|
||||
<string name="withLoginSwitch">"Login required ?"</string>
|
||||
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string>
|
||||
<string name="login_url_problem">"Oups. You may need to add a \"/\" at the end of the url."</string>
|
||||
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
|
||||
<string name="prompt_login">"Username"</string>
|
||||
<string name="prompt_http_login">"HTTP Username"</string>
|
||||
<string name="label_share">"Share"</string>
|
||||
|
Loading…
Reference in New Issue
Block a user