From 0e573c7a52e58f68043b4eddd3048d5b77c6904a Mon Sep 17 00:00:00 2001 From: Dar9586 Date: Thu, 14 Feb 2019 22:08:05 +0100 Subject: [PATCH] NClientV2 1.7.7 + Added new SearchActivity * Check for updates from API 16 * Bug fixes --- app/build.gradle | 8 +- app/src/main/AndroidManifest.xml | 17 ++- .../java/com/dar/nclientv2/MainActivity.java | 101 +++++++++++------- .../com/dar/nclientv2/SearchActivity.java | 101 ++++++++++++++++++ .../nclientv2/adapters/HistoryAdapter.java | 100 +++++++++++++++++ .../java/com/dar/nclientv2/api/Inspector.java | 2 +- .../dar/nclientv2/async/VersionChecker.java | 1 + .../async/scrape/TagPageScraper.java | 2 +- .../components/CustomSSLSocketFactory.java | 98 +++++++++++++++++ .../dar/nclientv2/components/CustomSwipe.java | 31 ++++++ .../com/dar/nclientv2/components/History.java | 63 +++++++++++ .../com/dar/nclientv2/settings/Global.java | 18 +++- app/src/main/res/drawable/ic_add.xml | 9 ++ app/src/main/res/drawable/ic_mode_edit.xml | 9 ++ app/src/main/res/layout/activity_search.xml | 34 ++++++ app/src/main/res/layout/entry_history.xml | 46 ++++++++ app/src/main/res/menu/search.xml | 14 +++ app/src/main/res/values/strings.xml | 9 +- app/src/main/res/xml/backup_content.xml | 2 - app/src/main/res/xml/settings.xml | 6 ++ 20 files changed, 620 insertions(+), 51 deletions(-) create mode 100644 app/src/main/java/com/dar/nclientv2/SearchActivity.java create mode 100644 app/src/main/java/com/dar/nclientv2/adapters/HistoryAdapter.java create mode 100644 app/src/main/java/com/dar/nclientv2/components/CustomSSLSocketFactory.java create mode 100644 app/src/main/java/com/dar/nclientv2/components/CustomSwipe.java create mode 100644 app/src/main/java/com/dar/nclientv2/components/History.java create mode 100644 app/src/main/res/drawable/ic_add.xml create mode 100644 app/src/main/res/drawable/ic_mode_edit.xml create mode 100644 app/src/main/res/layout/activity_search.xml create mode 100644 app/src/main/res/layout/entry_history.xml create mode 100644 app/src/main/res/menu/search.xml diff --git a/app/build.gradle b/app/build.gradle index d3c3c27c..1478ce43 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.dar.nclientv2" minSdkVersion 14 targetSdkVersion 28 - versionCode 176 - versionName "1.7.6" + versionCode 177 + versionName "1.7.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -30,7 +30,7 @@ android { } dependencies { - def supportVersion='1.0.0' + def supportVersion = '1.0.0' implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "androidx.appcompat:appcompat:1.0.2" implementation "androidx.legacy:legacy-support-v4:$supportVersion" @@ -46,4 +46,6 @@ dependencies { implementation 'org.jsoup:jsoup:1.11.3' implementation "ch.acra:acra-core:5.1.3" + implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'androidx.viewpager:viewpager:1.0.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d8aef396..b122d326 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,10 +16,13 @@ android:roundIcon="@mipmap/ic_launcher" android:supportsRtl="true" android:theme="@style/LightTheme"> + + @@ -40,6 +43,7 @@ + @@ -57,7 +61,9 @@ + + @@ -102,7 +108,9 @@ + + @@ -118,7 +126,9 @@ + + @@ -132,7 +142,9 @@ + + @@ -159,12 +171,15 @@ + + + diff --git a/app/src/main/java/com/dar/nclientv2/MainActivity.java b/app/src/main/java/com/dar/nclientv2/MainActivity.java index 3ce0c93e..a1357081 100644 --- a/app/src/main/java/com/dar/nclientv2/MainActivity.java +++ b/app/src/main/java/com/dar/nclientv2/MainActivity.java @@ -2,6 +2,7 @@ import android.Manifest; import android.annotation.TargetApi; +import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; @@ -12,7 +13,6 @@ import android.view.MenuItem; import android.view.View; import android.widget.EditText; -import android.widget.ImageView; import com.dar.nclientv2.api.Inspector; import com.dar.nclientv2.api.components.Tag; @@ -35,9 +35,9 @@ import java.util.Locale; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; @@ -51,6 +51,7 @@ public class MainActivity extends BaseActivity private Tag tag; private int related=-1; private boolean tagFromURL=false; + private static boolean firstTime=true; public void setInspector(Inspector inspector) { this.inspector = inspector; } @@ -106,12 +107,10 @@ protected void onCreate(Bundle savedInstanceState) { navigationView = findViewById(R.id.nav_view); changeNavigationImage(navigationView); navigationView.setNavigationItemSelectedListener(this); - navigationView.getMenu().findItem(R.id.online_favorite_manager).setVisible(com.dar.nclientv2.settings.Login.isLogged()); navigationView.getMenu().findItem(R.id.action_login).setTitle(com.dar.nclientv2.settings.Login.isLogged()?R.string.logout:R.string.login); recycler=findViewById(R.id.recycler); refresher=findViewById(R.id.refresher); - prepareUpdateIcon(); recycler.setHasFixedSize(true); recycler.setItemViewCacheSize(24); recycler.addOnScrollListener(new RecyclerView.OnScrollListener(){ @@ -160,7 +159,10 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){ drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); toggle.setDrawerIndicatorEnabled(false); } else new Inspector(this,1,"",ApiRequestType.BYALL); - if(Global.shouldCheckForUpdates(this))new VersionChecker(this,true); + if(firstTime){ + if(Global.shouldCheckForUpdates(this))new VersionChecker(this,true); + firstTime=false; + } } private void changeNavigationImage(NavigationView navigationView) { @@ -176,33 +178,18 @@ protected void onDestroy(){ super.onDestroy(); } - private void prepareUpdateIcon(){ - if(Global.getOnlyLanguage()==null)Global.updateOnlyLanguage(this,Language.UNKNOWN); - else{ - switch (Global.getOnlyLanguage()){ - case ENGLISH:Global.updateOnlyLanguage(this,null);break; - case JAPANESE:Global.updateOnlyLanguage(this,Language.ENGLISH);break; - case CHINESE:Global.updateOnlyLanguage(this,Language.JAPANESE);break; - case UNKNOWN:Global.updateOnlyLanguage(this,Language.CHINESE);break; - } - } - } - private void updateLanguageIcon(MenuItem item,boolean update){ + private void updateLanguageIcon(MenuItem item){ //ALL,ENGLISH;JAPANESE;CHINESE;OTHER - if(Global.getOnlyLanguage()==null){ - Global.updateOnlyLanguage(this,Language.ENGLISH); - item.setTitle(R.string.only_english); - item.setIcon(R.drawable.ic_gbbw); - } + if(Global.getOnlyLanguage()==null) Global.updateOnlyLanguage(this,Language.ENGLISH); else switch (Global.getOnlyLanguage()){ - case ENGLISH:Global.updateOnlyLanguage(this, Language.JAPANESE);item.setTitle(R.string.only_japanese);item.setIcon(R.drawable.ic_jpbw);break; - case JAPANESE:Global.updateOnlyLanguage(this, Language.CHINESE);item.setTitle(R.string.only_chinese);item.setIcon(R.drawable.ic_cnbw);break; - case CHINESE:Global.updateOnlyLanguage(this, Language.UNKNOWN);item.setTitle(R.string.only_other);item.setIcon(R.drawable.ic_help);break; - case UNKNOWN:Global.updateOnlyLanguage(this, null);item.setTitle(R.string.all_languages);item.setIcon(R.drawable.ic_world);break; + case ENGLISH:Global.updateOnlyLanguage(this, Language.JAPANESE);break; + case JAPANESE:Global.updateOnlyLanguage(this, Language.CHINESE);break; + case CHINESE:Global.updateOnlyLanguage(this, Language.UNKNOWN);break; + case UNKNOWN:Global.updateOnlyLanguage(this, null);break; } - if(update)new Inspector(MainActivity.this,Inspector.getActualPage(),Inspector.getActualQuery(),Inspector.getActualRequestType()); + new Inspector(MainActivity.this,Inspector.getActualPage(),Inspector.getActualQuery(),Inspector.getActualRequestType()); Global.setTint(item.getIcon()); } @Override @@ -259,7 +246,6 @@ private class Setting{ } } private void removeQuery(){ - searchView.setQuery("",false); getSupportActionBar().setTitle(R.string.app_name); if(related!=-1){ new Inspector(this,1,""+related,ApiRequestType.RELATED); @@ -298,14 +284,13 @@ protected void onResume() { } invalidateOptionsMenu(); } - private SearchView searchView; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); menu.findItem(R.id.by_popular).setIcon(Global.isByPopular()?R.drawable.ic_star_border:R.drawable.ic_access_time); menu.findItem(R.id.by_popular).setTitle(Global.isByPopular()?R.string.sort_by_popular:R.string.sort_by_latest); - updateLanguageIcon(menu.findItem(R.id.only_language),false); + showLanguageIcon(menu.findItem(R.id.only_language)); if(tag!=null||related!=-1){ if(tag!=null){ @@ -323,12 +308,12 @@ public boolean onCreateOptionsMenu(Menu menu) { } Global.setTint(menu.findItem(R.id.open_browser).getIcon()); Global.setTint(menu.findItem(R.id.by_popular).getIcon()); - searchView =(SearchView)menu.findItem(R.id.search).getActionView(); if(related!=-1){ menu.findItem(R.id.search).setVisible(false); return true; } - searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + menu.findItem(R.id.search).setActionView(null); + /*searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { if(query.length()==0)return true; @@ -352,12 +337,25 @@ public boolean onQueryTextSubmit(String query) { public boolean onQueryTextChange(String newText) { return true; } - }); - ImageView closeButton = searchView.findViewById(R.id.search_close_btn); - closeButton.setOnClickListener(v -> removeQuery()); + });*/ return true; } + private void showLanguageIcon(MenuItem item) { + if(Global.getOnlyLanguage()==null){ + item.setTitle(R.string.all_languages);item.setIcon(R.drawable.ic_world); + + } + else + switch (Global.getOnlyLanguage()){ + case JAPANESE:item.setTitle(R.string.only_japanese);item.setIcon(R.drawable.ic_jpbw);break; + case CHINESE:item.setTitle(R.string.only_chinese);item.setIcon(R.drawable.ic_cnbw);break; + case UNKNOWN:item.setTitle(R.string.only_other);item.setIcon(R.drawable.ic_help);break; + case ENGLISH:item.setTitle(R.string.only_english);item.setIcon(R.drawable.ic_gbbw);break; + } + Global.setTint(item.getIcon()); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will @@ -371,7 +369,11 @@ public boolean onOptionsItemSelected(MenuItem item) { item.setTitle(Global.isByPopular()?R.string.sort_by_popular:R.string.sort_by_latest); Global.setTint(item.getIcon()); new Inspector(this,1,Inspector.getActualQuery(),Inspector.getActualRequestType());break; - case R.id.only_language:updateLanguageIcon(item,true);break; + case R.id.only_language:updateLanguageIcon(item);showLanguageIcon(item); break; + case R.id.search: + i=new Intent(this,SearchActivity.class); + startActivityForResult(i,1); + break; case R.id.open_browser: if(inspector!=null) { i = new Intent(Intent.ACTION_VIEW); @@ -393,6 +395,29 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if(requestCode==1&&resultCode== Activity.RESULT_OK){ + manageQuery(data.getStringExtra("query")); + } + super.onActivityResult(requestCode, resultCode, data); + } + private void manageQuery(String query){ + if(query.length()==0)return; + try { + if (tag == null && related == -1) { + int id=Integer.parseInt(query); + if(id>0&&id<=Global.getMaxId()){ + new Inspector(MainActivity.this, -1, "" + id, ApiRequestType.BYSINGLE); + return; + } + } + }catch (NumberFormatException ignore){} + query=query.trim(); + getSupportActionBar().setTitle(query+(tag!=null?' '+tag.getName():"")); + new Inspector(MainActivity.this,1,query+(tag!=null?(' '+tag.toQueryTag(TagStatus.DEFAULT)):""),ApiRequestType.BYSEARCH); + } + private void showLogoutForm() { AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setIcon(R.drawable.ic_exit_to_app).setTitle(R.string.logout).setMessage(R.string.are_you_sure); @@ -420,6 +445,10 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) { startActivity(intent); } break; + case R.id.search: + intent=new Intent(this,SearchActivity.class); + startActivity(intent); + break; case R.id.favorite_manager: intent=new Intent(this,FavoriteActivity.class); startActivity(intent); diff --git a/app/src/main/java/com/dar/nclientv2/SearchActivity.java b/app/src/main/java/com/dar/nclientv2/SearchActivity.java new file mode 100644 index 00000000..af0c2224 --- /dev/null +++ b/app/src/main/java/com/dar/nclientv2/SearchActivity.java @@ -0,0 +1,101 @@ +package com.dar.nclientv2; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.SearchView; +import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; + +import com.dar.nclientv2.adapters.HistoryAdapter; +import com.dar.nclientv2.components.History; +import com.dar.nclientv2.settings.Global; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SearchActivity extends AppCompatActivity { + @NonNull private SharedPreferences preferences; + private Listhistory=new ArrayList<>(); + private SearchView searchView; + private RecyclerView recyclerView; + private HistoryAdapter adapter; + public void setQuery(String str,boolean submit){ + runOnUiThread(() -> searchView.setQuery(str,submit)); + } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Global.loadTheme(this); + Global.initKeepHistory(this); + setContentView(R.layout.activity_search); + Toolbar toolbar=findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowTitleEnabled(false); + searchView=findViewById(R.id.search); + adapter=new HistoryAdapter(this); + recyclerView=findViewById(R.id.recycler); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(adapter); + recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL)); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + adapter.addHistory(query); + Intent returnIntent = new Intent(); + returnIntent.putExtra("query",query); + setResult(Activity.RESULT_OK,returnIntent); + finish(); + return true; + } + + @Override + public boolean onQueryTextChange(String newText) { + return false; + } + }); + searchView.requestFocus(); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.search, menu); + Global.setTint(menu.findItem(R.id.search).getIcon()); + //searchView=(SearchView) menu.findItem(R.id.search).getActionView(); + //searchView.setIconifiedByDefault(false); + //searchView.setIconified(false); + return super.onCreateOptionsMenu(menu); + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()){ + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + +} diff --git a/app/src/main/java/com/dar/nclientv2/adapters/HistoryAdapter.java b/app/src/main/java/com/dar/nclientv2/adapters/HistoryAdapter.java new file mode 100644 index 00000000..8586c650 --- /dev/null +++ b/app/src/main/java/com/dar/nclientv2/adapters/HistoryAdapter.java @@ -0,0 +1,100 @@ +package com.dar.nclientv2.adapters; + +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.TextView; + +import com.dar.nclientv2.R; +import com.dar.nclientv2.SearchActivity; +import com.dar.nclientv2.components.History; +import com.dar.nclientv2.settings.Global; + +import java.util.HashSet; +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.RecyclerView; + +public class HistoryAdapter extends RecyclerView.Adapter { + private List history; + private SearchActivity context; + + public HistoryAdapter(SearchActivity context) { + this.context = context; + if(!Global.isKeepHistory())context.getSharedPreferences("History",0).edit().clear().apply(); + history=Global.isKeepHistory()?History.setToList(context.getSharedPreferences("History",0).getStringSet("history",new HashSet<>())):null; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new HistoryAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.entry_history, parent, false)); + } + int remove=-1; + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + Global.loadImage(remove==holder.getAdapterPosition()?R.drawable.ic_close:R.drawable.ic_mode_edit,holder.imageButton); + String entry=history.get(holder.getAdapterPosition()).getValue(); + holder.text.setText(entry); + holder.master.setOnClickListener(v -> context.setQuery(entry,true)); + holder.imageButton.setOnLongClickListener(v -> { + context.runOnUiThread(() -> { + if(remove==holder.getAdapterPosition()){ + remove=-1; + notifyItemChanged(holder.getAdapterPosition()); + }else{ + if(remove!=-1){ + int l=remove; + remove=-1; + notifyItemChanged(l); + } + remove=holder.getAdapterPosition(); + notifyItemChanged(holder.getAdapterPosition()); + } + }); + return true; + }); + holder.imageButton.setOnClickListener(v -> { + if(remove==holder.getAdapterPosition()){ + removeHistory(remove); + remove=-1; + }else{ + context.setQuery(entry,false); + } + }); + } + + @Override + public int getItemCount() { + return history==null?0:history.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + ConstraintLayout master; + TextView text; + ImageButton imageButton; + public ViewHolder(@NonNull View itemView) { + super(itemView); + this.master=itemView.findViewById(R.id.master_layout); + this.text=itemView.findViewById(R.id.text); + this.imageButton=itemView.findViewById(R.id.edit); + } + } + public void addHistory(String value){ + if(!Global.isKeepHistory())return; + History history=new History(value,false); + int pos=this.history.indexOf(history); + if(pos>=0)this.history.set(pos,history); + else this.history.add(history); + context.getSharedPreferences("History",0).edit().putStringSet("history",History.listToSet(this.history)).apply(); + } + public void removeHistory(int pos){ + history.remove(pos); + context.getSharedPreferences("History",0).edit().putStringSet("history",History.listToSet(this.history)).apply(); + context.runOnUiThread(() -> notifyItemRemoved(pos)); + } +} diff --git a/app/src/main/java/com/dar/nclientv2/api/Inspector.java b/app/src/main/java/com/dar/nclientv2/api/Inspector.java index ece95877..cd526f21 100644 --- a/app/src/main/java/com/dar/nclientv2/api/Inspector.java +++ b/app/src/main/java/com/dar/nclientv2/api/Inspector.java @@ -133,7 +133,7 @@ public void onResponse(@NonNull Call call,@NonNull Response response) throws IOE intent.putExtra(activity.getPackageName()+".GALLERY",galleries.get(0)); intent.putExtra(activity.getPackageName()+".ZOOM",page-1); activity.startActivity(intent); - activity.getRefresher().setEnabled(false); + if(activity instanceof GalleryActivity)activity.getRefresher().setEnabled(false); if(page!=-1)activity.finish(); } activity.getRefresher().setRefreshing(false); diff --git a/app/src/main/java/com/dar/nclientv2/async/VersionChecker.java b/app/src/main/java/com/dar/nclientv2/async/VersionChecker.java index 1e2defd5..936b81e0 100644 --- a/app/src/main/java/com/dar/nclientv2/async/VersionChecker.java +++ b/app/src/main/java/com/dar/nclientv2/async/VersionChecker.java @@ -33,6 +33,7 @@ public VersionChecker(Activity context,final boolean silent){ @Override public void onFailure(@NonNull Call call,@NonNull IOException e){ context.runOnUiThread(()->{ + Log.e(Global.LOGTAG,e.getLocalizedMessage(),e); if(!silent) Toast.makeText(context, R.string.error_retrieving, Toast.LENGTH_SHORT).show(); }); } diff --git a/app/src/main/java/com/dar/nclientv2/async/scrape/TagPageScraper.java b/app/src/main/java/com/dar/nclientv2/async/scrape/TagPageScraper.java index 7daced74..865c5ed8 100644 --- a/app/src/main/java/com/dar/nclientv2/async/scrape/TagPageScraper.java +++ b/app/src/main/java/com/dar/nclientv2/async/scrape/TagPageScraper.java @@ -22,7 +22,7 @@ class TagPageScraper extends Thread{ private final TagScrapeStatus status; - public static final int MIN_TAG_COUNT=5; + public static final int MIN_TAG_COUNT=2; private int minReached=99999; private boolean showed=false; diff --git a/app/src/main/java/com/dar/nclientv2/components/CustomSSLSocketFactory.java b/app/src/main/java/com/dar/nclientv2/components/CustomSSLSocketFactory.java new file mode 100644 index 00000000..3d4b9175 --- /dev/null +++ b/app/src/main/java/com/dar/nclientv2/components/CustomSSLSocketFactory.java @@ -0,0 +1,98 @@ +package com.dar.nclientv2.components; + +import android.os.Build; +import android.util.Log; + +import com.dar.nclientv2.settings.Global; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +import okhttp3.ConnectionSpec; +import okhttp3.OkHttpClient; +import okhttp3.TlsVersion; + +public class CustomSSLSocketFactory extends SSLSocketFactory { + private static final String[] TLS_V12_ONLY = {"TLSv1.2"}; + + final SSLSocketFactory delegate; + + public CustomSSLSocketFactory(SSLSocketFactory base) { + this.delegate = base; + } + + @Override + public String[] getDefaultCipherSuites() { + return delegate.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return delegate.getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + return patch(delegate.createSocket(s, host, port, autoClose)); + } + + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + return patch(delegate.createSocket(host, port)); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + return patch(delegate.createSocket(host, port, localHost, localPort)); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + return patch(delegate.createSocket(host, port)); + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return patch(delegate.createSocket(address, port, localAddress, localPort)); + } + + private Socket patch(Socket s) { + if (s instanceof SSLSocket) { + ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY); + } + return s; + } + public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) { + if (Build.VERSION.SDK_INT>=16&&Build.VERSION.SDK_INT < 22) { + try { + SSLContext sc = SSLContext.getInstance("TLSv1.2"); + sc.init(null, null, null); + client.sslSocketFactory(new CustomSSLSocketFactory(sc.getSocketFactory())); + + ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build(); + + List specs = new ArrayList<>(); + specs.add(cs); + specs.add(ConnectionSpec.COMPATIBLE_TLS); + specs.add(ConnectionSpec.CLEARTEXT); + + client.connectionSpecs(specs); + } catch (Exception exc) { + Log.e(Global.LOGTAG, "Error while setting TLS 1.2", exc); + } + } + + return client; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dar/nclientv2/components/CustomSwipe.java b/app/src/main/java/com/dar/nclientv2/components/CustomSwipe.java new file mode 100644 index 00000000..bdf14bbc --- /dev/null +++ b/app/src/main/java/com/dar/nclientv2/components/CustomSwipe.java @@ -0,0 +1,31 @@ +package com.dar.nclientv2.components; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import com.dar.nclientv2.settings.Global; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +public class CustomSwipe extends SwipeRefreshLayout { + public CustomSwipe(@NonNull Context context) { + super(context); + } + + public CustomSwipe(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void setEnabled(boolean refreshing) { + try{ + throw new Exception(); + }catch (Exception e){ + Log.e(Global.LOGTAG,"NEW VALUE: "+refreshing+",,"+e.getLocalizedMessage(),e); + } + super.setRefreshing(refreshing); + } +} diff --git a/app/src/main/java/com/dar/nclientv2/components/History.java b/app/src/main/java/com/dar/nclientv2/components/History.java new file mode 100644 index 00000000..e3fffa1d --- /dev/null +++ b/app/src/main/java/com/dar/nclientv2/components/History.java @@ -0,0 +1,63 @@ +package com.dar.nclientv2.components; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class History{ + final String value; + final Date date; + + public History(String value,boolean set) { + if(set){ + int p=value.indexOf('|'); + date=new Date(Long.parseLong(value.substring(0,p))); + this.value=value.substring(p+1); + }else { + this.value = value; + this.date = new Date(); + } + } + public static List setToList(Set set){ + Listh=new ArrayList<>(set.size()); + for(String s:set)h.add(new History(s,true)); + Collections.sort(h, new Comparator() { + @Override + public int compare(History o2, History o1) { + int o=o1.date.compareTo(o2.date); + if(o==0)o=o1.value.compareTo(o2.value); + return o; + } + }); + + return h; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + History history = (History) o; + return value.equals(history.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + public static SetlistToSet(Listlist){ + HashSets=new HashSet<>(list.size()); + for (History h:list)s.add(h.date.getTime()+"|"+h.value); + return s; + } +} diff --git a/app/src/main/java/com/dar/nclientv2/settings/Global.java b/app/src/main/java/com/dar/nclientv2/settings/Global.java index fb780ba6..34ea5efa 100644 --- a/app/src/main/java/com/dar/nclientv2/settings/Global.java +++ b/app/src/main/java/com/dar/nclientv2/settings/Global.java @@ -21,6 +21,7 @@ import com.dar.nclientv2.api.components.GenericGallery; import com.dar.nclientv2.api.enums.Language; import com.dar.nclientv2.api.enums.TitleType; +import com.dar.nclientv2.components.CustomSSLSocketFactory; import com.dar.nclientv2.loginapi.LoadTags; import com.dar.nclientv2.loginapi.User; import com.franmontiel.persistentcookiejar.PersistentCookieJar; @@ -61,7 +62,7 @@ public enum ThemeScheme{LIGHT,DARK,BLACK} public static final String CHANNEL_ID1="download_gallery",CHANNEL_ID2="create_pdf"; private static Language onlyLanguage=null; private static TitleType titleType; - private static boolean byPopular,loadImages,hideFromGallery,highRes,onlyTag,infiniteScroll,removeIgnoredGalleries; + private static boolean byPopular,keepHistory,loadImages,hideFromGallery,highRes,onlyTag,infiniteScroll,removeIgnoredGalleries; private static ThemeScheme theme; private static int notificationId,columnCount,maxId,imageQuality,galleryWidth=-1, galleryHeight =-1; @@ -91,6 +92,7 @@ public static void initTitleType(@NonNull Context context){ } } public static void initByPopular (@NonNull Context context){byPopular=context.getSharedPreferences("Settings", 0).getBoolean(context.getString(R.string.key_by_popular),false);} + public static void initKeepHistory (@NonNull Context context){keepHistory=context.getSharedPreferences("Settings", 0).getBoolean(context.getString(R.string.key_keep_history),true);} public static void initInfiniteScroll (@NonNull Context context){infiniteScroll=context.getSharedPreferences("Settings", 0).getBoolean(context.getString(R.string.key_infinite_scroll),false);} public static void initHideFromGallery (@NonNull Context context){hideFromGallery=context.getSharedPreferences("Settings", 0).getBoolean(context.getString(R.string.key_hide_saved_images),false);} public static void initHighRes (@NonNull Context context){highRes=context.getSharedPreferences("Settings", 0).getBoolean(context.getString(R.string.key_high_res_gallery),true);} @@ -104,9 +106,12 @@ public static void initTitleType(@NonNull Context context){ public static void initHttpClient(@NonNull Context context){ if(client!=null)return; - client=new OkHttpClient.Builder() - .cookieJar(new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context.getSharedPreferences("Login",0)))) - .build(); + OkHttpClient.Builder builder=new OkHttpClient.Builder() + .cookieJar(new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context.getSharedPreferences("Login",0)))); + + CustomSSLSocketFactory.enableTls12OnPreLollipop(builder); + client=builder.build(); + client.dispatcher().setMaxRequests(25); client.dispatcher().setMaxRequestsPerHost(25); if(Login.isLogged()&&Login.getUser()==null){ @@ -151,6 +156,11 @@ public static boolean isHighRes() { public static boolean isOnlyTag() { return onlyTag; } + + public static boolean isKeepHistory() { + return keepHistory; + } + public static boolean isByPopular() { return byPopular; } diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 00000000..0258249c --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_mode_edit.xml b/app/src/main/res/drawable/ic_mode_edit.xml new file mode 100644 index 00000000..2ab2fb75 --- /dev/null +++ b/app/src/main/res/drawable/ic_mode_edit.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml new file mode 100644 index 00000000..e398aa2a --- /dev/null +++ b/app/src/main/res/layout/activity_search.xml @@ -0,0 +1,34 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/entry_history.xml b/app/src/main/res/layout/entry_history.xml new file mode 100644 index 00000000..249ea8f2 --- /dev/null +++ b/app/src/main/res/layout/entry_history.xml @@ -0,0 +1,46 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/search.xml b/app/src/main/res/menu/search.xml new file mode 100644 index 00000000..b0f86161 --- /dev/null +++ b/app/src/main/res/menu/search.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5696672e..602b7779 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -81,7 +81,6 @@ You can have a maximum of %d selected tags. - Filters Only english Only japanese @@ -165,8 +164,6 @@ 999/999 - - Share with Link copied to clipboard Open in browser @@ -222,6 +219,12 @@ Cache size: %.2f MB Cache cleared Sort by latest + Edit + Options + keep_history + The searches will be stored + The searched will not be stored + Keep search history diff --git a/app/src/main/res/xml/backup_content.xml b/app/src/main/res/xml/backup_content.xml index 8f34a4f4..ace05e3f 100644 --- a/app/src/main/res/xml/backup_content.xml +++ b/app/src/main/res/xml/backup_content.xml @@ -5,6 +5,4 @@ ./adb shell bmgr restore com.dar.nclientv2 --> - - \ No newline at end of file diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index aa501123..ee5da47e 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -51,6 +51,12 @@ android:summaryOn="@string/setting_on_infinite_scroll" android:summaryOff="@string/setting_off_infinite_scroll" android:title="@string/infinite_scroll" /> +