From 197b3fcf8aa4281a0fdf540cdfb02738c6dc84e5 Mon Sep 17 00:00:00 2001 From: tom79 Date: Sat, 13 Jul 2019 12:20:41 +0200 Subject: [PATCH] Export muted instances and share them with comments --- app/src/main/AndroidManifest.xml | 5 + .../android/activities/BaseMainActivity.java | 10 +- .../activities/MutedInstanceActivity.java | 397 ++++++++++++++++++ .../android/client/Entities/Status.java | 2 +- .../app/fedilab/android/helper/Helper.java | 243 +++++++++++ .../app/fedilab/android/sqlite/Sqlite.java | 5 +- .../res/layout/activity_muted_instances.xml | 81 ++++ .../res/layout/fragment_muted_instances.xml | 2 +- .../main/res/layout/muted_instance_popup.xml | 22 + .../res/layout/simple_bar_muted_instance.xml | 70 +++ .../main/res/menu/option_muted_instance.xml | 16 + app/src/main/res/values/strings.xml | 5 + 12 files changed, 849 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/app/fedilab/android/activities/MutedInstanceActivity.java create mode 100644 app/src/main/res/layout/activity_muted_instances.xml create mode 100644 app/src/main/res/layout/muted_instance_popup.xml create mode 100644 app/src/main/res/layout/simple_bar_muted_instance.xml create mode 100644 app/src/main/res/menu/option_muted_instance.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7818022ea..f00c93627 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -314,6 +314,11 @@ android:configChanges="orientation|screenSize" android:label="@string/app_name" /> + . */ +package app.fedilab.android.activities; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.database.sqlite.SQLiteDatabase; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.PopupMenu; +import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import app.fedilab.android.R; +import app.fedilab.android.asynctasks.PostActionAsyncTask; +import app.fedilab.android.asynctasks.RetrieveDomainsAsyncTask; +import app.fedilab.android.client.API; +import app.fedilab.android.client.APIResponse; +import app.fedilab.android.client.Entities.Account; +import app.fedilab.android.client.Entities.Error; +import app.fedilab.android.drawers.DomainsListAdapter; +import app.fedilab.android.helper.Helper; +import app.fedilab.android.interfaces.OnPostActionInterface; +import app.fedilab.android.interfaces.OnRetrieveDomainsInterface; +import app.fedilab.android.sqlite.AccountDAO; +import app.fedilab.android.sqlite.Sqlite; +import es.dmoral.toasty.Toasty; + + +/** + * Created by Thomas on 13/07/2019. + * Muted instances activity + */ + +public class MutedInstanceActivity extends BaseActivity implements OnRetrieveDomainsInterface, OnPostActionInterface { + + private boolean flag_loading; + private AsyncTask asyncTask; + private DomainsListAdapter domainsListAdapter; + private String max_id; + private List domains; + private RelativeLayout mainLoader, nextElementLoader, textviewNoAction; + private boolean firstLoad; + private SwipeRefreshLayout swipeRefreshLayout; + private boolean swiped; + private RecyclerView lv_domains; + private final int PICK_IMPORT_INSTANCE = 5326; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + switch (theme){ + case Helper.THEME_LIGHT: + setTheme(R.style.AppTheme); + break; + case Helper.THEME_DARK: + setTheme(R.style.AppThemeDark); + break; + case Helper.THEME_BLACK: + setTheme(R.style.AppThemeBlack); + break; + default: + setTheme(R.style.AppThemeDark); + } + if( getSupportActionBar() != null) + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + ActionBar actionBar = getSupportActionBar(); + if( actionBar != null ) { + LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); + assert inflater != null; + @SuppressLint("InflateParams") View view = inflater.inflate(R.layout.simple_bar_muted_instance, null); + actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); + ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close); + TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title); + ImageView option = actionBar.getCustomView().findViewById(R.id.option); + toolbar_close.setOnClickListener(v -> finish()); + option.setOnClickListener(v -> { + PopupMenu popup = new PopupMenu(MutedInstanceActivity.this, option); + popup.getMenuInflater() + .inflate(R.menu.option_muted_instance, popup.getMenu()); + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_add_instances: + final SharedPreferences sharedpreferences1 = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + int theme1 = sharedpreferences1.getInt(Helper.SET_THEME, Helper.THEME_DARK); + int style; + if (theme1 == Helper.THEME_DARK) { + style = R.style.DialogDark; + } else if (theme1 == Helper.THEME_BLACK){ + style = R.style.DialogBlack; + }else { + style = R.style.Dialog; + } + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MutedInstanceActivity.this, style); + LayoutInflater inflater = getLayoutInflater(); + @SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.add_blocked_instance, null); + dialogBuilder.setView(dialogView); + + EditText add_domain = dialogView.findViewById(R.id.add_domain); + dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + if(add_domain.getText() != null && add_domain.getText().toString().trim().matches("^[\\da-zA-Z.-]+\\.[a-zA-Z.]{2,10}$")){ + new PostActionAsyncTask(MutedInstanceActivity.this, API.StatusAction.BLOCK_DOMAIN, add_domain.getText().toString().trim(), MutedInstanceActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + dialog.dismiss(); + }else{ + Toasty.error(MutedInstanceActivity.this, getString(R.string.toast_empty_content)).show(); + } + } + }); + dialogBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + AlertDialog alertDialog = dialogBuilder.create(); + alertDialog.setTitle(getString(R.string.block_domain)); + if( alertDialog.getWindow() != null ) + alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + alertDialog.show(); + break; + case R.id.action_export_instances: + SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(getApplicationContext())); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + Account account = new AccountDAO(getApplicationContext(), db).getUniqAccount(userId, instance); + Helper.exportInstanceBlock(MutedInstanceActivity.this,account.getAcct()+"_"+account.getInstance()); + break; + case R.id.action_import_instances: + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (ContextCompat.checkSelfPermission(MutedInstanceActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != + PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(MutedInstanceActivity.this, + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + TootActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); + return true; + } + } + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + intent.setType("*/*"); + String[] mimetypes = {"*/*"}; + intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes); + startActivityForResult(intent, PICK_IMPORT_INSTANCE); + }else { + intent.setType("*/*"); + Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); + Intent chooserIntent = Intent.createChooser(intent, getString(R.string.toot_select_import)); + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent}); + startActivityForResult(chooserIntent, PICK_IMPORT_INSTANCE); + } + break; + } + return true; + }}); + popup.show(); + }); + toolbar_title.setText(R.string.blocked_domains); + if (theme == Helper.THEME_LIGHT){ + Toolbar toolbar = actionBar.getCustomView().findViewById(R.id.toolbar); + Helper.colorizeToolbar(toolbar, R.color.black, MutedInstanceActivity.this); + } + } + setContentView(R.layout.activity_muted_instances); + + domains = new ArrayList<>(); + max_id = null; + firstLoad = true; + flag_loading = true; + swiped = false; + + swipeRefreshLayout = findViewById(R.id.swipeContainer); + lv_domains = findViewById(R.id.lv_domains); + lv_domains.addItemDecoration(new DividerItemDecoration(MutedInstanceActivity.this, DividerItemDecoration.VERTICAL)); + mainLoader = findViewById(R.id.loader); + nextElementLoader = findViewById(R.id.loading_next_domains); + textviewNoAction = findViewById(R.id.no_action); + mainLoader.setVisibility(View.VISIBLE); + nextElementLoader.setVisibility(View.GONE); + domainsListAdapter = new DomainsListAdapter(MutedInstanceActivity.this, this.domains, textviewNoAction); + lv_domains.setAdapter(domainsListAdapter); + + final LinearLayoutManager mLayoutManager; + mLayoutManager = new LinearLayoutManager(MutedInstanceActivity.this); + lv_domains.setLayoutManager(mLayoutManager); + lv_domains.addOnScrollListener(new RecyclerView.OnScrollListener() { + public void onScrolled(@NotNull RecyclerView recyclerView, int dx, int dy) + { + if(dy > 0) { + int visibleItemCount = mLayoutManager.getChildCount(); + int totalItemCount = mLayoutManager.getItemCount(); + int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); + if (firstVisibleItem + visibleItemCount == totalItemCount) { + if (!flag_loading) { + flag_loading = true; + asyncTask = new RetrieveDomainsAsyncTask(MutedInstanceActivity.this, max_id, MutedInstanceActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); nextElementLoader.setVisibility(View.VISIBLE); + } + } else { + nextElementLoader.setVisibility(View.GONE); + } + } + } + }); + swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + max_id = null; + domains = new ArrayList<>(); + firstLoad = true; + flag_loading = true; + swiped = true; + asyncTask = new RetrieveDomainsAsyncTask(MutedInstanceActivity.this, max_id, MutedInstanceActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + }); + switch (theme){ + case Helper.THEME_LIGHT: + swipeRefreshLayout.setColorSchemeResources(R.color.mastodonC4, + R.color.mastodonC2, + R.color.mastodonC3); + swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(MutedInstanceActivity.this, R.color.white)); + break; + case Helper.THEME_DARK: + swipeRefreshLayout.setColorSchemeResources(R.color.mastodonC4__, + R.color.mastodonC4, + R.color.mastodonC4); + swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(MutedInstanceActivity.this, R.color.mastodonC1_)); + break; + case Helper.THEME_BLACK: + swipeRefreshLayout.setColorSchemeResources(R.color.dark_icon, + R.color.mastodonC2, + R.color.mastodonC3); + swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(MutedInstanceActivity.this, R.color.black_3)); + break; + } + + asyncTask = new RetrieveDomainsAsyncTask(MutedInstanceActivity.this, max_id, MutedInstanceActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + + setTitle(R.string.blocked_domains); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if(asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING) + asyncTask.cancel(true); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onRetrieveDomains(APIResponse apiResponse) { + mainLoader.setVisibility(View.GONE); + nextElementLoader.setVisibility(View.GONE); + if( apiResponse.getError() != null){ + Toasty.error(MutedInstanceActivity.this, apiResponse.getError().getError(),Toast.LENGTH_LONG).show(); + swipeRefreshLayout.setRefreshing(false); + swiped = false; + flag_loading = false; + return; + } + flag_loading = (apiResponse.getMax_id() == null ); + List domains = apiResponse.getDomains(); + if( !swiped && firstLoad && (domains == null || domains.size() == 0)) + textviewNoAction.setVisibility(View.VISIBLE); + else + textviewNoAction.setVisibility(View.GONE); + max_id = apiResponse.getMax_id(); + if( swiped ){ + domainsListAdapter = new DomainsListAdapter(MutedInstanceActivity.this, this.domains, textviewNoAction); + lv_domains.setAdapter(domainsListAdapter); + swiped = false; + } + if( domains != null && domains.size() > 0) { + this.domains.addAll(domains); + domainsListAdapter.notifyDataSetChanged(); + } + swipeRefreshLayout.setRefreshing(false); + firstLoad = false; + } + + @Override + public void onRetrieveDomainsDeleted(int response) { + + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == PICK_IMPORT_INSTANCE && resultCode == RESULT_OK) { + if (data == null || data.getData() == null) { + Toasty.error(getApplicationContext(),getString(R.string.toot_select_file_error),Toast.LENGTH_LONG).show(); + return; + } + try { + InputStream is = getContentResolver().openInputStream(data.getData()); + HashMap resultList = new HashMap<>(); + BufferedReader reader = new BufferedReader(new InputStreamReader( is)); + String csvLine; + while ((csvLine = reader.readLine()) != null) { + String[] row = csvLine.split(","); + if( row.length > 1) { + if( !row[0].equals("INSTANCE")) + resultList.put(row[0], row[1]); + }else if(row.length == 1){ + if( !row[0].equals("INSTANCE")) + resultList.put(row[0], ""); + } + } + Helper.importInstanceBlock(MutedInstanceActivity.this,resultList); + } catch (Exception e) { + Toasty.error(MutedInstanceActivity.this, getString(R.string.toast_error), Toast.LENGTH_SHORT).show(); + } + + + } + } + + @Override + public void onPostAction(int statusCode, API.StatusAction statusAction, String userId, Error error) { + if( error != null){ + Toasty.error(MutedInstanceActivity.this, error.getError(),Toast.LENGTH_LONG).show(); + return; + } + Helper.manageMessageStatusCode(MutedInstanceActivity.this, statusCode, statusAction); + this.domains.add(0,userId); + domainsListAdapter.notifyItemInserted(0); + if( this.domains.size() > 0){ + textviewNoAction.setVisibility(View.GONE); + } + } + +} diff --git a/app/src/main/java/app/fedilab/android/client/Entities/Status.java b/app/src/main/java/app/fedilab/android/client/Entities/Status.java index 10acedbeb..1b1e10e73 100644 --- a/app/src/main/java/app/fedilab/android/client/Entities/Status.java +++ b/app/src/main/java/app/fedilab/android/client/Entities/Status.java @@ -602,7 +602,7 @@ public class Status implements Parcelable{ urlText += "|"+count; count++; } - content = content.replaceFirst(beforemodification, urlText); + content = content.replaceFirst(Pattern.quote(beforemodification), urlText); } } spannableStringContent = new SpannableString(content); diff --git a/app/src/main/java/app/fedilab/android/helper/Helper.java b/app/src/main/java/app/fedilab/android/helper/Helper.java index 69f45f016..857ba4dfc 100644 --- a/app/src/main/java/app/fedilab/android/helper/Helper.java +++ b/app/src/main/java/app/fedilab/android/helper/Helper.java @@ -24,6 +24,7 @@ import android.app.FragmentManager; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.ProgressDialog; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; @@ -55,6 +56,8 @@ import android.os.Build; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Environment; +import android.os.Handler; +import android.os.Message; import android.provider.MediaStore; import android.provider.OpenableColumns; import androidx.annotation.NonNull; @@ -71,16 +74,20 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.view.menu.ActionMenuItemView; import androidx.appcompat.widget.ActionMenuView; import androidx.appcompat.widget.Toolbar; + +import android.text.Editable; import android.text.Html; import android.text.SpannableString; import android.text.Spanned; import android.text.TextPaint; import android.text.TextUtils; +import android.text.TextWatcher; import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.util.DisplayMetrics; import android.util.Log; import android.util.Patterns; +import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -95,9 +102,13 @@ import android.webkit.URLUtil; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; @@ -141,6 +152,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -159,6 +171,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -172,20 +185,27 @@ import java.util.regex.Pattern; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; +import app.fedilab.android.activities.MutedInstanceActivity; +import app.fedilab.android.asynctasks.PostActionAsyncTask; import app.fedilab.android.client.API; +import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Application; import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Card; import app.fedilab.android.client.Entities.Emojis; import app.fedilab.android.client.Entities.Filters; +import app.fedilab.android.client.Entities.ManageTimelines; import app.fedilab.android.client.Entities.Mention; import app.fedilab.android.client.Entities.RemoteInstance; +import app.fedilab.android.client.Entities.Results; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.Entities.Tag; import app.fedilab.android.client.Entities.TagTimeline; import app.fedilab.android.client.Entities.Version; import app.fedilab.android.client.Tls12SocketFactory; +import app.fedilab.android.fragments.DisplayMutedInstanceFragment; +import app.fedilab.android.sqlite.DomainBlockDAO; import es.dmoral.toasty.Toasty; import app.fedilab.android.BuildConfig; import app.fedilab.android.R; @@ -4100,4 +4120,227 @@ public class Helper { return client; } + + + public static void exportInstanceBlock(Context context, String username){ + + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date()); + String backupDBPath = "instance_mute_"+timeStamp+".csv"; + File sd = Environment.getExternalStorageDirectory(); + final String filename = sd + "/" + backupDBPath; + + + new AsyncTask>() { + private WeakReference contextReference = new WeakReference<>(context); + APIResponse apiResponse; + + @Override + protected void onPreExecute() { + } + + @Override + protected List doInBackground(Void... voids) { + apiResponse = new API(contextReference.get()).getBlockedDomain(null); + return apiResponse.getDomains(); + } + @Override + protected void onPostExecute( List domains) { + if( domains == null){ + return; + } + final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + int style; + if (theme == Helper.THEME_DARK) { + style = R.style.DialogDark; + } else if (theme == Helper.THEME_BLACK){ + style = R.style.DialogBlack; + }else { + style = R.style.Dialog; + } + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context, style); + LayoutInflater inflater = ((MutedInstanceActivity)context).getLayoutInflater(); + ScrollView scrollView = new ScrollView(context); + LinearLayout linearLayout_main = new LinearLayout(context); + + linearLayout_main.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); + linearLayout_main.setOrientation(LinearLayout.VERTICAL); + + for(String domain: domains){ + @SuppressLint("InflateParams") View item = inflater.inflate(R.layout.muted_instance_popup, null); + CheckBox checkBox = item.findViewById(R.id.popup_domain); + checkBox.setText(domain); + linearLayout_main.addView(item); + } + scrollView.addView(linearLayout_main); + dialogBuilder.setView(scrollView); + HashMap domainBlocked = new HashMap<>(); + dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + for( int i = 0; i < linearLayout_main.getChildCount() ; i++){ + LinearLayout linearLayout = (LinearLayout) linearLayout_main.getChildAt(i); + CheckBox checkBox = linearLayout.findViewById(R.id.popup_domain); + EditText editText = linearLayout.findViewById(R.id.popup_comment); + if( checkBox.isChecked()){ + String comment = null; + String domain = checkBox.getText().toString().trim(); + if( editText.getText() != null) { + comment = editText.getText().toString().trim(); + } + domainBlocked.put(domain, comment); + } + } + if( domainBlocked.size() > 0 ){ + new Thread() { + public void run() { + try { + + FileWriter fw = new FileWriter(filename); + fw.append("INSTANCE"); + fw.append(','); + fw.append("COMMENT"); + fw.append('\n'); + Iterator it = domainBlocked.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry)it.next(); + fw.append((String)pair.getKey()); + fw.append(','); + fw.append((String)pair.getValue()); + fw.append('\n'); + it.remove(); + } + fw.close(); + } catch (Exception ignored) { + } + final Intent intent = new Intent(); + Random r = new Random(); + final int notificationIdTmp = r.nextInt(10000); + intent.setAction(android.content.Intent.ACTION_VIEW); + Uri uri = Uri.fromFile(new File(filename)); + intent.setDataAndType(uri, "text/csv"); + Helper.notify_user(context, intent, notificationIdTmp, BitmapFactory.decodeResource(context.getResources(), + R.mipmap.ic_launcher), Helper.NotifType.STORE, context.getString(R.string.muted_instance_exported), context.getString(R.string.download_from, backupDBPath)); + } + }.start(); + } + dialog.dismiss(); + } + }); + dialogBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + AlertDialog alertDialog = dialogBuilder.create(); + alertDialog.show(); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR ); + } + + + + public static void importInstanceBlock(Context context, HashMap instances){ + + + final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + int style; + if (theme == Helper.THEME_DARK) { + style = R.style.DialogDark; + } else if (theme == Helper.THEME_BLACK){ + style = R.style.DialogBlack; + }else { + style = R.style.Dialog; + } + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context, style); + LayoutInflater inflater = ((MutedInstanceActivity)context).getLayoutInflater(); + ScrollView scrollView = new ScrollView(context); + LinearLayout linearLayout_main = new LinearLayout(context); + + linearLayout_main.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); + linearLayout_main.setOrientation(LinearLayout.VERTICAL); + Iterator it = instances.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry)it.next(); + @SuppressLint("InflateParams") View item = inflater.inflate(R.layout.muted_instance_popup, null); + CheckBox checkBox = item.findViewById(R.id.popup_domain); + checkBox.setText(pair.getKey().toString().trim()); + item.findViewById(R.id.popup_comment).setVisibility(View.GONE); + if( pair.getValue() != null) { + TextView textView = item.findViewById(R.id.comment_text); + textView.setText(pair.getValue().toString()); + textView.setVisibility(View.VISIBLE); + } + linearLayout_main.addView(item); + it.remove(); + } + scrollView.addView(linearLayout_main); + dialogBuilder.setView(scrollView); + HashMap domainBlocked = new HashMap<>(); + dialogBuilder.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + for( int i = 0; i < linearLayout_main.getChildCount() ; i++){ + LinearLayout linearLayout = (LinearLayout) linearLayout_main.getChildAt(i); + CheckBox checkBox = linearLayout.findViewById(R.id.popup_domain); + if( checkBox.isChecked()){ + String domain = checkBox.getText().toString().trim(); + domainBlocked.put(domain, null); + } + } + if( domainBlocked.size() > 0 ){ + new Thread() { + public void run() { + Iterator it = domainBlocked.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry)it.next(); + try { + sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + new PostActionAsyncTask(context, API.StatusAction.BLOCK_DOMAIN, pair.getKey().toString().trim(), ((MutedInstanceActivity)context)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + it.remove(); + } + } + }.start(); + } + dialog.dismiss(); + } + }); + dialogBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }); + AlertDialog alertDialog = dialogBuilder.create(); + alertDialog.show(); + + new AsyncTask>() { + private WeakReference contextReference = new WeakReference<>(context); + APIResponse apiResponse; + + @Override + protected void onPreExecute() { + } + + @Override + protected List doInBackground(Void... voids) { + apiResponse = new API(contextReference.get()).getBlockedDomain(null); + return apiResponse.getDomains(); + } + @Override + protected void onPostExecute( List domains) { + if( domains == null){ + return; + } + + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR ); + + + } } diff --git a/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java b/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java index 902346232..82e022c8a 100644 --- a/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java +++ b/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java @@ -500,7 +500,7 @@ public class Sqlite extends SQLiteOpenHelper { if (sd.canWrite()) { - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date()); String backupDBPath = "Fedilab_export_"+timeStamp+".fedilab"; File dbSource = context.getDatabasePath(DB_NAME); File dbDest = new File(sd,backupDBPath); @@ -524,4 +524,7 @@ public class Sqlite extends SQLiteOpenHelper { Toasty.error(context, context.getString(R.string.data_export_error_simple), Toast.LENGTH_LONG).show(); } } + + + } diff --git a/app/src/main/res/layout/activity_muted_instances.xml b/app/src/main/res/layout/activity_muted_instances.xml new file mode 100644 index 000000000..2959cddcc --- /dev/null +++ b/app/src/main/res/layout/activity_muted_instances.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_muted_instances.xml b/app/src/main/res/layout/fragment_muted_instances.xml index a9a27df6e..1c7f6a3be 100644 --- a/app/src/main/res/layout/fragment_muted_instances.xml +++ b/app/src/main/res/layout/fragment_muted_instances.xml @@ -52,7 +52,7 @@ android:layout_height="match_parent" /> - + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/simple_bar_muted_instance.xml b/app/src/main/res/layout/simple_bar_muted_instance.xml new file mode 100644 index 000000000..e7d207fe1 --- /dev/null +++ b/app/src/main/res/layout/simple_bar_muted_instance.xml @@ -0,0 +1,70 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/option_muted_instance.xml b/app/src/main/res/menu/option_muted_instance.xml new file mode 100644 index 000000000..8cac49b17 --- /dev/null +++ b/app/src/main/res/menu/option_muted_instance.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 02470a90a..1cf7dafea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1113,6 +1113,11 @@ Create folder Use your favourite browser inside the application. By disabling, links will be opened externally Display a toast message after an action has been completed (boost, fav, etc.)? + Export muted instances + Muted instances have been exported! + Add an instance + Export instances + Import instances %d vote