diff options
73 files changed, 3257 insertions, 549 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7d911e4e6..5ed0fa75d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,3 +7,6 @@ Mastalab works only with [Crowdin](https://crowdin.com/project/mastalab), which New translations will be automatically merged in a branch. If your language is not listed, please ask me to add it. If you prefer to work on an XML file, you should be able [to upload it with Crowdin](https://support.crowdin.com/xml-configuration/). Crowdin will not pick up changes in develop branch, that's why all translations should be done with this tool. + +If you're submiting a merge request and your work adds new strings to the app, make sure they only exist in the default strings.xml file (res/values/strings.xml). +If you add or modify strings of other languages, it will interfere with crowdin's translations.
\ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f0b302af8..9ff210576 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "fr.gouv.etalab.mastodon" minSdkVersion 16 targetSdkVersion 28 - versionCode 230 - versionName "1.66.0" + versionCode 233 + versionName "1.67.1" multiDexEnabled true } dexOptions { @@ -90,7 +90,9 @@ dependencies { implementation 'com.android.support:multidex:1.0.3' implementation 'com.google.android.exoplayer:exoplayer:2.9.3' implementation 'com.github.stom79:android-upload-service:3.4.2-Mastalab' + implementation 'org.apache.poi:poi:3.16' implementation 'com.github.mabbas007:TagsEditText:1.0.5' implementation 'com.jaredrummler:material-spinner:1.3.1' + implementation 'com.github.stom79:SQLite2XL:1.0.5' playstoreImplementation "io.github.kobakei:ratethisapp:$ratethisappLibraryVersion" } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java index 9f9287665..2091d0248 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/BaseMainActivity.java @@ -25,6 +25,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.sqlite.SQLiteDatabase; +import android.graphics.BitmapFactory; import android.graphics.PorterDuff; import android.net.Uri; import android.os.AsyncTask; @@ -77,15 +78,23 @@ import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; +import com.ajts.androidmads.library.ExcelToSQLite; +import com.ajts.androidmads.library.SQLiteToExcel; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.io.File; import java.lang.reflect.Method; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; +import java.util.Random; import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -121,7 +130,9 @@ import fr.gouv.etalab.mastodon.fragments.DisplayHowToFragment; import fr.gouv.etalab.mastodon.fragments.DisplayListsFragment; import fr.gouv.etalab.mastodon.fragments.DisplayMutedInstanceFragment; import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment; +import fr.gouv.etalab.mastodon.fragments.DisplayPeertubeNotificationsFragment; import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment; +import fr.gouv.etalab.mastodon.fragments.SettingsFragment; import fr.gouv.etalab.mastodon.fragments.SettingsPeertubeFragment; import fr.gouv.etalab.mastodon.fragments.TabLayoutScheduleFragment; import fr.gouv.etalab.mastodon.fragments.TabLayoutSettingsFragment; @@ -165,6 +176,7 @@ import static fr.gouv.etalab.mastodon.helper.Helper.changeUser; import static fr.gouv.etalab.mastodon.helper.Helper.menuAccounts; import static fr.gouv.etalab.mastodon.helper.Helper.unCheckAllMenuItems; import static fr.gouv.etalab.mastodon.helper.Helper.updateHeaderAccountInfo; +import static fr.gouv.etalab.mastodon.sqlite.Sqlite.DB_NAME; public abstract class BaseMainActivity extends BaseActivity @@ -210,6 +222,7 @@ public abstract class BaseMainActivity extends BaseActivity private FloatingActionButton federatedTimelines; public static UpdateAccountInfoAsyncTask.SOCIAL social; SparseArray<Fragment> registeredFragments = new SparseArray<>(); + private final int PICK_IMPORT = 5556; @Override protected void onCreate(Bundle savedInstanceState) { @@ -221,7 +234,7 @@ public abstract class BaseMainActivity extends BaseActivity userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(getApplicationContext())); - SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), DB_NAME, null, Sqlite.DB_VERSION).open(); boolean displayFollowInstance = sharedpreferences.getBoolean(Helper.SET_DISPLAY_FOLLOW_INSTANCE, true); Account account = new AccountDAO(getApplicationContext(), db).getAccountByToken(token); if( account == null){ @@ -233,12 +246,14 @@ public abstract class BaseMainActivity extends BaseActivity } //Update the static variable which manages account type - if( account.getSocial() == null || account.getSocial().equals("MASTODON") ) + if( account.getSocial() == null || account.getSocial().equals("MASTODON")) social = UpdateAccountInfoAsyncTask.SOCIAL.MASTODON; else if( account.getSocial().equals("PEERTUBE")) social = UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE; else if( account.getSocial().equals("PIXELFED")) social = UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED; + else if( account.getSocial().equals("PLEROMA")) + social = UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA; countNewStatus = 0; countNewNotifications = 0; @@ -328,7 +343,7 @@ public abstract class BaseMainActivity extends BaseActivity delete_all = findViewById(R.id.delete_all); add_new = findViewById(R.id.add_new); - if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { + if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { TabLayout.Tab tabHome = tabLayout.newTab(); TabLayout.Tab tabNotif = tabLayout.newTab(); TabLayout.Tab tabDirect = tabLayout.newTab(); @@ -1058,14 +1073,14 @@ public abstract class BaseMainActivity extends BaseActivity changeDrawableColor(getApplicationContext(), R.drawable.ic_recently_added,R.color.dark_text); } - if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) + if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) startSreaming(); - if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) + if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) Helper.refreshSearchTag(BaseMainActivity.this, tabLayout, adapter); int tabCount = tabLayout.getTabCount(); - if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) + if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) for( int j = countPage ; j < tabCount ; j++){ attacheDelete(j); } @@ -1185,7 +1200,7 @@ public abstract class BaseMainActivity extends BaseActivity tabLayout.getTabAt(0).select(); - if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { + if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { toot.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -1339,6 +1354,61 @@ public abstract class BaseMainActivity extends BaseActivity startService(backupIntent); } return true; + + case R.id.action_import_data: + + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (ContextCompat.checkSelfPermission(BaseMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != + PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(BaseMainActivity.this, + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + TootActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); + return true; + } + } + 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("application/vnd.ms-excel"); + String[] mimetypes = {"application/vnd.ms-excel"}; + intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes); + startActivityForResult(intent, PICK_IMPORT); + }else { + intent.setType("application/vnd.ms-excel"); + 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); + } + return true; + case R.id.action_export_data: + SQLiteToExcel sqliteToExcel = new SQLiteToExcel(BaseMainActivity.this, DB_NAME); + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); + final String fileName = "Mastalab_export_"+timeStamp+".xls"; + sqliteToExcel.exportAllTables(fileName, new SQLiteToExcel.ExportListener() { + @Override + public void onStart() { + + } + @Override + public void onCompleted(String filePath) { + final Intent intent = new Intent(); + Random r = new Random(); + final int notificationIdTmp = r.nextInt(10000); + File file = new File(filePath); + intent.setAction(android.content.Intent.ACTION_VIEW); + Uri uri = Uri.fromFile(file); + intent.setDataAndType(uri, "application/vnd.ms-excel"); + Helper.notify_user(getApplicationContext(), intent, notificationIdTmp, BitmapFactory.decodeResource(getResources(), + R.mipmap.ic_launcher), Helper.NotifType.STORE, getString(R.string.save_over), getString(R.string.download_from, fileName)); + Toasty.success(getApplicationContext(), getString(R.string.toast_saved),Toast.LENGTH_LONG).show(); + } + @Override + public void onError(Exception e) { + Toasty.error(getApplicationContext(), getString(R.string.data_export_error_simple),Toast.LENGTH_LONG).show(); + } + }); + return true; default: return true; } @@ -1403,7 +1473,7 @@ public abstract class BaseMainActivity extends BaseActivity // Asked once for notification opt-in boolean popupShown = sharedpreferences.getBoolean(Helper.SET_POPUP_PUSH, false); - if(!popupShown && social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON){ + if(!popupShown && (social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA)){ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(BaseMainActivity.this, style); LayoutInflater inflater = getLayoutInflater(); @SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.popup_quick_settings, null); @@ -1443,7 +1513,7 @@ public abstract class BaseMainActivity extends BaseActivity mamageNewIntent(getIntent()); - if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { + if( social == UpdateAccountInfoAsyncTask.SOCIAL.MASTO |