Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2021-06-17 18:30:59 +0300
committerStefan Niedermann <info@niedermann.it>2021-06-17 18:31:10 +0300
commitb108515abae3a9523179f4e576545335978fcbfd (patch)
tree37936d02d4f59d5b5174d21c63b650f30203723d
parent5fa1024e4a63e2e85cd94f6d7e237d8d3a7b549b (diff)
parent34458e8c3bc02daae17872b2ab0671d20119a8ce (diff)
Merge branch 'master' into create-card-before-editing
Signed-off-by: Stefan Niedermann <info@niedermann.it> # Conflicts: # app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
-rw-r--r--app/build.gradle2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java70
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/extrawurst/UserSearchLiveData.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java15
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/NewCardDialog.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java12
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsViewModel.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/filter/FilterWidget.java18
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidget.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidget.java25
-rw-r--r--app/src/main/res/layout/activity_exception.xml4
-rw-r--r--app/src/main/res/values/strings.xml10
-rw-r--r--app/src/main/res/xml/searchable.xml4
15 files changed, 132 insertions, 78 deletions
diff --git a/app/build.gradle b/app/build.gradle
index fa5e6f8d6..d2477e60a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -121,7 +121,7 @@ dependencies {
// Tests
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.5.1'
- testImplementation 'org.mockito:mockito-core:3.11.0'
+ testImplementation 'org.mockito:mockito-core:3.11.1'
testImplementation 'androidx.test:core:1.3.0'
testImplementation 'androidx.arch.core:core-testing:2.1.0'
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java
index 10a18bb09..059ed5e6b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java
@@ -6,38 +6,24 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.Observer;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
import static androidx.lifecycle.Transformations.distinctUntilChanged;
public class LiveDataHelper {
- public interface DataChangeProcessor<T> {
- void onDataChanged(T data);
+ private LiveDataHelper() {
+ throw new UnsupportedOperationException("This class must not be instantiated.");
}
- public interface DataTransformator<I, O> {
- O transform(I data);
- }
-
- public interface LiveDataWrapper<T> {
- T getData();
-
- default void postResult(WrappedLiveData<T> liveData) {
- liveData.setError(null);
- T data = null;
- try {
- data = getData();
- } catch (RuntimeException e) {
- liveData.setError(e);
- }
- liveData.postValue(data);
- }
- }
+ private static final ExecutorService executor = Executors.newCachedThreadPool();
public static <T> LiveData<T> interceptLiveData(LiveData<T> data, DataChangeProcessor<T> onDataChange) {
MediatorLiveData<T> ret = new MediatorLiveData<>();
ret.addSource(data, changedData ->
- doAsync(() -> {
+ executor.submit(() -> {
onDataChange.onDataChanged(changedData);
ret.postValue(changedData);
})
@@ -47,32 +33,29 @@ public class LiveDataHelper {
public static <I, O> LiveData<O> postCustomValue(LiveData<I> data, DataTransformator<I, O> transformator) {
- MediatorLiveData<O> ret = new MediatorLiveData<>();
-
- ret.addSource(data, changedData -> doAsync(() -> ret.postValue(transformator.transform(changedData))));
+ final MediatorLiveData<O> ret = new MediatorLiveData<>();
+ ret.addSource(data, changedData -> executor.submit(() -> ret.postValue(transformator.transform(changedData))));
return distinctUntilChanged(ret);
}
public static <I> MediatorLiveData<I> of(I oneShot) {
- MediatorLiveData<I> ret = new MediatorLiveData<I>() {
+ return new MediatorLiveData<I>() {
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, observer);
- doAsync(() -> postValue(oneShot));
+ executor.submit(() -> postValue(oneShot));
}
};
- return ret;
}
public static <I, O> LiveData<O> postSingleValue(LiveData<I> data, DataTransformator<I, O> transformator) {
- MediatorLiveData<O> ret = new MediatorLiveData<>();
-
- ret.addSource(data, changedData -> doAsync(() -> ret.postValue(transformator.transform(changedData))));
+ final MediatorLiveData<O> ret = new MediatorLiveData<>();
+ ret.addSource(data, changedData -> executor.submit(() -> ret.postValue(transformator.transform(changedData))));
return distinctUntilChanged(ret);
}
public static <T> void observeOnce(LiveData<T> liveData, LifecycleOwner owner, Observer<T> observer) {
- Observer<T> tempObserver = new Observer<T>() {
+ final Observer<T> tempObserver = new Observer<T>() {
@Override
public void onChanged(T result) {
liveData.removeObserver(this);
@@ -85,7 +68,7 @@ public class LiveDataHelper {
public static <T> WrappedLiveData<T> wrapInLiveData(final LiveDataWrapper<T> liveDataWrapper) {
final WrappedLiveData<T> liveData = new WrappedLiveData<>();
- doAsync(() -> {
+ executor.submit(() -> {
try {
liveDataWrapper.postResult(liveData);
} catch (Throwable t) {
@@ -96,7 +79,26 @@ public class LiveDataHelper {
return liveData;
}
- private static void doAsync(Runnable r) {
- new Thread(r).start();
+ public interface DataChangeProcessor<T> {
+ void onDataChanged(T data);
+ }
+
+ public interface DataTransformator<I, O> {
+ O transform(I data);
+ }
+
+ public interface LiveDataWrapper<T> {
+ T getData();
+
+ default void postResult(WrappedLiveData<T> liveData) {
+ liveData.setError(null);
+ T data = null;
+ try {
+ data = getData();
+ } catch (RuntimeException e) {
+ liveData.setError(e);
+ }
+ liveData.postValue(data);
+ }
}
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/extrawurst/UserSearchLiveData.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/extrawurst/UserSearchLiveData.java
index 3d05247b3..4a90664c9 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/extrawurst/UserSearchLiveData.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/extrawurst/UserSearchLiveData.java
@@ -18,12 +18,12 @@ import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.DataBaseAdapter
public class UserSearchLiveData extends MediatorLiveData<List<User>> implements Debouncer.Callback<Long> {
private static final int DEBOUNCE_TIME = 300; // ms
- private DataBaseAdapter db;
- private ServerAdapter server;
+ private final DataBaseAdapter db;
+ private final ServerAdapter server;
long accountId;
String searchTerm;
long notYetAssignedInACL;
- private Debouncer<Long> debouncer = new Debouncer<>(this, DEBOUNCE_TIME);
+ private final Debouncer<Long> debouncer = new Debouncer<>(this, DEBOUNCE_TIME);
public UserSearchLiveData(DataBaseAdapter db, ServerAdapter server) {
this.db = db;
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
index d01ef3d42..79e29c08b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
@@ -3,13 +3,20 @@ package it.niedermann.nextcloud.deck.ui.board;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
+import java.util.Objects;
+
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogTextColorInputBinding;
import it.niedermann.nextcloud.deck.model.full.FullBoard;
@@ -75,6 +82,14 @@ public class EditBoardDialogFragment extends DialogFragment {
return builder.create();
}
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ binding.input.requestFocus();
+ Objects.requireNonNull(requireDialog().getWindow()).setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ return super.onCreateView(inflater, container, savedInstanceState);
+ }
+
public static DialogFragment newInstance(long boardId) {
final DialogFragment dialog = new EditBoardDialogFragment();
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/NewCardDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/NewCardDialog.java
index 5d60951fe..d133ef029 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/NewCardDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/NewCardDialog.java
@@ -72,8 +72,8 @@ public class NewCardDialog extends DialogFragment implements DialogInterface.OnC
final AlertDialog dialog = new AlertDialog.Builder(requireActivity())
.setTitle(R.string.add_card)
.setView(binding.getRoot())
- .setPositiveButton(R.string.edit, null)
- .setNegativeButton(R.string.simple_save, null)
+ .setPositiveButton(R.string.save_and_edit, null)
+ .setNegativeButton(R.string.save_and_close, null)
.create();
dialog.setOnShowListener(d -> {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java
index f1f584df6..4648e34c3 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java
@@ -19,6 +19,8 @@ import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import it.niedermann.android.crosstabdnd.DragAndDropAdapter;
import it.niedermann.android.crosstabdnd.DraggedItemLocalState;
@@ -45,6 +47,7 @@ import static it.niedermann.nextcloud.deck.util.MimeTypeUtil.TEXT_PLAIN;
public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> implements DragAndDropAdapter<FullCard>, CardOptionsItemSelectedListener, Branded {
+ private final ExecutorService executor;
private final boolean compactMode;
@NonNull
protected final MainViewModel mainViewModel;
@@ -66,6 +69,10 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
protected final int maxCoverImages;
public CardAdapter(@NonNull Activity activity, @NonNull FragmentManager fragmentManager, long stackId, @NonNull MainViewModel mainViewModel, @Nullable SelectCardListener selectCardListener) {
+ this(activity, fragmentManager, stackId, mainViewModel, selectCardListener, Executors.newSingleThreadExecutor());
+ }
+
+ private CardAdapter(@NonNull Activity activity, @NonNull FragmentManager fragmentManager, long stackId, @NonNull MainViewModel mainViewModel, @Nullable SelectCardListener selectCardListener, @NonNull ExecutorService executor) {
this.activity = activity;
this.counterMaxValue = this.activity.getString(R.string.counter_max_value);
this.fragmentManager = fragmentManager;
@@ -79,6 +86,7 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
? activity.getResources().getInteger(R.integer.max_cover_images)
: 0;
setHasStableIds(true);
+ this.executor = executor;
}
@Override
@@ -204,10 +212,10 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
.putExtra(Intent.EXTRA_TEXT, CardUtil.getCardContentAsString(activity, fullCard));
activity.startActivity(Intent.createChooser(shareIntent, fullCard.getCard().getTitle()));
} else if (itemId == R.id.action_card_assign) {
- new Thread(() -> mainViewModel.assignUserToCard(mainViewModel.getUserByUidDirectly(fullCard.getCard().getAccountId(), account.getUserName()), fullCard.getCard())).start();
+ executor.submit(() -> mainViewModel.assignUserToCard(mainViewModel.getUserByUidDirectly(fullCard.getCard().getAccountId(), account.getUserName()), fullCard.getCard()));
return true;
} else if (itemId == R.id.action_card_unassign) {
- new Thread(() -> mainViewModel.unassignUserFromCard(mainViewModel.getUserByUidDirectly(fullCard.getCard().getAccountId(), account.getUserName()), fullCard.getCard())).start();
+ executor.submit(() -> mainViewModel.unassignUserFromCard(mainViewModel.getUserByUidDirectly(fullCard.getCard().getAccountId(), account.getUserName()), fullCard.getCard()));
return true;
} else if (itemId == R.id.action_card_move) {
DeckLog.verbose("[Move card] Launch move dialog for " + Card.class.getSimpleName() + " \"" + fullCard.getCard().getTitle() + "\" (#" + fullCard.getLocalId() + ") from " + Stack.class.getSimpleName() + " #" + +stackId);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
index 4594fcf79..4cf57ba6f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
@@ -38,6 +38,8 @@ import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import id.zelory.compressor.constraint.FormatConstraint;
import id.zelory.compressor.constraint.QualityConstraint;
@@ -95,6 +97,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
private PreviewDialogViewModel previewViewModel;
private BottomSheetBehavior<LinearLayout> mBottomSheetBehaviour;
private boolean compressImagesOnUpload = true;
+ private final ExecutorService executor = Executors.newCachedThreadPool();
private RecyclerView.ItemDecoration galleryItemDecoration;
@@ -404,7 +407,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
DeckLog.verbose("--- found content URL", sourceUri.getPath());
// Separate Thread required because picked file might not yet be locally available
// https://github.com/stefan-niedermann/nextcloud-deck/issues/814
- new Thread(() -> {
+ executor.submit(() -> {
try {
final File originalFile = copyContentUriToTempFile(requireContext(), sourceUri, editViewModel.getAccount().getId(), editViewModel.getFullCard().getLocalId());
requireActivity().runOnUiThread(() -> {
@@ -430,7 +433,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
} catch (IOException e) {
requireActivity().runOnUiThread(() -> ExceptionDialogFragment.newInstance(e, editViewModel.getAccount()).show(getChildFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
}
- }).start();
+ });
break;
}
default: {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsViewModel.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsViewModel.java
index 23336c91f..8914a87ed 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsViewModel.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsViewModel.java
@@ -7,6 +7,8 @@ import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import it.niedermann.nextcloud.deck.api.IResponseCallback;
import it.niedermann.nextcloud.deck.model.Account;
@@ -19,10 +21,12 @@ import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.WrappedLiv
public class UpcomingCardsViewModel extends AndroidViewModel {
private final SyncManager syncManager;
+ private final ExecutorService executor;
public UpcomingCardsViewModel(@NonNull Application application) {
super(application);
this.syncManager = new SyncManager(application);
+ this.executor = Executors.newCachedThreadPool();
}
public LiveData<List<UpcomingCardsAdapterItem>> getUpcomingCards() {
@@ -30,11 +34,11 @@ public class UpcomingCardsViewModel extends AndroidViewModel {
}
public void assignUser(@NonNull Account account, @NonNull Card card) {
- new Thread(() -> syncManager.assignUserToCard(syncManager.getUserByUidDirectly(card.getAccountId(), account.getUserName()), card)).start();
+ executor.submit(() -> syncManager.assignUserToCard(syncManager.getUserByUidDirectly(card.getAccountId(), account.getUserName()), card));
}
public void unassignUser(@NonNull Account account, @NonNull Card card) {
- new Thread(() -> syncManager.unassignUserFromCard(syncManager.getUserByUidDirectly(card.getAccountId(), account.getUserName()), card)).start();
+ executor.submit(() -> syncManager.unassignUserFromCard(syncManager.getUserByUidDirectly(card.getAccountId(), account.getUserName()), card));
}
public void archiveCard(@NonNull FullCard card, @NonNull IResponseCallback<FullCard> callback) {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/filter/FilterWidget.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/filter/FilterWidget.java
index 89d75eeee..56ea508c0 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/filter/FilterWidget.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/filter/FilterWidget.java
@@ -7,7 +7,11 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import androidx.annotation.NonNull;
+
import java.util.NoSuchElementException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.model.Account;
@@ -18,26 +22,26 @@ import static android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE;
public class FilterWidget extends AppWidgetProvider {
public static final String ACCOUNT_KEY = "filter_widget_account";
public static final String BUNDLE_KEY = "filter_widget_bundle";
+ final ExecutorService executor = Executors.newCachedThreadPool();
- static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds, Account account) {
+ static void updateAppWidget(@NonNull ExecutorService executor, @NonNull Context context, AppWidgetManager awm, int[] appWidgetIds, Account account) {
final SyncManager syncManager = new SyncManager(context);
-
for (int appWidgetId : appWidgetIds) {
- new Thread(() -> {
+ executor.submit(() -> {
try {
// TODO implement
throw new UnsupportedOperationException("Not yet implemented");
} catch (NoSuchElementException e) {
// onUpdate has been triggered before the user finished configuring the widget
}
- }).start();
+ });
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
- updateAppWidget(context, appWidgetManager, appWidgetIds, null);
+ updateAppWidget(executor, context, appWidgetManager, appWidgetIds, null);
}
@Override
@@ -56,10 +60,10 @@ public class FilterWidget extends AppWidgetProvider {
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
if (intent.getExtras() != null) {
- updateAppWidget(context, awm, new int[]{intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)}, account);
+ updateAppWidget(executor, context, awm, new int[]{intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)}, account);
}
} else {
- updateAppWidget(context, awm, awm.getAppWidgetIds(new ComponentName(context, FilterWidget.class)), account);
+ updateAppWidget(executor, context, awm, awm.getAppWidgetIds(new ComponentName(context, FilterWidget.class)), account);
}
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java
index 766948062..b3e4d622b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java
@@ -15,6 +15,8 @@ import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import java.util.NoSuchElementException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Card;
@@ -25,11 +27,13 @@ import it.niedermann.nextcloud.deck.util.DateUtil;
public class SingleCardWidget extends AppWidgetProvider {
+ private final ExecutorService executor = Executors.newCachedThreadPool();
+
void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) {
final SyncManager syncManager = new SyncManager(context);
for (int appWidgetId : appWidgetIds) {
- new Thread(() -> {
+ executor.submit(() -> {
try {
final FullSingleCardWidgetModel fullModel = syncManager.getSingleCardWidgetModelDirectly(appWidgetId);
@@ -106,7 +110,7 @@ public class SingleCardWidget extends AppWidgetProvider {
} catch (NoSuchElementException e) {
// onUpdate has been triggered before the user finished configuring the widget
}
- }).start();
+ });
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidget.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidget.java
index 5b0907ef3..02d426bbb 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidget.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidget.java
@@ -10,6 +10,10 @@ import android.net.Uri;
import android.widget.RemoteViews;
import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
@@ -23,11 +27,12 @@ import static android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE;
public class StackWidget extends AppWidgetProvider {
private static final int PENDING_INTENT_OPEN_APP_RQ = 0;
private static final int PENDING_INTENT_EDIT_CARD_RQ = 1;
+ private final ExecutorService executor = Executors.newCachedThreadPool();
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
- updateAppWidget(context, appWidgetManager, appWidgetIds);
+ updateAppWidget(executor, context, appWidgetManager, appWidgetIds);
}
@Override
@@ -40,10 +45,10 @@ public class StackWidget extends AppWidgetProvider {
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
DeckLog.verbose(ACTION_APPWIDGET_UPDATE, "for", StackWidget.class.getSimpleName(), "with id", appWidgetId, "→ perform update.");
- updateAppWidget(context, awm, new int[]{appWidgetId});
+ updateAppWidget(executor, context, awm, new int[]{appWidgetId});
} else {
DeckLog.verbose(ACTION_APPWIDGET_UPDATE, "→ Triggering update for all widgets of type", StackWidget.class.getSimpleName());
- updateAppWidget(context, awm, awm.getAppWidgetIds(new ComponentName(context, StackWidget.class)));
+ updateAppWidget(executor, context, awm, awm.getAppWidgetIds(new ComponentName(context, StackWidget.class)));
}
}
}
@@ -59,10 +64,10 @@ public class StackWidget extends AppWidgetProvider {
}
}
- private static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) {
+ private static void updateAppWidget(@NonNull ExecutorService executor, @NonNull Context context, AppWidgetManager awm, int[] appWidgetIds) {
final SyncManager syncManager = new SyncManager(context);
for (int appWidgetId : appWidgetIds) {
- new Thread(() -> {
+ executor.submit(() -> {
if (syncManager.filterWidgetExists(appWidgetId)) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_stack);
@@ -94,7 +99,7 @@ public class StackWidget extends AppWidgetProvider {
} else {
DeckLog.warn("Does not yet exist");
}
- }).start();
+ });
}
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidget.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidget.java
index a28f1ef4f..42c7989dd 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidget.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidget.java
@@ -12,6 +12,8 @@ import android.widget.RemoteViews;
import androidx.annotation.NonNull;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import it.niedermann.nextcloud.deck.BuildConfig;
@@ -35,6 +37,7 @@ public class UpcomingWidget extends AppWidgetProvider {
private static final String PENDING_INTENT_ACTION_OPEN = "open";
private static final String PENDING_INTENT_PARAM_LOCAL_CARD_ID = "localCardId";
private static final String PENDING_INTENT_PARAM_ACCOUNT_ID = "accountId";
+ private final ExecutorService executor = Executors.newCachedThreadPool();
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
@@ -42,10 +45,10 @@ public class UpcomingWidget extends AppWidgetProvider {
final SyncManager syncManager = new SyncManager(context);
for (int appWidgetId : appWidgetIds) {
- new Thread(() -> {
+ executor.submit(() -> {
if (syncManager.filterWidgetExists(appWidgetId)) {
DeckLog.warn(UpcomingWidget.class.getSimpleName(), "with id", appWidgetId, "already exists, perform update instead.");
- updateAppWidget(context, appWidgetManager, appWidgetIds);
+ updateAppWidget(executor, context, appWidgetManager, appWidgetIds);
} else {
final List<Account> accountsList = syncManager.readAccountsDirectly();
final FilterWidget config = new FilterWidget(appWidgetId, EWidgetType.UPCOMING_WIDGET);
@@ -59,7 +62,7 @@ public class UpcomingWidget extends AppWidgetProvider {
@Override
public void onResponse(Integer response) {
DeckLog.verbose("Successfully created", UpcomingWidget.class.getSimpleName(), "with id", appWidgetId);
- updateAppWidget(context, appWidgetManager, appWidgetIds);
+ updateAppWidget(executor, context, appWidgetManager, appWidgetIds);
}
@Override
@@ -70,7 +73,7 @@ public class UpcomingWidget extends AppWidgetProvider {
}
});
}
- }).start();
+ });
}
}
@@ -84,17 +87,17 @@ public class UpcomingWidget extends AppWidgetProvider {
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
DeckLog.verbose(ACTION_APPWIDGET_UPDATE, "for", UpcomingWidget.class.getSimpleName(), "with id", appWidgetId, "→ perform update.");
- updateAppWidget(context, awm, new int[]{appWidgetId});
+ updateAppWidget(executor, context, awm, new int[]{appWidgetId});
} else {
DeckLog.verbose(ACTION_APPWIDGET_UPDATE, "→ Triggering update for all widgets of type", UpcomingWidget.class.getSimpleName());
- updateAppWidget(context, awm, awm.getAppWidgetIds(new ComponentName(context, UpcomingWidget.class)));
+ updateAppWidget(executor, context, awm, awm.getAppWidgetIds(new ComponentName(context, UpcomingWidget.class)));
}
} else if (PENDING_INTENT_ACTION_EDIT.equals(intent.getAction())) {
if (intent.hasExtra(PENDING_INTENT_PARAM_ACCOUNT_ID) && intent.hasExtra(PENDING_INTENT_PARAM_LOCAL_CARD_ID)) {
- new Thread(() -> {
+ executor.submit(() -> {
final SyncManager syncManager = new SyncManager(context);
context.startActivity(EditActivity.createEditCardIntent(context, syncManager.readAccountDirectly(intent.getLongExtra(PENDING_INTENT_PARAM_ACCOUNT_ID, -1)), syncManager.getBoardLocalIdByLocalCardIdDirectly(intent.getLongExtra(PENDING_INTENT_PARAM_LOCAL_CARD_ID, -1)), intent.getLongExtra(PENDING_INTENT_PARAM_LOCAL_CARD_ID, -1)));
- }).start();
+ });
} else {
DeckLog.error(PENDING_INTENT_PARAM_ACCOUNT_ID, "and", PENDING_INTENT_PARAM_LOCAL_CARD_ID, "must be provided for action", PENDING_INTENT_ACTION_EDIT);
}
@@ -114,9 +117,9 @@ public class UpcomingWidget extends AppWidgetProvider {
}
}
- private static void updateAppWidget(@NonNull Context context, @NonNull AppWidgetManager awm, int[] appWidgetIds) {
+ private static void updateAppWidget(@NonNull ExecutorService executor, @NonNull Context context, @NonNull AppWidgetManager awm, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
- new Thread(() -> {
+ executor.submit(() -> {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_upcoming);
final Intent serviceIntent = new Intent(context, UpcomingWidgetService.class);
@@ -131,7 +134,7 @@ public class UpcomingWidget extends AppWidgetProvider {
awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.upcoming_widget_lv);
awm.updateAppWidget(appWidgetId, views);
- }).start();
+ });
}
}
diff --git a/app/src/main/res/layout/activity_exception.xml b/app/src/main/res/layout/activity_exception.xml
index 932fa7bf2..9d7420d1f 100644
--- a/app/src/main/res/layout/activity_exception.xml
+++ b/app/src/main/res/layout/activity_exception.xml
@@ -28,7 +28,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:hint="An error appeared."
+ android:hint="@string/hint_error_appeared"
app:drawableEndCompat="@drawable/ic_bug_report_black_24dp"
tools:ignore="HardcodedText" />
@@ -111,4 +111,4 @@
app:backgroundTint="@color/defaultBrand" />
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f9acf8b6b..8cacf2776 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,6 +3,7 @@
<string name="app_name_short" translatable="false">Deck</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
+ <string name="hint_search_deck">Search deck</string>
<string name="simple_boards">Boards</string>
<string name="simple_add">Add</string>
@@ -34,6 +35,7 @@
<string name="simple_copied">Copied</string>
<string name="simple_archive">Archive</string>
<string name="simple_unassigned">Unassigned</string>
+ <string name="hint_error_appeared">An error appeared</string>
<string name="edit_board">Edit board</string>
<string name="archive_board">Archive board</string>
@@ -71,6 +73,10 @@
<string name="about_license_tab_title">License</string>
<string name="seconds_ago">seconds ago</string>
<string name="edit">Edit</string>
+ <!-- After specifying the title of a new card, save it and then directly start it in edit mode -->
+ <string name="save_and_edit">@string/edit</string>
+ <!-- After specifying the title of a new card, save it and return to the list of cards -->
+ <string name="save_and_close">@string/simple_save</string>
<string name="label_labels">Select Tags</string>
<string name="label_description">Description</string>
<string name="hint_assign_people">Assign users</string>
@@ -174,7 +180,7 @@
<string name="hours_6">6 hours</string>
<string name="action_card_move">Move card</string>
<string name="action_card_move_title">Move %1$s</string>
- <string name="title_is_mandatory">Title is mandatory</string>
+ <string name="title_is_mandatory">Title is required</string>
<string name="provide_at_least_a_title_or_description">Provide at least a title or description</string>
<string name="welcome_text">Welcome to %1$s</string>
<string name="maintenance_mode_explanation">The server %1$s is currently in maintenance mode. Please contact your administrator or try later again.</string>
@@ -341,6 +347,6 @@
<string name="account_imported">Account imported</string>
<string name="simple_search">Search</string>
<!-- Label for a title input field that is required to be filled out -->
- <string name="title_mandatory">Title (mandatory)</string>
+ <string name="title_mandatory">Title (required)</string>
<string name="saving_new_card">Saving new card…</string>
</resources>
diff --git a/app/src/main/res/xml/searchable.xml b/app/src/main/res/xml/searchable.xml
index 47128864a..cbef62706 100644
--- a/app/src/main/res/xml/searchable.xml
+++ b/app/src/main/res/xml/searchable.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
- android:hint="Search deck"
- android:label="@string/app_name"></searchable> \ No newline at end of file
+ android:hint="@string/hint_search_deck"
+ android:label="@string/app_name"></searchable>