From 7f1098e3451f6bcbeca215546c7d3cae01b30f58 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 Dec 2022 09:55:04 +0100 Subject: [PATCH 01/19] Create table / update db --- .../java/app/fedilab/android/sqlite/Sqlite.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) 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 55daf2e0..0856ae9d 100644 --- a/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java +++ b/app/src/main/java/app/fedilab/android/sqlite/Sqlite.java @@ -23,7 +23,7 @@ import android.database.sqlite.SQLiteOpenHelper; public class Sqlite extends SQLiteOpenHelper { - public static final int DB_VERSION = 7; + public static final int DB_VERSION = 8; public static final String DB_NAME = "fedilab_db"; //Table of owned accounts @@ -84,6 +84,9 @@ public class Sqlite extends SQLiteOpenHelper { //Tracking domains public static final String TABLE_DOMAINS_TRACKING = "TABLE_DOMAINS_TRACKING"; public static final String COL_DOMAIN = "DOMAIN"; + //Muted accounts for home + public static final String TABLE_MUTED = "TABLE_MUTED"; + public static final String COL_MUTED_ACCOUNTS = "MUTED_ACCOUNTS"; private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " (" + COL_USER_ID + " TEXT NOT NULL, " @@ -177,6 +180,14 @@ public class Sqlite extends SQLiteOpenHelper { + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COL_DOMAIN + " TEXT NOT NULL)"; + + private static final String CREATE_TABLE_MUTED = "CREATE TABLE IF NOT EXISTS " + TABLE_MUTED + " (" + + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + COL_INSTANCE + " TEXT NOT NULL, " + + COL_USER_ID + " TEXT NOT NULL, " + + COL_TYPE + " TEXT NOT NULL, " + + COL_MUTED_ACCOUNTS + " TEXT)"; + public static SQLiteDatabase db; private static Sqlite sInstance; @@ -205,6 +216,7 @@ public class Sqlite extends SQLiteOpenHelper { db.execSQL(CREATE_TABLE_SCHEDULE_BOOST); db.execSQL(CREATE_TABLE_BOTTOM_MENU); db.execSQL(CREATE_DOMAINS_TRACKING); + db.execSQL(CREATE_TABLE_MUTED); } @Override @@ -229,6 +241,8 @@ public class Sqlite extends SQLiteOpenHelper { db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUICK_LOAD); case 6: db.execSQL("DROP TABLE IF EXISTS " + TABLE_DOMAINS_TRACKING); + case 7: + db.execSQL(CREATE_TABLE_MUTED); default: break; } From 5e11438f0c460996b016f7ef96ca519d78ca1e4e Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 Dec 2022 10:40:29 +0100 Subject: [PATCH 02/19] Manage accounts --- .../client/entities/app/MutedAccounts.java | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java new file mode 100644 index 00000000..7ee494f5 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java @@ -0,0 +1,216 @@ +package app.fedilab.android.client.entities.app; +/* Copyright 2022 Thomas Schneider + * + * This file is a part of Fedilab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Fedilab; if not, + * see . */ + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import app.fedilab.android.client.entities.api.Account; +import app.fedilab.android.exception.DBException; +import app.fedilab.android.sqlite.Sqlite; + + +public class MutedAccounts implements Serializable { + + + private transient final SQLiteDatabase db; + @SerializedName("id") + public long id = -1; + @SerializedName("instance") + public String instance; + @SerializedName("user_id") + public String user_id; + @SerializedName("type") + public Timeline.TimeLineEnum type; + @SerializedName("accounts") + public List accounts; + + public MutedAccounts() { + db = null; + } + + public MutedAccounts(Context context) { + //Creation of the DB with tables + this.db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + } + + + /** + * Serialized a list of BaseAccount class + * + * @param accounts List of {@link Account} to serialize + * @return String serialized emoji list + */ + public static String accountListToStringStorage(List accounts) { + Gson gson = new Gson(); + try { + return gson.toJson(accounts); + } catch (Exception e) { + return null; + } + } + + /** + * Unserialized a BaseAccount List + * + * @param serializedAccounts String serialized BaseAccount list + * @return List of {@link Account} + */ + public static List restoreAccountsFromString(String serializedAccounts) { + Gson gson = new Gson(); + try { + return gson.fromJson(serializedAccounts, new TypeToken>() { + }.getType()); + } catch (Exception e) { + return null; + } + } + + + /** + * Insert an Account in muted account in db + * + * @param forAccount {@link BaseAccount} + * @param target {@link Account} + * @return long - db id + * @throws DBException exception with database + */ + public long muteAccount(BaseAccount forAccount, Account target) throws DBException { + if (db == null) { + throw new DBException("db is null. Wrong initialization."); + } + boolean insert = false; + MutedAccounts mutedAccounts = getMutedAccount(forAccount); + ContentValues values = new ContentValues(); + if (mutedAccounts == null) { + mutedAccounts = new MutedAccounts(); + mutedAccounts.accounts = new ArrayList<>(); + mutedAccounts.type = Timeline.TimeLineEnum.HOME; + values.put(Sqlite.COL_INSTANCE, forAccount.instance); + values.put(Sqlite.COL_USER_ID, forAccount.user_id); + insert = true; + values.put(Sqlite.COL_TYPE, mutedAccounts.type.getValue()); + } else if (mutedAccounts.accounts == null) { + mutedAccounts.accounts = new ArrayList<>(); + } + if (!mutedAccounts.accounts.contains(target)) { + mutedAccounts.accounts.add(target); + } + values.put(Sqlite.COL_MUTED_ACCOUNTS, accountListToStringStorage(mutedAccounts.accounts)); + + //Inserts or updates + try { + if (insert) { + return db.insertOrThrow(Sqlite.TABLE_MUTED, null, values); + } else { + return db.update(Sqlite.TABLE_MUTED, + values, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " = ?", + new String[]{forAccount.user_id, forAccount.instance}); + } + } catch (Exception e) { + e.printStackTrace(); + return -1; + } + } + + + /** + * Remove an Account in muted account in db + * + * @param forAccount {@link BaseAccount} + * @param target {@link Account} + * @return long - db id + * @throws DBException exception with database + */ + public long unMuteAccount(BaseAccount forAccount, Account target) throws DBException { + if (db == null) { + throw new DBException("db is null. Wrong initialization."); + } + boolean insert = false; + MutedAccounts mutedAccounts = getMutedAccount(forAccount); + ContentValues values = new ContentValues(); + if (mutedAccounts == null) { + mutedAccounts = new MutedAccounts(); + mutedAccounts.accounts = new ArrayList<>(); + mutedAccounts.type = Timeline.TimeLineEnum.HOME; + values.put(Sqlite.COL_INSTANCE, forAccount.instance); + values.put(Sqlite.COL_USER_ID, forAccount.user_id); + insert = true; + values.put(Sqlite.COL_TYPE, mutedAccounts.type.getValue()); + } else if (mutedAccounts.accounts == null) { + mutedAccounts.accounts = new ArrayList<>(); + } + mutedAccounts.accounts.remove(target); + values.put(Sqlite.COL_MUTED_ACCOUNTS, accountListToStringStorage(mutedAccounts.accounts)); + + //Inserts or updates + try { + if (insert) { + return db.insertOrThrow(Sqlite.TABLE_MUTED, null, values); + } else { + return db.update(Sqlite.TABLE_MUTED, + values, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " = ?", + new String[]{forAccount.user_id, forAccount.instance}); + } + } catch (Exception e) { + e.printStackTrace(); + return -1; + } + } + + /** + * Returns the MutedAccounts for an account + * + * @param account Account + * @return MutedAccounts - {@link MutedAccounts} + */ + public MutedAccounts getMutedAccount(BaseAccount account) throws DBException { + if (db == null) { + throw new DBException("db is null. Wrong initialization."); + } + try { + Cursor c = db.query(Sqlite.TABLE_MUTED, null, Sqlite.COL_INSTANCE + " = '" + account.instance + "' AND " + Sqlite.COL_USER_ID + " = '" + account.user_id + "'", null, null, null, null, null); + return convertCursorToMuted(c); + } catch (Exception e) { + return null; + } + } + + /** + * Read cursor and hydrate without closing it + * + * @param c - Cursor + * @return MutedAccounts + */ + private MutedAccounts convertCursorToMuted(Cursor c) { + MutedAccounts mutedAccounts = new MutedAccounts(); + mutedAccounts.id = c.getInt(c.getColumnIndexOrThrow(Sqlite.COL_ID)); + mutedAccounts.instance = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_INSTANCE)); + mutedAccounts.user_id = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_USER_ID)); + mutedAccounts.accounts = restoreAccountsFromString(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_MUTED_ACCOUNTS))); + mutedAccounts.type = Timeline.TimeLineEnum.valueOf(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_TYPE))); + return mutedAccounts; + } +} From 93fce1f56e911cf4249746decb2dc46a31cebe5c Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 Dec 2022 11:21:00 +0100 Subject: [PATCH 03/19] Allow to mute/unmute from profile --- .../android/activities/ProfileActivity.java | 34 ++++++++++ .../client/entities/app/MutedAccounts.java | 22 ++++++ .../android/ui/drawer/StatusAdapter.java | 11 +++ .../viewmodel/mastodon/AccountsVM.java | 67 +++++++++++++++++++ app/src/main/res/menu/activity_profile.xml | 5 ++ app/src/main/res/menu/option_toot.xml | 4 ++ app/src/main/res/values/strings.xml | 2 + 7 files changed, 145 insertions(+) diff --git a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java index 79ac5c58..9b795443 100644 --- a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java @@ -16,6 +16,7 @@ package app.fedilab.android.activities; import static app.fedilab.android.BaseMainActivity.currentAccount; +import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction; import android.content.BroadcastReceiver; import android.content.ClipData; @@ -117,6 +118,7 @@ public class ProfileActivity extends BaseActivity { private String mention_str; private WellKnownNodeinfo.NodeInfo nodeInfo; private boolean checkRemotely; + private boolean homeMuted; private final BroadcastReceiver broadcast_data = new BroadcastReceiver() { @Override @@ -144,6 +146,7 @@ public class ProfileActivity extends BaseActivity { Bundle b = getIntent().getExtras(); binding.accountFollow.setEnabled(false); checkRemotely = false; + homeMuted = false; if (b != null) { account = (Account) b.getSerializable(Helper.ARG_ACCOUNT); account_id = b.getString(Helper.ARG_USER_ID, null); @@ -185,6 +188,8 @@ public class ProfileActivity extends BaseActivity { Toasty.error(ProfileActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); finish(); } + //Check if account is homeMuted + accountsVM.isMuted(currentAccount, account).observe(ProfileActivity.this, account1 -> homeMuted = account1 != null); LocalBroadcastManager.getInstance(ProfileActivity.this).registerReceiver(broadcast_data, new IntentFilter(Helper.BROADCAST_DATA)); } @@ -685,9 +690,11 @@ public class ProfileActivity extends BaseActivity { menu.findItem(R.id.action_endorse).setVisible(false); menu.findItem(R.id.action_direct_message).setVisible(false); menu.findItem(R.id.action_add_to_list).setVisible(false); + menu.findItem(R.id.action_mute_home).setVisible(false); } else { menu.findItem(R.id.action_block).setVisible(true); menu.findItem(R.id.action_mute).setVisible(true); + menu.findItem(R.id.action_mute_home).setVisible(true); menu.findItem(R.id.action_timed_mute).setVisible(true); menu.findItem(R.id.action_mention).setVisible(true); } @@ -696,6 +703,7 @@ public class ProfileActivity extends BaseActivity { if (!relationship.following) { menu.findItem(R.id.action_hide_boost).setVisible(false); menu.findItem(R.id.action_endorse).setVisible(false); + menu.findItem(R.id.action_mute_home).setVisible(false); } if (relationship.blocking) { menu.findItem(R.id.action_block).setTitle(R.string.action_unblock); @@ -713,6 +721,11 @@ public class ProfileActivity extends BaseActivity { } else { menu.findItem(R.id.action_hide_boost).setTitle(getString(R.string.show_boost, account.username)); } + if (homeMuted) { + menu.findItem(R.id.action_mute_home).setTitle(getString(R.string.unmute_home)); + } else { + menu.findItem(R.id.action_mute_home).setTitle(getString(R.string.mute_home)); + } } } return true; @@ -989,6 +1002,27 @@ public class ProfileActivity extends BaseActivity { }); builderInner.show(); } + } else if (itemId == R.id.action_mute_home) { + AlertDialog.Builder builderInner = new AlertDialog.Builder(ProfileActivity.this, Helper.dialogStyle()); + builderInner.setMessage(account.acct); + builderInner.setNeutralButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); + if (homeMuted) { + builderInner.setTitle(R.string.unmute_home); + builderInner.setPositiveButton(R.string.action_unmute, (dialog, which) -> accountsVM.unmuteHome(currentAccount, account) + .observe(ProfileActivity.this, account -> { + homeMuted = false; + Toasty.info(ProfileActivity.this, getString(R.string.toast_unmute), Toasty.LENGTH_LONG).show(); + })); + } else { + builderInner.setTitle(R.string.mute_home); + builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, account) + .observe(ProfileActivity.this, account -> { + homeMuted = true; + sendAction(ProfileActivity.this, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, account.id); + Toasty.info(ProfileActivity.this, getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); + })); + } + builderInner.show(); } else if (itemId == R.id.action_timed_mute) { MastodonHelper.scheduleBoost(ProfileActivity.this, MastodonHelper.ScheduleType.TIMED_MUTED, null, account, rs -> { this.relationship = rs; diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java index 7ee494f5..355fece9 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java @@ -180,6 +180,28 @@ public class MutedAccounts implements Serializable { } } + /** + * Check if an account is muted in db + * + * @param forAccount {@link BaseAccount} + * @param target {@link Account} + * @return MutedAccounts - {@link MutedAccounts} + */ + public boolean isMuted(BaseAccount forAccount, Account target) throws DBException { + if (db == null) { + throw new DBException("db is null. Wrong initialization."); + } + MutedAccounts mutedAccounts = getMutedAccount(forAccount); + if (mutedAccounts != null && mutedAccounts.accounts != null) { + for (Account account : mutedAccounts.accounts) { + if (account.id.equals(target.id)) { + return true; + } + } + } + return false; + } + /** * Returns the MutedAccounts for an account * diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index 41b29f4b..5861c8b1 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -1655,6 +1655,17 @@ public class StatusAdapter extends RecyclerView.Adapter Toasty.info(context, context.getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); })); builderInner.show(); + } else if (itemId == R.id.action_mute_home) { + AlertDialog.Builder builderInner = new AlertDialog.Builder(context, Helper.dialogStyle()); + builderInner.setTitle(R.string.mute_home); + builderInner.setMessage(statusToDeal.account.acct); + builderInner.setNeutralButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); + builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, statusToDeal.account) + .observe((LifecycleOwner) context, account -> { + sendAction(context, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, statusToDeal.account.id); + Toasty.info(context, context.getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); + })); + builderInner.show(); } else if (itemId == R.id.action_mute_conversation) { if (statusToDeal.muted) { statusesVM.unMute(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id).observe((LifecycleOwner) context, status1 -> Toasty.info(context, context.getString(R.string.toast_unmute_conversation)).show()); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index 5d4e17cd..aa8a3876 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -52,7 +52,10 @@ import app.fedilab.android.client.entities.api.Suggestion; import app.fedilab.android.client.entities.api.Suggestions; import app.fedilab.android.client.entities.api.Tag; import app.fedilab.android.client.entities.api.Token; +import app.fedilab.android.client.entities.app.BaseAccount; +import app.fedilab.android.client.entities.app.MutedAccounts; import app.fedilab.android.client.entities.app.StatusCache; +import app.fedilab.android.exception.DBException; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import okhttp3.MultipartBody; @@ -748,6 +751,70 @@ public class AccountsVM extends AndroidViewModel { return relationShipMutableLiveData; } + + /** + * Mute the given account in db + * + * @return {@link LiveData} containing the {@link Account} to the given account + */ + public LiveData isMuted(@NonNull BaseAccount forAccount, @NonNull Account target) { + accountMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + boolean isMuted = false; + try { + isMuted = new MutedAccounts(getApplication().getApplicationContext()).isMuted(forAccount, target); + } catch (DBException e) { + e.printStackTrace(); + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + boolean finalIsMuted = isMuted; + Runnable myRunnable = () -> accountMutableLiveData.setValue(finalIsMuted ? target : null); + mainHandler.post(myRunnable); + }).start(); + return accountMutableLiveData; + } + + /** + * Mute the given account in db + * + * @return {@link LiveData} containing the {@link Account} to the given account + */ + public LiveData muteHome(@NonNull BaseAccount forAccount, @NonNull Account target) { + accountMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + + try { + new MutedAccounts(getApplication().getApplicationContext()).muteAccount(forAccount, target); + } catch (DBException e) { + e.printStackTrace(); + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> accountMutableLiveData.setValue(target); + mainHandler.post(myRunnable); + }).start(); + return accountMutableLiveData; + } + + /** + * Unmute the given account in db + * + * @return {@link LiveData} containing the {@link Account} to the given account + */ + public LiveData unmuteHome(@NonNull BaseAccount forAccount, @NonNull Account target) { + accountMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + try { + new MutedAccounts(getApplication().getApplicationContext()).unMuteAccount(forAccount, target); + } catch (DBException e) { + e.printStackTrace(); + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> accountMutableLiveData.setValue(target); + mainHandler.post(myRunnable); + }).start(); + return accountMutableLiveData; + } + /** * Unmute the given account. * diff --git a/app/src/main/res/menu/activity_profile.xml b/app/src/main/res/menu/activity_profile.xml index d34cfd13..cd17ac2c 100644 --- a/app/src/main/res/menu/activity_profile.xml +++ b/app/src/main/res/menu/activity_profile.xml @@ -16,6 +16,11 @@ android:icon="@drawable/ic_baseline_open_with_24" android:title="@string/action_open_in_web" app:showAsAction="never" /> + + Pin tag Unpin tag Unfollow tag + Mute for home + Unmute for home \ No newline at end of file From 7d03f5b6c0f6d346a607aa2d17e029f77b67b6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Jel=C3=ADnek?= Date: Wed, 14 Dec 2022 11:49:08 +0100 Subject: [PATCH 04/19] Translated using Weblate (Czech) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 98.6% (972 of 985 strings) Co-authored-by: Lukáš Jelínek Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/cs/ Translation: Fedilab/Strings --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index d2b43093..537c7503 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -443,7 +443,7 @@ Tato instance funguje na pozvánky. Aby se dal váš účet používat, musí ho ručně schválit administrátor. Hesla nesouhlasí! E-mail se zdá být neplatný! - Poslali jsme vám potvrzovací e-mail + Instance vám pošle potvrzovací e-mail Použijte minimálně 8 znaků Heslo musí mít minimálně 8 znaků Uživatelské jméno smí obsahovat jen písmena, číslice a podtržítka From 83f0699d47ab773346f200291e69efab0bffe531 Mon Sep 17 00:00:00 2001 From: Ajeje Brazorf Date: Wed, 14 Dec 2022 11:49:08 +0100 Subject: [PATCH 05/19] Translated using Weblate (Sardinian) Currently translated at 99.4% (980 of 985 strings) Co-authored-by: Ajeje Brazorf Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/sc/ Translation: Fedilab/Strings --- app/src/main/res/values-sc/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index d616e1c4..10363286 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -914,4 +914,10 @@ Permitit de personalizare unos cantos elementos in is messàgios pro su tema craru. Torra a proare prus a tardu. S\'aplicatzione no at agatadu su messàgiu remotu. + Pone s\'eticheta a sa muda + Isbloca s\'eticheta + Ammustra semper su butone de tradutzione + Torra a ativare s\'eticheta + Apica s\'eticheta + Non sigas prus s\'eticheta \ No newline at end of file From 7a93b22f7782239265b6c58da190beb25e11e8d9 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 Dec 2022 11:55:19 +0100 Subject: [PATCH 06/19] Display home muted --- .../app/fedilab/android/BaseMainActivity.java | 8 +++- .../android/activities/ActionActivity.java | 6 ++- .../android/client/entities/app/Timeline.java | 2 + .../android/helper/TimelineHelper.java | 21 +++++++++ .../timeline/FragmentMastodonAccount.java | 6 +++ .../viewmodel/mastodon/AccountsVM.java | 27 ++++++++++++ app/src/main/res/layout/activity_actions.xml | 44 +++++++++++++------ app/src/main/res/values/strings.xml | 1 + 8 files changed, 99 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java index 7e43d4d0..09fdb201 100644 --- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java @@ -127,6 +127,7 @@ import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.client.entities.app.Account; import app.fedilab.android.client.entities.app.BaseAccount; import app.fedilab.android.client.entities.app.BottomMenu; +import app.fedilab.android.client.entities.app.MutedAccounts; import app.fedilab.android.client.entities.app.Pinned; import app.fedilab.android.client.entities.app.PinnedTimeline; import app.fedilab.android.client.entities.app.StatusCache; @@ -164,6 +165,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt public static status networkAvailable = UNKNOWN; public static Instance instanceInfo; public static List mainFilters; + public static List filteredAccounts; public static boolean filterFetched; public static boolean show_boosts, show_replies, show_art_nsfw; public static String regex_home, regex_local, regex_public; @@ -302,7 +304,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } else { BaseMainActivity.currentToken = sharedpreferences.getString(Helper.PREF_USER_TOKEN, null); } - + filteredAccounts = new ArrayList<>(); mamageNewIntent(getIntent()); filterFetched = false; networkStateReceiver = new NetworkStateReceiver(); @@ -565,6 +567,10 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt currentAccount = new Account(BaseMainActivity.this).getConnectedAccount(); //Delete cache older than 7 days new StatusCache(BaseMainActivity.this).deleteForAllAccountAfter7Days(); + MutedAccounts mutedAccounts = new MutedAccounts(BaseMainActivity.this).getMutedAccount(currentAccount); + if (mutedAccounts != null && mutedAccounts.accounts != null) { + filteredAccounts = mutedAccounts.accounts; + } } catch (DBException e) { e.printStackTrace(); } diff --git a/app/src/main/java/app/fedilab/android/activities/ActionActivity.java b/app/src/main/java/app/fedilab/android/activities/ActionActivity.java index faa7a7ec..aab8386c 100644 --- a/app/src/main/java/app/fedilab/android/activities/ActionActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ActionActivity.java @@ -54,11 +54,12 @@ public class ActionActivity extends BaseBarActivity { binding.muted.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.MUTED_TIMELINE)); binding.blocked.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.BLOCKED_TIMELINE)); binding.domainBlock.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.BLOCKED_DOMAIN_TIMELINE)); + binding.mutedHome.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.MUTED_TIMELINE_HOME)); } private void displayTimeline(Timeline.TimeLineEnum type) { canGoBack = true; - if (type == Timeline.TimeLineEnum.MUTED_TIMELINE || type == Timeline.TimeLineEnum.BLOCKED_TIMELINE) { + if (type == Timeline.TimeLineEnum.MUTED_TIMELINE || type == Timeline.TimeLineEnum.BLOCKED_TIMELINE || type == Timeline.TimeLineEnum.MUTED_TIMELINE_HOME) { ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> { fragmentMastodonAccount = new FragmentMastodonAccount(); @@ -114,6 +115,9 @@ public class ActionActivity extends BaseBarActivity { case BLOCKED_DOMAIN_TIMELINE: setTitle(R.string.blocked_domains); break; + case MUTED_TIMELINE_HOME: + setTitle(R.string.muted_menu_home); + break; } } diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java b/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java index 0f5f6046..109a8790 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java @@ -388,6 +388,8 @@ public class Timeline { ACCOUNT_TIMELINE("ACCOUNT_TIMELINE"), @SerializedName("MUTED_TIMELINE") MUTED_TIMELINE("MUTED_TIMELINE"), + @SerializedName("MUTED_TIMELINE_HOME") + MUTED_TIMELINE_HOME("MUTED_TIMELINE_HOME"), @SerializedName("BOOKMARK_TIMELINE") BOOKMARK_TIMELINE("BOOKMARK_TIMELINE"), @SerializedName("BLOCKED_DOMAIN_TIMELINE") diff --git a/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java b/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java index 2f0366d7..f2e3fe59 100644 --- a/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java @@ -14,6 +14,8 @@ package app.fedilab.android.helper; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import static app.fedilab.android.BaseMainActivity.filteredAccounts; + import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; @@ -35,6 +37,7 @@ import java.util.regex.Pattern; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.client.endpoints.MastodonFiltersService; +import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Filter; import app.fedilab.android.client.entities.api.Notification; import app.fedilab.android.client.entities.api.Status; @@ -90,6 +93,7 @@ public class TimelineHelper { } } } + //If there are filters: if (BaseMainActivity.mainFilters != null && BaseMainActivity.mainFilters.size() > 0 && statuses != null && statuses.size() > 0) { @@ -143,6 +147,23 @@ public class TimelineHelper { Matcher ms = p.matcher(spoilerText); if (ms.find()) { status.filteredByApp = filter; + continue; + } + } + + if (filterTimeLineType == Timeline.TimeLineEnum.HOME) { + if (filteredAccounts != null && filteredAccounts.size() > 0) { + for (Account account : filteredAccounts) { + if (account.acct.equals(status.account.acct)) { + Filter filterCustom = new Filter(); + filterCustom.filter_action = "hide"; + ArrayList contextCustom = new ArrayList<>(); + contextCustom.add("home"); + filterCustom.title = "Fedilab"; + filterCustom.context = contextCustom; + status.filteredByApp = filterCustom; + } + } } } } diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java index 988aab25..9cf65321 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java @@ -32,6 +32,7 @@ import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; +import app.fedilab.android.activities.MainActivity; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Accounts; import app.fedilab.android.client.entities.api.Pagination; @@ -128,6 +129,11 @@ public class FragmentMastodonAccount extends Fragment { accountsVM.getMutes(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), max_id, null) .observe(getViewLifecycleOwner(), this::dealWithPagination); } + } else if (timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE_HOME) { + if (firstLoad) { + accountsVM.getMutedHome(MainActivity.currentAccount) + .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); + } } else if (timelineType == Timeline.TimeLineEnum.BLOCKED_TIMELINE) { if (firstLoad) { accountsVM.getBlocks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), null, null) diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index aa8a3876..7a09b09b 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -752,6 +752,33 @@ public class AccountsVM extends AndroidViewModel { } + /** + * Mute the given account in db + * + * @return {@link LiveData} containing the {@link Account} to the given account + */ + public LiveData getMutedHome(@NonNull BaseAccount forAccount) { + accountsMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + Accounts accounts = new Accounts(); + MutedAccounts mutedAccount; + try { + mutedAccount = new MutedAccounts(getApplication().getApplicationContext()).getMutedAccount(forAccount); + if (mutedAccount != null) { + accounts.accounts = mutedAccount.accounts; + } + accounts.pagination = new Pagination(); + } catch (DBException e) { + e.printStackTrace(); + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); + mainHandler.post(myRunnable); + }).start(); + return accountsMutableLiveData; + } + + /** * Mute the given account in db * diff --git a/app/src/main/res/layout/activity_actions.xml b/app/src/main/res/layout/activity_actions.xml index a1c7c143..22420311 100644 --- a/app/src/main/res/layout/activity_actions.xml +++ b/app/src/main/res/layout/activity_actions.xml @@ -12,12 +12,27 @@ android:orientation="vertical" android:padding="24dp"> + + + + - Home Local timeline Muted users + Home muted users Blocked users Notifications Follow requests From 807ff6c9da3f896c9cb5992631ab25d49ab4936d Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 Dec 2022 12:15:41 +0100 Subject: [PATCH 07/19] Some changes --- .../android/activities/ProfileActivity.java | 8 ++++++++ .../client/entities/app/MutedAccounts.java | 10 +++++++++- .../java/app/fedilab/android/helper/Helper.java | 15 +++++++++++++++ .../fedilab/android/ui/drawer/StatusAdapter.java | 4 ++++ app/src/main/res/layout/activity_list.xml | 4 ++-- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java index 9b795443..9eef75bf 100644 --- a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java @@ -16,6 +16,8 @@ package app.fedilab.android.activities; import static app.fedilab.android.BaseMainActivity.currentAccount; +import static app.fedilab.android.helper.Helper.addMutedAccount; +import static app.fedilab.android.helper.Helper.removeMutedAccount; import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction; import android.content.BroadcastReceiver; @@ -1011,12 +1013,18 @@ public class ProfileActivity extends BaseActivity { builderInner.setPositiveButton(R.string.action_unmute, (dialog, which) -> accountsVM.unmuteHome(currentAccount, account) .observe(ProfileActivity.this, account -> { homeMuted = false; + if (account != null) { + removeMutedAccount(account); + } Toasty.info(ProfileActivity.this, getString(R.string.toast_unmute), Toasty.LENGTH_LONG).show(); })); } else { builderInner.setTitle(R.string.mute_home); builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, account) .observe(ProfileActivity.this, account -> { + if (account != null) { + addMutedAccount(account); + } homeMuted = true; sendAction(ProfileActivity.this, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, account.id); Toasty.info(ProfileActivity.this, getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java index 355fece9..d36d310e 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java @@ -213,9 +213,10 @@ public class MutedAccounts implements Serializable { throw new DBException("db is null. Wrong initialization."); } try { - Cursor c = db.query(Sqlite.TABLE_MUTED, null, Sqlite.COL_INSTANCE + " = '" + account.instance + "' AND " + Sqlite.COL_USER_ID + " = '" + account.user_id + "'", null, null, null, null, null); + Cursor c = db.query(Sqlite.TABLE_MUTED, null, Sqlite.COL_INSTANCE + " = '" + account.instance + "' AND " + Sqlite.COL_USER_ID + " = '" + account.user_id + "'", null, null, null, null, "1"); return convertCursorToMuted(c); } catch (Exception e) { + e.printStackTrace(); return null; } } @@ -227,12 +228,19 @@ public class MutedAccounts implements Serializable { * @return MutedAccounts */ private MutedAccounts convertCursorToMuted(Cursor c) { + if (c.getCount() == 0) { + c.close(); + return null; + } + //Take the first element + c.moveToFirst(); MutedAccounts mutedAccounts = new MutedAccounts(); mutedAccounts.id = c.getInt(c.getColumnIndexOrThrow(Sqlite.COL_ID)); mutedAccounts.instance = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_INSTANCE)); mutedAccounts.user_id = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_USER_ID)); mutedAccounts.accounts = restoreAccountsFromString(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_MUTED_ACCOUNTS))); mutedAccounts.type = Timeline.TimeLineEnum.valueOf(c.getString(c.getColumnIndexOrThrow(Sqlite.COL_TYPE))); + c.close(); return mutedAccounts; } } 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 2b1aa30a..e1d55937 100644 --- a/app/src/main/java/app/fedilab/android/helper/Helper.java +++ b/app/src/main/java/app/fedilab/android/helper/Helper.java @@ -1953,4 +1953,19 @@ public class Helper { public interface OnAttachmentCopied { void onAttachmentCopied(Attachment attachment); } + + public static void addMutedAccount(app.fedilab.android.client.entities.api.Account target) { + if (MainActivity.filteredAccounts == null) { + MainActivity.filteredAccounts = new ArrayList<>(); + } + if (!MainActivity.filteredAccounts.contains(target)) { + MainActivity.filteredAccounts.add(target); + } + } + + public static void removeMutedAccount(app.fedilab.android.client.entities.api.Account target) { + if (MainActivity.filteredAccounts != null) { + MainActivity.filteredAccounts.remove(target); + } + } } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index 5861c8b1..2beece92 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -28,6 +28,7 @@ import static app.fedilab.android.helper.Helper.ARG_TIMELINE_REFRESH_ALL; import static app.fedilab.android.helper.Helper.PREF_USER_ID; import static app.fedilab.android.helper.Helper.PREF_USER_INSTANCE; import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN; +import static app.fedilab.android.helper.Helper.addMutedAccount; import android.annotation.SuppressLint; import android.app.Activity; @@ -1662,6 +1663,9 @@ public class StatusAdapter extends RecyclerView.Adapter builderInner.setNeutralButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, statusToDeal.account) .observe((LifecycleOwner) context, account -> { + if (account != null) { + addMutedAccount(account); + } sendAction(context, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, statusToDeal.account.id); Toasty.info(context, context.getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); })); diff --git a/app/src/main/res/layout/activity_list.xml b/app/src/main/res/layout/activity_list.xml index e55a04b5..ad074498 100644 --- a/app/src/main/res/layout/activity_list.xml +++ b/app/src/main/res/layout/activity_list.xml @@ -2,8 +2,8 @@ + android:layout_marginHorizontal="6dp" + android:orientation="vertical"> Date: Wed, 14 Dec 2022 14:29:20 +0100 Subject: [PATCH 08/19] Allow to mute/unmute from the list with a new icon --- .../android/activities/ProfileActivity.java | 12 +++------ .../android/client/entities/api/Account.java | 12 +++++++++ .../client/entities/app/MutedAccounts.java | 3 +++ .../android/ui/drawer/AccountAdapter.java | 27 +++++++++++++++++-- .../android/ui/drawer/StatusAdapter.java | 4 --- .../timeline/FragmentMastodonAccount.java | 2 +- .../viewmodel/mastodon/AccountsVM.java | 14 +++++++--- app/src/main/res/layout/drawer_account.xml | 12 +++++++++ 8 files changed, 66 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java index 9eef75bf..022c6512 100644 --- a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java @@ -16,8 +16,6 @@ package app.fedilab.android.activities; import static app.fedilab.android.BaseMainActivity.currentAccount; -import static app.fedilab.android.helper.Helper.addMutedAccount; -import static app.fedilab.android.helper.Helper.removeMutedAccount; import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction; import android.content.BroadcastReceiver; @@ -191,7 +189,7 @@ public class ProfileActivity extends BaseActivity { finish(); } //Check if account is homeMuted - accountsVM.isMuted(currentAccount, account).observe(ProfileActivity.this, account1 -> homeMuted = account1 != null); + accountsVM.isMuted(currentAccount, account).observe(this, result -> homeMuted = result != null && result); LocalBroadcastManager.getInstance(ProfileActivity.this).registerReceiver(broadcast_data, new IntentFilter(Helper.BROADCAST_DATA)); } @@ -1013,19 +1011,15 @@ public class ProfileActivity extends BaseActivity { builderInner.setPositiveButton(R.string.action_unmute, (dialog, which) -> accountsVM.unmuteHome(currentAccount, account) .observe(ProfileActivity.this, account -> { homeMuted = false; - if (account != null) { - removeMutedAccount(account); - } + invalidateOptionsMenu(); Toasty.info(ProfileActivity.this, getString(R.string.toast_unmute), Toasty.LENGTH_LONG).show(); })); } else { builderInner.setTitle(R.string.mute_home); builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, account) .observe(ProfileActivity.this, account -> { - if (account != null) { - addMutedAccount(account); - } homeMuted = true; + invalidateOptionsMenu(); sendAction(ProfileActivity.this, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, account.id); Toasty.info(ProfileActivity.this, getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); })); diff --git a/app/src/main/java/app/fedilab/android/client/entities/api/Account.java b/app/src/main/java/app/fedilab/android/client/entities/api/Account.java index ae0b71ae..9c423554 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/api/Account.java +++ b/app/src/main/java/app/fedilab/android/client/entities/api/Account.java @@ -19,6 +19,8 @@ import android.content.Context; import android.text.Spannable; import android.view.View; +import androidx.annotation.Nullable; + import com.google.gson.annotations.SerializedName; import java.io.Serializable; @@ -148,4 +150,14 @@ public class Account implements Serializable { public LinkedHashMap fields; } + + + @Override + public boolean equals(@Nullable Object obj) { + boolean same = false; + if (obj instanceof Account) { + same = this.id.equals(((Account) obj).id); + } + return same; + } } diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java index d36d310e..5932aac3 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/MutedAccounts.java @@ -88,6 +88,9 @@ public class MutedAccounts implements Serializable { } } + public void delete() { + db.delete(Sqlite.TABLE_MUTED, null, null); + } /** * Insert an Account in muted account in db diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/AccountAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/AccountAdapter.java index 2b0448de..031030ba 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/AccountAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/AccountAdapter.java @@ -42,6 +42,7 @@ import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; +import app.fedilab.android.activities.MainActivity; import app.fedilab.android.activities.ProfileActivity; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.databinding.DrawerAccountBinding; @@ -56,12 +57,19 @@ public class AccountAdapter extends RecyclerView.Adapter accountList; private Context context; + private final boolean home_mute; + + public AccountAdapter(List accountList, boolean home_mute) { + this.accountList = accountList; + this.home_mute = home_mute; + } public AccountAdapter(List accountList) { this.accountList = accountList; + this.home_mute = false; } - public static void accountManagement(Context context, AccountViewHolder accountViewHolder, Account account, int position, RecyclerView.Adapter adapter) { + public static void accountManagement(Context context, AccountViewHolder accountViewHolder, Account account, int position, RecyclerView.Adapter adapter, boolean home_mute) { MastodonHelper.loadPPMastodon(accountViewHolder.binding.avatar, account); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context); @@ -73,6 +81,21 @@ public class AccountAdapter extends RecyclerView.Adapter { + if (muted) { + accountsVM.unmuteHome(MainActivity.currentAccount, account).observe((LifecycleOwner) context, account1 -> adapter.notifyItemChanged(accountViewHolder.getLayoutPosition())); + } else { + accountsVM.muteHome(MainActivity.currentAccount, account).observe((LifecycleOwner) context, account1 -> adapter.notifyItemChanged(accountViewHolder.getLayoutPosition())); + } + }); + } else { + accountViewHolder.binding.muteHome.setVisibility(View.GONE); + } + accountViewHolder.binding.avatar.setOnClickListener(v -> { Intent intent = new Intent(context, ProfileActivity.class); Bundle b = new Bundle(); @@ -263,7 +286,7 @@ public class AccountAdapter extends RecyclerView.Adapter builderInner.setNeutralButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, statusToDeal.account) .observe((LifecycleOwner) context, account -> { - if (account != null) { - addMutedAccount(account); - } sendAction(context, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, statusToDeal.account.id); Toasty.info(context, context.getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); })); diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java index 9cf65321..afef6168 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java @@ -203,7 +203,7 @@ public class FragmentMastodonAccount extends Fragment { } this.accounts = accounts.accounts; - accountAdapter = new AccountAdapter(this.accounts); + accountAdapter = new AccountAdapter(this.accounts, timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE_HOME); flagLoading = accounts.pagination.max_id == null; LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index 7a09b09b..f24b257d 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -14,6 +14,8 @@ package app.fedilab.android.viewmodel.mastodon; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import static app.fedilab.android.helper.Helper.addMutedAccount; +import static app.fedilab.android.helper.Helper.removeMutedAccount; import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction; import android.app.Application; @@ -95,6 +97,8 @@ public class AccountsVM extends AndroidViewModel { private MutableLiveData tokenMutableLiveData; private MutableLiveData domainsMutableLiveData; private MutableLiveData reportMutableLiveData; + private MutableLiveData booleanMutableLiveData; + public AccountsVM(@NonNull Application application) { super(application); @@ -784,8 +788,8 @@ public class AccountsVM extends AndroidViewModel { * * @return {@link LiveData} containing the {@link Account} to the given account */ - public LiveData isMuted(@NonNull BaseAccount forAccount, @NonNull Account target) { - accountMutableLiveData = new MutableLiveData<>(); + public LiveData isMuted(@NonNull BaseAccount forAccount, @NonNull Account target) { + booleanMutableLiveData = new MutableLiveData<>(); new Thread(() -> { boolean isMuted = false; try { @@ -795,10 +799,10 @@ public class AccountsVM extends AndroidViewModel { } Handler mainHandler = new Handler(Looper.getMainLooper()); boolean finalIsMuted = isMuted; - Runnable myRunnable = () -> accountMutableLiveData.setValue(finalIsMuted ? target : null); + Runnable myRunnable = () -> booleanMutableLiveData.setValue(finalIsMuted); mainHandler.post(myRunnable); }).start(); - return accountMutableLiveData; + return booleanMutableLiveData; } /** @@ -812,6 +816,7 @@ public class AccountsVM extends AndroidViewModel { try { new MutedAccounts(getApplication().getApplicationContext()).muteAccount(forAccount, target); + addMutedAccount(target); } catch (DBException e) { e.printStackTrace(); } @@ -832,6 +837,7 @@ public class AccountsVM extends AndroidViewModel { new Thread(() -> { try { new MutedAccounts(getApplication().getApplicationContext()).unMuteAccount(forAccount, target); + removeMutedAccount(target); } catch (DBException e) { e.printStackTrace(); } diff --git a/app/src/main/res/layout/drawer_account.xml b/app/src/main/res/layout/drawer_account.xml index 449c8bef..61caa37a 100644 --- a/app/src/main/res/layout/drawer_account.xml +++ b/app/src/main/res/layout/drawer_account.xml @@ -116,6 +116,18 @@ app:iconPadding="0dp" app:strokeWidth="1dp" /> + + Date: Wed, 14 Dec 2022 14:48:32 +0100 Subject: [PATCH 09/19] Mute from lists --- .../android/activities/MastodonListActivity.java | 16 ++++++++++++++++ .../android/activities/ProfileActivity.java | 2 -- .../fedilab/android/ui/drawer/StatusAdapter.java | 1 - .../android/viewmodel/mastodon/AccountsVM.java | 1 + app/src/main/res/menu/menu_list.xml | 5 +++++ app/src/main/res/values/strings.xml | 3 +++ 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/app/fedilab/android/activities/MastodonListActivity.java b/app/src/main/java/app/fedilab/android/activities/MastodonListActivity.java index 0d451652..0d621931 100644 --- a/app/src/main/java/app/fedilab/android/activities/MastodonListActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/MastodonListActivity.java @@ -143,6 +143,22 @@ public class MastodonListActivity extends BaseBarActivity implements MastodonLis if (item.getItemId() == android.R.id.home) { onBackPressed(); return true; + } else if (item.getItemId() == R.id.action_user_mute_home) { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MastodonListActivity.this, Helper.dialogStyle()); + dialogBuilder.setTitle(R.string.put_all_accounts_in_home_muted); + dialogBuilder.setPositiveButton(R.string.mute_them_all, (dialog, id) -> { + timelinesVM.getAccountsInList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, mastodonList.id, null, null, 0) + .observe(MastodonListActivity.this, accounts -> { + if (accounts != null && accounts.size() > 0) { + for (Account account : accounts) { + accountsVM.muteHome(MainActivity.currentAccount, account); + } + } + }); + dialog.dismiss(); + }); + dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); + dialogBuilder.show(); } else if (item.getItemId() == R.id.action_manage_users) { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MastodonListActivity.this, Helper.dialogStyle()); PopupManageAccountsListBinding popupManageAccountsListBinding = PopupManageAccountsListBinding.inflate(getLayoutInflater()); diff --git a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java index 022c6512..97b13d76 100644 --- a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java @@ -16,7 +16,6 @@ package app.fedilab.android.activities; import static app.fedilab.android.BaseMainActivity.currentAccount; -import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction; import android.content.BroadcastReceiver; import android.content.ClipData; @@ -1020,7 +1019,6 @@ public class ProfileActivity extends BaseActivity { .observe(ProfileActivity.this, account -> { homeMuted = true; invalidateOptionsMenu(); - sendAction(ProfileActivity.this, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, account.id); Toasty.info(ProfileActivity.this, getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); })); } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index 5861c8b1..fc873348 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -1662,7 +1662,6 @@ public class StatusAdapter extends RecyclerView.Adapter builderInner.setNeutralButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); builderInner.setPositiveButton(R.string.action_mute, (dialog, which) -> accountsVM.muteHome(currentAccount, statusToDeal.account) .observe((LifecycleOwner) context, account -> { - sendAction(context, Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, statusToDeal.account.id); Toasty.info(context, context.getString(R.string.toast_mute), Toasty.LENGTH_LONG).show(); })); builderInner.show(); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index f24b257d..b8032f6a 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -821,6 +821,7 @@ public class AccountsVM extends AndroidViewModel { e.printStackTrace(); } Handler mainHandler = new Handler(Looper.getMainLooper()); + sendAction(getApplication().getApplicationContext(), Helper.ARG_STATUS_ACCOUNT_ID_DELETED, null, target.id); Runnable myRunnable = () -> accountMutableLiveData.setValue(target); mainHandler.post(myRunnable); }).start(); diff --git a/app/src/main/res/menu/menu_list.xml b/app/src/main/res/menu/menu_list.xml index 95b2b0f3..b59c627b 100644 --- a/app/src/main/res/menu/menu_list.xml +++ b/app/src/main/res/menu/menu_list.xml @@ -11,6 +11,11 @@ android:icon="@drawable/ic_baseline_edit_note_24" android:title="@string/action_lists_edit" app:showAsAction="ifRoom" /> + Unfollow tag Mute for home Unmute for home + Add all users in muted home + All accounts will be muted for the Home timeline. + Mute them all \ No newline at end of file From 15829da7769583deac1033d19c9a65af2f1c25f6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 14 Dec 2022 15:08:10 +0100 Subject: [PATCH 10/19] Release 3.11.1 --- app/build.gradle | 4 ++-- app/src/main/assets/release_notes/notes.json | 5 +++++ src/fdroid/fastlane/metadata/android/en/changelogs/447.txt | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/fdroid/fastlane/metadata/android/en/changelogs/447.txt diff --git a/app/build.gradle b/app/build.gradle index d22d76ee..b2fa994e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { defaultConfig { minSdk 21 targetSdk 32 - versionCode 446 - versionName "3.11.0" + versionCode 447 + versionName "3.11.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } flavorDimensions "default" diff --git a/app/src/main/assets/release_notes/notes.json b/app/src/main/assets/release_notes/notes.json index f3818d4c..ea9247c4 100644 --- a/app/src/main/assets/release_notes/notes.json +++ b/app/src/main/assets/release_notes/notes.json @@ -1,4 +1,9 @@ [ + { + "version": "3.11.1", + "code": "447", + "note": "Added:\n- Mute/Unmute accounts in the Home timeline from their messages or their profiles\n- Add all users from a list to \"Muted home\" in one click\n- Display/Manage users that are muted for home" + }, { "version": "3.11.0", "code": "446", diff --git a/src/fdroid/fastlane/metadata/android/en/changelogs/447.txt b/src/fdroid/fastlane/metadata/android/en/changelogs/447.txt new file mode 100644 index 00000000..0c1c477d --- /dev/null +++ b/src/fdroid/fastlane/metadata/android/en/changelogs/447.txt @@ -0,0 +1,4 @@ +Added: +- Mute/Unmute accounts in the Home timeline from their messages or their profiles +- Add all users from a list to "Muted home" in one click +- Display/Manage users that are muted for home From a1542f8cf8ff0ffca59c5eea990a5acfb3ff56b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Jel=C3=ADnek?= Date: Thu, 15 Dec 2022 09:48:26 +0100 Subject: [PATCH 11/19] Translated using Weblate (Czech) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 98.0% (972 of 991 strings) Co-authored-by: Lukáš Jelínek Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/cs/ Translation: Fedilab/Strings --- app/src/main/res/values-cs/strings.xml | 66 ++++++++++++++------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 537c7503..c104834e 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -159,9 +159,11 @@ Zpráva byla naplánována! Plánované datum musí být vyšší než aktuální hodina! - Časový interval pro ztlumení musí být vyšší než jedna minuta. - %1$s byl ztlumen až do %2$s. \n Ztišení účtu můžete zrušit z jeho/její profilové stránky. - %1$s je ztlumen do %2$s. \n Klikněte zde pro zrušení ztišení. + Časový interval pro ztlumení musí být delší než jedna minuta. + %1$s byl ztlumen až do %2$s. +\n Ztlumení účtu můžete zrušit z jeho/její profilové stránky. + %1$s je ztlumen do %2$s. +\n Klikněte zde pro zrušení ztlumení. Žádné upozornění k zobrazení vás zmínil(a) @@ -194,7 +196,7 @@ Nelze vykonat akci Při překladu došlo k chybě! - Počet zpráv pro jedno nahrání + Počet zpráv pro jedno načtení Zakázat GIF avatary Upozornit, když vás někdo začne sledovat Upozornit, když někdo boostne váš status @@ -314,7 +316,9 @@ Stahování médií Vybrat tón Zapnout rozvrh oznámení - Určitě chcete zablokovat %s?\n\nJiž z této domény neuvidíte ve všech veřejných časových osách ani v oznámeních žádný obsah. Vaši sledující z této domény budou odstraněni. + Určitě chcete zablokovat %s\? +\n +\nJiž z této domény neuvidíte ve všech veřejných časových osách ani v oznámeních žádný obsah. Vaši sledující z této domény budou odstraněni. Zablokovat doménu Doména je blokována Načítám vzdálený status @@ -332,9 +336,9 @@ Naplánovat boost Boost je naplánován! Žádný naplánovaný boost k zobrazení! - Otevřete nabídku + Otevřít nabídku Profilový obrázek - Profilová hlavička + Hlavička profilu Kontaktovat administrátora instance Logo MastoHost Výběr emotikonů @@ -384,7 +388,7 @@ Seznam blokovaných volání Odeslat Filtrovat časovou osu s hashtagy - Žádné hashtagy + Žádné tagy Při sdílení URL připojit obrázek Vytvořit anketu @@ -415,14 +419,14 @@ Filtr Štětec Zahodit - Ukladáno… + Ukladání… Obrázek byl úspěšně uložen! Nepodařilo se uložit obrázek Přidat položku ankety - Ztišit konverzaci - Zrušit umlčení konverzace - Konverzace už není umlčená! - Konverzace je umlčená + Ztlumit konverzaci + Zrušit ztlumení konverzace + Konverzace už není ztlumená! + Konverzace je ztlumená Základní Regionální Umění @@ -433,7 +437,7 @@ Jídlo Logo instance Připojte se k Mastodonu - Choose an instance by picking up a category, then tap on a check button. + K získání seznamu instancí vyberte kategorii, potom si klepnutím zvolte instanci, kterou chcete. %1$s uživatelů Potvrdit heslo Souhlasím s %1$s a %2$s @@ -466,20 +470,20 @@ Pozastaveno Oprávnění Vypnout - Silence + Ztišit Účet - Undo silence + Zrušit ztišení Zrušit vypnutí Pozastavit Zrušit pozastavení Zvuk Hlasová zpráva - During the time slot, the app will send notifications. You can reverse (ie: silent) this time slot with the right spinner. + Během časového úseku budu aplikace posílat upozornění. Můžete to pro tento úsek změnit (tzn. ztišit) pomocí ovládacího prvku vpravo. Náhledy nebudou v časových osách oříznuty - Automatically insert a line break after the mention to capitalize the first letter + Automaticky vkládat zalomení řádku za zmínku, aby bylo první písmeno velké Umožňuje tvůrcům obsahu sdílet statusy do jejich kanálů RSS Vytváření - Select + Vybrat Přidat instanci Zapnout hlášení o pádech aplikace Pokud je zapnuto, místně se vytvoří hlášení o pádu a pak ho budete moci sdílet. @@ -525,13 +529,13 @@ Odkazy Změnit ve zprávách barvu odkazů (URL, zmínek, tagů apod.) Hlavička reblogů - Change the color of display name at the top of messages - Change the color of the user name at the top of messages + Změnit barvu zobrazovaného jména nad zprávami + Změnit barvu uživatelského jména nad zprávami Změnit barvu hlavičky pro reblogy Příspěvky Barva pozadí příspěvků v časových osách Resetovat barvy - Tap here to reset all your custom colors + Klepněte zde k resetu všech vašich vlastních barev Reset Ikony Barva dolních ikon v časových osách @@ -546,14 +550,14 @@ Téma bylo exportováno Téma bylo úspěšně exportováno do CSV Importovat téma - Tap here to import a theme from a previous export + Klepněte zde k importu tématu z předchozího exportu Exportovat téma - Tap here to export the current theme + Klepněte zde k exportu aktuálního tématu Při výběru souboru s tématem došlo k chybě Počet uživatelů Počet statusů Počet instancí - End in %s + Konec za %s Tato instance není k dispozici na https://instances.social Zobrazit úplný odkaz Sdílet odkaz @@ -605,7 +609,7 @@ Filtr Velikosti ikon Výchozí viditelnost zpráv: - Počet upozornění na jedno nahrání + Počet upozornění na jedno načtení Doména frontendu Redditu Skrýt obsah < Je to spam @@ -625,7 +629,7 @@ Která pravidla jsou porušována\? Připojte se k fediverse Smazat pole - Nahrát více zpráv… + Načíst více zpráv… Použít alternativní frontend pro YouTube Použít alternativní frontend pro Twitter YouTube @@ -649,7 +653,7 @@ Vždy zobrazovat tlačítko pro záložky Spodní nabídka "Oblíbené také u: " - Klepněte zde pro aktualizaci hlasování + Klepněte zde pro znovunačtení ankety Média se nepovedlo nahrát! Načíst náhledy pro média Zobrazovat média @@ -699,7 +703,7 @@ Upravit zprávu Zpráva byla přidána do vašich záložek! Zpráva byla odebrána z vašich záložek! - Počet účtů na jedno nahrání + Počet účtů na jedno načtení Hudba Doména frontendu YouTube Toto pole nesmí být prázdné! @@ -711,7 +715,7 @@ Uložit změny Účet bota Ukázat obsah > - Neuvidíte jejich příspěvky. Mohou vás stále sledovat a vidět vaše příspěvky a nedozví se, že jste je umlčeli. + Neuvidíte jejich příspěvky. Mohou vás stále sledovat a vidět vaše příspěvky a nedozví se, že jste je ztlumili. Je ještě něco jiného, co si myslíte, že bychom měli vědět\? Profil byl aktualizován! Název seznamu není platný! @@ -721,7 +725,7 @@ Ahoj! Zveme vás k připojení do Fediverse. Zmínky Odemčeno - Umlčet %1$s + Ztlumit %1$s Přidat pole Zde jsou volby ovládající, co uvidíte na Mastodonu: Nesledovat %1$s From edf4f0130968abb47b4a9ebece18068b3ff22c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Ersen?= Date: Thu, 15 Dec 2022 09:48:26 +0100 Subject: [PATCH 12/19] Translated using Weblate (Turkish) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (991 of 991 strings) Co-authored-by: Oğuz Ersen Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/tr/ Translation: Fedilab/Strings --- app/src/main/res/values-tr/strings.xml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 0c930bfa..dd7ccea5 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -226,7 +226,7 @@ Takip Et Engeli kaldır Sustur - Sesi aç + Susturmaktan vazgeç İstek gönderildi Sizi takip ediyor Cevaplarda ilk harf büyük olsun @@ -647,8 +647,8 @@ %1$s bildiriliyor Kötü amaçlı bağlantılar, sahte etkileşim veya tekrarlayan yanıtlar Bu hesabı takip ediyorsunuz. Gönderilerini artık ana akışınızda görmemek için onları takip etmeyi bırakın. - %1$s sesini kapat - Onların gönderilerini görmeyeceksiniz. Yine de sizi takip edebilir ve gönderilerinizi görebilirler ve sessize alındıklarını bilmezler. + %1$s sustur + Onların gönderilerini görmeyeceksiniz. Yine de sizi takip edebilir ve gönderilerinizi görebilirler ve susturulduklarını bilmezler. %1$s engelle Bu bildirimi destekleyen herhangi bir gönderi var mı\? Hesap başka bir sunucudan. Bildirimin anonimleştirilmiş bir kopyası da oraya gönderilsin mi\? @@ -899,7 +899,7 @@ Moderatörler tarafından özel kullanım için bu etki alanı sınırlaması hakkında yorum yapın. Etki alanı sınırlamaları listesinin tanıtılması etkinleştirilmişse listedeki etki alanı adını kısmen gizleyin Etki alanı sınırlamaları listesinin tanıtılması etkinleştirilmişse, bu etki alanı sınırlaması hakkında herkese açık yorum yapın. - %1$s etiketini sessize almak istediğinizden emin misiniz\? + %1$s etiketini susturmak istediğinizden emin misiniz\? Renkleri özelleştir Temalar için özel renklerinizi ayarlamanıza izin verir. Değişken Renk @@ -920,10 +920,16 @@ Görüşme sizin sunucunuzda başladı! Lütfen daha sonra tekrar deneyin. Uygulama uzak mesajı bulamadı. - Etiketi sessize al + Etiketi sustur Etiketin sabitlemesini kaldır Her zaman çevir düğmesini göster - Etiketin sesini aç + Etiketi susturmaktan vazgeç Etiketi sabitle Etiketi takibi bırak + Ana sayfada susturulan kullanıcılar + Ana sayfa zaman çizelgesi için tüm hesaplar susturulacaktır. + Tümünü sustur + Ana sayfa için susturmaktan vazgeç + Tüm kullanıcıları ana sayfada susturmaya ekle + Ana sayfa için sustur \ No newline at end of file From d7976734ce46a15e35f964e867d8449771d47855 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 15 Dec 2022 10:46:31 +0100 Subject: [PATCH 13/19] Fix issue #636 - Freeze with the app. --- .../main/java/app/fedilab/android/helper/SpannableHelper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java index 0d5b7bf3..03e9a52c 100644 --- a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java @@ -494,7 +494,9 @@ public class SpannableHelper { contentUrl = new SpannableString(Html.fromHtml(value, Html.FROM_HTML_MODE_LEGACY)); else contentUrl = new SpannableString(Html.fromHtml(value)); - + if (contentUrl.toString().trim().isEmpty()) { + continue; + } Pattern word = Pattern.compile(Pattern.quote(contentUrl.toString())); Matcher matcherLink = word.matcher(content); while (matcherLink.find()) { From 852f4e7f7a5b8ee9eabd727199aa92d13d0b5520 Mon Sep 17 00:00:00 2001 From: Screenshared Date: Thu, 15 Dec 2022 13:32:27 +0100 Subject: [PATCH 14/19] Translated using Weblate (Italian) Currently translated at 96.5% (957 of 991 strings) Co-authored-by: Screenshared Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/it/ Translation: Fedilab/Strings --- app/src/main/res/values-it/strings.xml | 329 ++++++++++++++++++++++++- 1 file changed, 323 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5f488678..fb5e7af9 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -29,7 +29,7 @@ Fotocamera Elimina tutto Pianifica - Dimensioni testo e icona + Dimensioni testo Successivo Precedente Apri con @@ -105,18 +105,22 @@ %d g %d secondo + %d secondi %d secondi %d minuto + %d minuti %d minuti %d ora + %d ore %d ore %d giorno + %d giorni %d giorni @@ -309,7 +313,9 @@ Scarica i media Seleziona tono Abilita fascia oraria - Sei sicuro di voler bloccare %s\? + Sei sicuro di voler bloccare %s\? +\nNon vedrai i contenuti di quel dominio in nessuna timeline pubblica e nelle notifiche. +\nI tuoi followers di quel dominio saranno rimossi. Blocca dominio Il dominio è bloccato Recupero dello stato remoto @@ -350,7 +356,7 @@ Lingue Solo media Mostra NSFW - Bot + Istanza Pixelfed Istanza Mastodon Qualsiasi tra queste @@ -424,7 +430,7 @@ Attivismo Gioco Tecnologia - Furry + Cibo Icona dell\'istanza Unisciti a Mastodon @@ -487,6 +493,7 @@ Segnala account %d votante + %d Votanti %d votanti @@ -508,7 +515,7 @@ Vuoi smettere di seguire questo account? Mostra finestra di conferma prima di smettere di seguire Replace Medium links - Replace medium.com links with an open source alternative front-end focused on privacy. + Usa un frontend alternativo per Medium Default: scribe.rip Usa un sistema di notifiche push per ricevere notifiche in tempo reale. Aggiungi note @@ -534,7 +541,7 @@ Scegli un\'azione Traduzione Colore del testo - Cambia il colore del testo nei riquadri + Cambia il colore del testo nei messaggi Usa un tema personalizzato Temi Il tema è stato esportato @@ -586,4 +593,314 @@ Il messaggio è stato aggiunto ai tuoi preferiti! Il messaggio è stato rimosso dai tuoi preferiti! Numero di account per caricamento + Approvato + Twitter + É offline! + Controllato il: %s + Barra azione singola + Se abilitato, l\'app avrà solo una singola barra per timeline + Timeline in lista + Nuovo aggiornamento + Nuova iscrizione + Nuova segnalazione + Un messaggio che hai condiviso è stato modificato + Mostra contenuto > + Ferma registrazione + Si tratta di altro + Stai seguendo questo account. Per non vedere più i suoi post sul tuo home feed, smetti di seguirlo. + L\'account proviene da un altro server. Vuoi inviare una copia anonima del report anche a quel server\? + Quali regole si stanno violando\? + Bloccato + Durante questo intervallo + Usa la cache + Rispondi + Mostra opzioni + Non confermato + Non segui alcuna etichetta! + Account silenziato + Stato + Segui etichetta + Etichette seguite + Modifica messaggio + Nascondi completamente + Nascondi il contenuto filtrato con un avviso con il titolo del filtro + Titolo + Home e liste + Sei sicuro di non voler fissare quella timeline\? + Domini + Nuova segnalazione (moderatori) + Ordine liste + Rifiuta segnalazioni + Tipo di notifiche + Sei sicuro di voler silenziare l\'etichetta %1$s\? + Scegli il tipo di notifiche + Seleziona un tema + Filtro + Approva + I media non possono essere caricati! + Imposta il ritardo tra ogni aggiornamento + Quando abilitato, tutte le timeline fissate saranno mostrate in un menú a tendina + Apri messaggio originale + %1$s modificato %2$s + Mostra sempre il bottone di traduzione + Mostra + L\'app ha fallito nel ricevere un token + Cronologia messaggio + Modificato %1$s + Creato %1$s + Aggiornamenti + Filtrato: %1$s + Mostra profilo remoto + Non hai domini bloccati + Vuoi sbloccare %1$s\? + Notifica aggiornamenti + Nuova registrazione(moderatori) + Apri con un altro account + Dimensioni icona + Numero di notifiche per caricamento + Musica + Inviando messaggio %d/%d + É online! + Preferiti + Nascondi contenuto< + Muta %1$s + Commenti aggiuntivi + Non hai un account\? + Unisciti al fediverso + Aggiungi filtro + La mia istanza + La mia app + Suggerimenti + Menzioni + Scegli se la base del tema debba essere scura o chiara + Ricondiviso anche da: + Forma + Messaggi in cache + Note aggiornamento + Esporta impostazioni + Scegli una modalità per il tema + Tema scuro default + Durata del sondaggio: + Dominio + Disabilita notifiche + Temi dai contribuenti + Modalità gomma + Controlla notifiche ogni: + Importa impostazioni + Un utente si è registrato + Un utente ha inviato una segnalazione + Questo campo non può essere vuoto! + Registrazioni + Usa un frontend alternativo per Twitter + Le impostazioni sono state esportate con successo + Le impostazioni sono state importate con successo + Continua + Dicci cosa non va con questo post + Viola le regole del server + Non sai se violi delle regole specifiche + Il problema non rientra nelle altre categorie + Non vuoi vederlo\? + Qui ci sono le tue opzioni per controllare cosa vedi su Mastodon: + Blocca %1$s + C\'é qualcos\'altro che vorresti aggiungere\? + Versione: %s +\n%s utenti -%s stati + Scegli l\'opzione migliore + Non seguire %1$s + Ciao! Ti inviatiamo ad unirti al fediverso. + Aggiornamenti dalle persone + Cancella tutte le notifiche + Salva modifiche + Mostra tutte le categorie + Interazioni + Aggiungi campo + Sbloccato + Sei sicuro di voler eliminare il campo\? + Schedulato + Il nome della lista non é valido! + Mostra sempre il pulsante segnalibro + Menú inferiore + Barra del menú superiore + "Preferito anche da: " + Ultima volta attivo + Risolto + Clicca qui per aggiornare il sondaggio + Annunci %1$s - %2$s + Elimina cache + Grandezza file cache + Usa la lingua di sistema + Apri bozza + Tempo controllo notifiche + Mostra i media + Mostra le timeline + Ricorda posizione nelle timeline + Aggrega notifiche + Mostra i media nelle notifiche + Cambia logo + Cambia il logo dell\'app sul dispositivo + Fissa messaggio + Non fissare messaggio + Modifica messaggio + Moderatore + Assegnamelo + Non assegnare + Le notifiche sono state rimosse dalla cache. + Segnala + Non seguire etichetta + Smettere di seguire questa etichetta\? + Scrivi l\'etichetta da seguire + Profili + La tua istanza non supporta questa feature! + Nascondi avviso + Nascondi completamente il contenuto filtrato, come se non esistesse + Parola chiave o frase + Elimina parola chiave + Aggiungi parola chiave + L\'app non é riuscita a trovare dati remoti! + Invia una segnalazione + Non interessato + Politiche sulla privacy + Rimuovere timeline fissate\? + Eliminare le timeline fissate\? + Mantieni notifiche + Rifiuta media + Rifiuta segnalazioni + Il blocco di dominio non previene la creazione di account nel database, ma applicherà retroattivamente e automaticamente metodi specifici di moderazione su questi account. + Gravità + Il silenziamento renderà i post dell\'account invisibili a tutti quelli che non lo seguono.La sospensione rimuoverà tutti i contenuti dell\'account, media e dati del profilo. Usa nessuno se vuoi solo rifiutare i media. + Ignora tutte le segnalazioni provenienti da questo dominio.Irrelevante per le sospensioni + Cards in sovraimpressione + Se abilitato, gli oggetti nelle timeline avranno un\'ombra e un elevazione. + Personalizza tema chiaro + Non silenziare per la home + Personalizza tema scuro + Permette di personalizzare alcuni elementi nei messaggi per il tema scuro. + Muta tutti + Le timeline sarranno mantenute in cache in modo da velocizzare l\'app. + Mostra i media nelle notifiche di preferiti e condivisioni + Scegli un logo + Traduci messaggi + Forza traduzione in una lingua specifica.Scegli la prima opzione per resettarla alle impostazioni del dispositivo + Utente + Amministratore + Indentazioni massime nei threads + Risposte non in lista + Riguarda solo le risposte pubbliche.Se abilitato, le tue risposte avranno automaticamente la visibilità \"non in lista\" invece di \"pubblico\" + Stato email + Stato login + Unito + IP recente + Permetti + Avvisa + Notifica user per email + Avviso personalizzato + Status segnalazioni + Silenziato + Permette di ridurre la lista della lingua del post quando si compone un messaggio. + Riavviare l\'app\? + Riavvia + Devi riavviare l\'app per applicare le modifiche. + Personalizzato + L\'istanza non sembra essere valida! + Solo followers + Aggiungi status + Preferito da + Altro + Es.: contenuto sensibile + Permette di creare il tuo tema personalizzato + Suoni delle notifiche + Modifica lista + Rimuovi status + Scegli un tema creato dai contribuenti + Sono un moderatore + Account bot + Nessun account trovato per questa lista! + Base del tema + Conferma unfollow + Altre azioni + Silenzia per la home + È spam + Segnala %1$s + Aggiungi tutti gli utenti nella home silenziata + Tipo di notifiche da mostrare + Origine dell\'account segnalato + Lingua dei messaggi + Il mio account + Controlla notifiche + Mostra contatori + Account avvisato + Account non sospeso + Account sospeso + Account abilitato + Account disabilitato + Invia una segnalazione + Iscritto + Rifiuta file media + Commento pubblico + Commento privato + Modifiche salvate! + Personalizza colori + Colore dinamico + Allinea la tonalità con il colore dello sfondo del dispositivo. + Tutti gli account saranno silenziati per la timeline della Home. + Usa un frontend alternativo per Instagram + Usa un fronten alternativo per Reddit + Piú recente + Pulisci la cache + Sei sicuro di voler pulire la cache\? Se hai bozze con media, andranno persi. + Le impostazioni sono state esportate + Invio messaggio… + Non è qualcosa che vorresti vedere + Non vedrai i suoi post.Non potrà vedere i tuoi post o seguirti.Saprà di essere stato bloccato. + Campo eliminato + Personalizza timelines + Server mutati + Il profilo é stato aggiornato! + Linea + Località + Ovale + Rettangolo + Non vedrai i suoi post. Potrà ancora seguirti e vedere i tuoi post e non saprà che l\'hai mutato. + Inviato a %1$s + Il messaggio è stato inviato! + Tipo di sondaggio: + Il report é stato inviato! + \"Mastodon non é un singolo sito come Twitter o Facebook, é una rete di migliaia di communità gestite da organizzazioni e individui differenti che forniscono un\'esperienza social integrata.\" + Segna tutte le notifiche come lette + Sei sicuro di voler eliminare tutte le notifiche\? L\'azione non puó essere annulata. + Risultati sondaggio + Vuoi uscire senza salvare l\'immagine\? + Permessi non abilitati! + Mostra contatori per i messaggi + Mostra anteprime per i media + Imposta numero massimo di caratteri + Carica impostazioni esportate + Mostrerà un contatore nel tab delle timeline per i nuovi messaggi + Se abiliato, l\'app aggregherà le notifiche della stessa tipologia + Segna come risolto + Segna come irrisolto + Account non silenziato + Confermato + Account rifiutato + Account approvato + Segui etichetta + Il nome etichetta non é valido! + Quarda i trends di questa istanza + Domini bloccati + Domini sbloccati + Nascondi nome dominio + Ignora tutte le segnalazioni provenienti da questo dominio.Irrilevante per le sospensioni + Crea un blocco dominio + Commento privato riguardo le limitazioni di questo dominio per uso interno dei moderatori. + Commento pubblico riguardo questo dominio, se é abilitata la lista delle limitazioni del dominio. + Permette di impostare un colore personalizzato per i temi. + Tema chiaro default + Permette di personalizzare alcuni elementi nei messaggi per il tema chiaro. + Il messaggio non é piú fissato! + Il messaggio é stato fissato + Filtra azione + Scegli quale azione eseguire quando un post corrisponde al filtro + Mostra comunque + L\'app non é riuscita ad aggiungere l\'account nella lista! + Elimina timeline \ No newline at end of file From b212e90bf0e5ba0dcaeec1eca8e16c7703cdd540 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 15 Dec 2022 13:32:27 +0100 Subject: [PATCH 15/19] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/ Translation: Fedilab/Strings --- app/src/main/res/values-it/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index fb5e7af9..7146b374 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -356,7 +356,6 @@ Lingue Solo media Mostra NSFW - Istanza Pixelfed Istanza Mastodon Qualsiasi tra queste @@ -430,7 +429,6 @@ Attivismo Gioco Tecnologia - Cibo Icona dell\'istanza Unisciti a Mastodon From c04462e19bd345d551cf8828a2a1fafeb99b6121 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 15 Dec 2022 16:52:51 +0100 Subject: [PATCH 16/19] Fix a crash --- .../app/fedilab/android/ui/fragment/media/FragmentMedia.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java index 8339f037..061f756e 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/media/FragmentMedia.java @@ -92,7 +92,7 @@ public class FragmentMedia extends Fragment { return; } canSwipe = (binding.mediaPicture.getScale() == 1); - if (!canSwipe) { + if (!canSwipe && !requireActivity().isFinishing() && isAdded()) { if (!((MediaActivity) requireActivity()).getFullScreen()) { ((MediaActivity) requireActivity()).setFullscreen(true); } From f35ac8ae6b19054b672fa757ba849c90f96d207b Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 15 Dec 2022 18:17:27 +0100 Subject: [PATCH 17/19] Improve filters --- .../main/java/app/fedilab/android/helper/TimelineHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java b/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java index f2e3fe59..66b01ba8 100644 --- a/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java @@ -154,7 +154,7 @@ public class TimelineHelper { if (filterTimeLineType == Timeline.TimeLineEnum.HOME) { if (filteredAccounts != null && filteredAccounts.size() > 0) { for (Account account : filteredAccounts) { - if (account.acct.equals(status.account.acct)) { + if (account.acct.equals(status.account.acct) || (status.reblog != null && account.acct.equals(status.reblog.account.acct))) { Filter filterCustom = new Filter(); filterCustom.filter_action = "hide"; ArrayList contextCustom = new ArrayList<>(); From 8ff82233782e2ce2949539ab10b4d08882bdd6f2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 15 Dec 2022 18:19:19 +0100 Subject: [PATCH 18/19] Release 3.11.2 --- app/src/main/assets/release_notes/notes.json | 6 +++--- src/fdroid/fastlane/metadata/android/en/changelogs/448.txt | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 src/fdroid/fastlane/metadata/android/en/changelogs/448.txt diff --git a/app/src/main/assets/release_notes/notes.json b/app/src/main/assets/release_notes/notes.json index ea9247c4..36a49bee 100644 --- a/app/src/main/assets/release_notes/notes.json +++ b/app/src/main/assets/release_notes/notes.json @@ -1,8 +1,8 @@ [ { - "version": "3.11.1", - "code": "447", - "note": "Added:\n- Mute/Unmute accounts in the Home timeline from their messages or their profiles\n- Add all users from a list to \"Muted home\" in one click\n- Display/Manage users that are muted for home" + "version": "3.11.2", + "code": "448", + "note": "Added:\n- Mute/Unmute accounts in the Home timeline from their messages or their profiles\n- Add all users from a list to \"Muted home\" in one click\n- Display/Manage users that are muted for home\n\nFixed:\n- Timeline crashes" }, { "version": "3.11.0", diff --git a/src/fdroid/fastlane/metadata/android/en/changelogs/448.txt b/src/fdroid/fastlane/metadata/android/en/changelogs/448.txt new file mode 100644 index 00000000..54eba4c5 --- /dev/null +++ b/src/fdroid/fastlane/metadata/android/en/changelogs/448.txt @@ -0,0 +1,7 @@ +Added: +- Mute/Unmute accounts in the Home timeline from their messages or their profiles +- Add all users from a list to "Muted home" in one click +- Display/Manage users that are muted for home + +Fixed: +- Timeline crashes \ No newline at end of file From 4ec3a430bd90cde6be7428ada0fab3020992a334 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 15 Dec 2022 18:25:05 +0100 Subject: [PATCH 19/19] Release 3.11.2 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b2fa994e..413135ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { defaultConfig { minSdk 21 targetSdk 32 - versionCode 447 - versionName "3.11.1" + versionCode 448 + versionName "3.11.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } flavorDimensions "default"